# OAuth2 and OIDC Authentication

This guide will explain how to configure an SSO provider using [OpenID Connect](http://openid.net/connect/) (also known as OIDC) to issue Teleport credentials to specific groups of users. When used in combination with role-based access control (RBAC), OIDC allows Teleport administrators to define policies like:

- Only members of the "DBA" group can connect to PostgreSQL databases.
- Developers must never SSH into production servers.

## How it works

You can register your Teleport cluster as an application with your SSO provider, then create an **authentication connector** resource that provides Teleport with information about your application. When a user signs in to Teleport, your SSO provider executes its own authentication flow, then sends an HTTP request to your Teleport cluster to indicate that authentication has completed.

Teleport authenticates users to your infrastructure by issuing short-lived certificates. After a user completes an SSO authentication flow, Teleport issues short-lived TLS and SSH certificates to the user. Teleport also creates a temporary user on the Auth Service backend.

Teleport roles are encoded in the user's certificates. To assign Teleport roles to the user, the Auth Service inspects the **role mapping** within the authentication connector, which associates user data on your SSO provider with the names of one or more Teleport roles.

## Prerequisites

- Admin access to the SSO/IdP being integrated with users assigned to groups/roles.
- Teleport role with permission to maintain `oidc` resources. This permission is available in the default `editor` role.

* A running Teleport Enterprise cluster. If you want to get started with Teleport, [sign up](https://goteleport.com/signup) for a free trial or [set up a demo environment](https://goteleport.com/docs/get-started/deploy-community.md).

* The `tctl` and `tsh` clients.

  Installing `tctl` and `tsh` clients

  1. Determine the version of your Teleport cluster. The `tctl` and `tsh` clients must be at most one major version behind your Teleport cluster version. Send a GET request to the Proxy Service at `/v1/webapi/find` and use a JSON query tool to obtain your cluster version. Replace teleport.example.com:443 with the web address of your Teleport Proxy Service:

     ```
     $ TELEPORT_DOMAIN=teleport.example.com:443
     $ TELEPORT_VERSION="$(curl -s https://$TELEPORT_DOMAIN/v1/webapi/find | jq -r '.server_version')"
     ```

  2. Follow the instructions for your platform to install `tctl` and `tsh` clients:

     **Mac**

     Download the signed macOS .pkg installer for Teleport, which includes the `tctl` and `tsh` clients:

     ```
     $ curl -O https://cdn.teleport.dev/teleport-${TELEPORT_VERSION?}.pkg
     ```

     In Finder double-click the `pkg` file to begin installation.

     ---

     DANGER

     Using Homebrew to install Teleport is not supported. The Teleport package in Homebrew is not maintained by Teleport and we can't guarantee its reliability or security.

     ---

     **Windows - Powershell**

     ```
     $ curl.exe -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION?}-windows-amd64-bin.zip
     Unzip the archive and move the `tctl` and `tsh` clients to your %PATH%
     NOTE: Do not place the `tctl` and `tsh` clients in the System32 directory, as this can cause issues when using WinSCP.
     Use %SystemRoot% (C:\Windows) or %USERPROFILE% (C:\Users\<username>) instead.
     ```

     **Linux**

     All of the Teleport binaries in Linux installations include the `tctl` and `tsh` clients. For more options (including RPM/DEB packages and downloads for i386/ARM/ARM64) see our [installation page](https://goteleport.com/docs/installation.md).

     ```
     $ curl -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gz
     $ tar -xzf teleport-v${TELEPORT_VERSION?}-linux-amd64-bin.tar.gz
     $ cd teleport
     $ sudo ./install
     Teleport binaries have been copied to /usr/local/bin
     ```

- To check that you can connect to your Teleport cluster, sign in with `tsh login`, then verify that you can run `tctl` commands using your current credentials. For example, run the following command, assigning teleport.example.com to the domain name of the Teleport Proxy Service in your cluster and email\@example.com to your Teleport username:
  ```
  $ tsh login --proxy=teleport.example.com --user=email@example.com
  $ tctl status
  Cluster  teleport.example.com
  Version  19.0.0-dev
  CA pin   sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678
  ```
  If you can connect to the cluster and run the `tctl status` command, you can use your current credentials to run subsequent `tctl` commands from your workstation. If you host your own Teleport cluster, you can also run `tctl` commands on the computer that hosts the Teleport Auth Service for full permissions.

## Step 1/3. Configure your OIDC provider

Register Teleport with the external identity provider you will be using and obtain your `client_id` and `client_secret`. This information should be documented on the identity providers website. Here are a few links:

- [Auth0 Client Configuration](https://auth0.com/docs/applications)
- [Google Identity Platform](https://developers.google.com/identity/protocols/OpenIDConnect)
- [Keycloak Client Registration](https://www.keycloak.org/docs/latest/securing_apps/index.html#_client_registration)

---

GOOGLE WORKSPACE

For Google Workspace, see [Teleport Authentication with Google Workspace](https://goteleport.com/docs/zero-trust-access/sso/integrate-idp/google-workspace.md)

---

Save the relevant information from your identity provider. To make following this guide easier, you can add the Client ID here and it will be included in the example commands below:

Client ID: CLIENT-ID

### Select an OIDC redirect URL

OIDC relies on HTTP redirects to return control back to Teleport after authentication is complete. The redirect URL must be selected by a Teleport administrator in advance.

The redirect URL for OIDC authentication in Teleport is  mytenant.teleport.sh:443`/v1/webapi/oidc/callback`. Replace mytenant.teleport.sh:443 with your Teleport Cloud tenant or Proxy Service address. If you have a self-hosted cluster with multiple public addresses for the Teleport Proxy Service (the value of `proxy_service.public_addr` in the Teleport configuration file), ensure that this address points to the first one listed.

## Step 2/3. Connect your OIDC provider to Teleport

In this section, you will create an authentication connector that provides Teleport with the information it needs to exchange OIDC messages with your IdP and issue certificates to users.

### Assign a role mapping

When a user authenticates to Teleport, the Teleport Auth Service issues SSH and TLS certificates to the user that contain the user's Teleport roles.

For SSO authentication connectors, the Auth Service determines which roles to encode in the certificate by reading the authentication connector's **role mapping**. The role mapping indicates which Teleport roles to assign based on data that your identity provider stores about the user.

When you configure an authentication connector using the `tctl` CLI, a role mapping takes the following format:

```
<claim_name>,<claim_value>,<teleport_role_1>,<teleport_role_2>,...,<teleport_role_n>

```

For example, the following role mapping means that any user with the claim `groups` with the value `admins` receives the Teleport roles `auditor` and `editor`:

```
groups,admins,auditor,editor

```

For the purpose of this guide, assign two separate role mappings:

- A more permissive role mapping: mapping\_1
- A more restrictive role mapping: mapping\_2

### Configure an OIDC connector

The next step is to add an OIDC connector to Teleport. The connectors are created, tested, and added or removed using `tctl` [resource commands](https://goteleport.com/docs/reference/infrastructure-as-code/teleport-resources.md) or the Teleport Web UI.

On your workstation, create a file called `client-secret.txt` consisting only of your client secret.

To create a new connector, use `tctl sso configure`. The following example creates a connector resource file in YAML format named `oidc-connector.yaml`:

```
$ tctl sso configure oidc --name <CONNECTOR-NAME> \
  --issuer-url <PATH-TO-PROVIDER> \
  --id CLIENT-ID \
  --secret $(cat client-secret.txt) \
  --claims-to-roles mapping_1 \
  --claims-to-roles mapping_2 > oidc-connector.yaml
```

- `--name`: Usually the name of the IdP, this is how the connector will be identified in Teleport.
- `--issuer-url`: This is the base path to the IdP's OIDC configuration endpoint, excluding `.well-known/openid-configuration`. If, for example, the endpoint is `https://example.com/.well-known/openid-configuration`, you would use `https://example.com`.
- `--id`: The client ID as defined in the IdP. Depending on your identity provider this may be something you can define (for example, `teleport`), or may be an assigned string.
- `--secret`: The client token/secret provided by the IdP to authorize this client.

For more information on these and all available flags, see the [tctl sso configure oidc](https://goteleport.com/docs/reference/cli/tctl.md) section of the Teleport CLI Reference page.

The file created should look like the example below:

```
kind: oidc
metadata:
  name: oidc_connector
spec:
  claims_to_roles:
  - claim: groups
    roles:
    - access
    value: devs
  - claim: groups
    roles:
    - auditor
    - editor
    value: admins
  client_id: <CLIENT-NAME>
  client_secret: <CLIENT-SECRET>
  issuer_url: https://idp.example.com/
  redirect_url: https://mytenant.teleport.sh:443/v1/webapi/oidc/callback
  max_age: 24h
  # pkce_mode determines if the OIDC authentication flow should include PKCE code verifiers. Options or `enabled`, `disabled`, and `` (defaults to disabled)
  pkce_mode: "enabled"
  client_redirect_settings:
    # a list of hostnames allowed for HTTPS client redirect URLs
    # can be a regex pattern
    allowed_https_hostnames:
      - remote.machine
      - '*.app.github.dev'
      - '^\d+-[a-zA-Z0-9]+\.foo.internal$'
    # a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
    insecure_allowed_cidr_ranges:
      - '192.168.1.0/24'
      - '2001:db8::/96'
version: v3


```

Details

Practical Example: Keycloak

The following example was generated using Keycloak as the identity provider. Keycloak is being served at `keycloak.example.com`, and the Teleport Proxy Service is listening at `teleport.example.com`. In Keycloak, the client is named `teleport`. Under the `teleport-dedicated` client scope, we've added the "Group Membership" mapper:

```
kind: oidc
metadata:
  name: keycloak
spec:
  claims_to_roles:
  - claim: groups
    roles:
    - access
    value: /devs
  - claim: groups
    roles:
    - auditor
    - editor
    value: /admins
  client_id: teleport
  client_secret: abc123...
  issuer_url: https://keycloak.example.com/realms/master
  redirect_url: https://teleport.example.com:443/v1/webapi/oidc/callback
version: v3


```

Changing the callback address

The callback address can be changed if calling back to a remote machine instead of the local machine is required:

```
--bind-addr sets the host and port tsh will listen on, and --callback changes
what link is displayed to the user
$ tsh login --proxy=proxy.example.com --auth=github --bind-addr=localhost:1234 --callback https://remote.machine:1234
```

For this to work the hostname or CIDR of the remote machine that will be used for the callback will need to be allowed via your auth connector's `client_redirect_settings`:

```
kind: oidc
metadata:
  name: example-connector
spec:
  client_redirect_settings:
    # a list of hostnames allowed for HTTPS client redirect URLs
    # can be a regex pattern
    allowed_https_hostnames:
      - remote.machine
      - '*.app.github.dev'
      - '^\d+-[a-zA-Z0-9]+\.foo.internal$'
    # a list of CIDRs allowed for HTTP or HTTPS client redirect URLs
    insecure_allowed_cidr_ranges:
      - '192.168.1.0/24'
      - '2001:db8::/96'

```

### Optional: ACR Values

Teleport supports sending Authentication Context Class Reference (ACR) values when obtaining an authorization code from an OIDC provider. By default ACR values are not set. However, if the `acr_values` field is set, Teleport expects to receive the same value in the `acr` claim, otherwise it will consider the callback invalid.

In addition, Teleport supports OIDC provider specific ACR value processing which can be enabled by setting the `provider` field in OIDC configuration. At the moment, the only build-in support is for NetIQ.

A example of using ACR values and provider specific processing is below:

```
# example connector which uses ACR values
kind: oidc
version: v2
metadata:
  name: "oidc-connector"
spec:
  issuer_url: "https://oidc.example.com"
  client_id: "xxxxxxxxxxxxxxxxxxxxxxx.example.com"
  client_secret: "zzzzzzzzzzzzzzzzzzzzzzzz"
  redirect_url: "https://mytenant.teleport.sh/v1/webapi/oidc/callback"
  display: "Login with Example"
  acr_values: "foo/bar"
  provider: netiq
  scope: [ "group" ]
  claims_to_roles:
     - claim: "group"
       value: "editor"
       roles: [ "editor" ]
     - claim: "group"
       value: "user"
       roles: [ "access" ]

```

### Optional: Max age

The `max_age` field controls the maximum age of users' sessions before they will be forced to reauthenticate. By default `max_age` is unset, meaning once a user authenticates using OIDC they will not have to reauthenticate unless the configured OIDC provider forces them to. This can be set to a duration of time to force users to reauthenticate more often. If `max_age` is set to zero seconds, users will be forced to reauthenticate with their OIDC provider every time they authenticate with Teleport.

Note that the specified duration must be in whole seconds. `24h` works because that's the same as `1440s`, but `60s500ms` would not be allowed as that is 60.5 seconds.

```
# Extra parts of OIDC yaml have been removed.
spec:
  max_age: 24h

```

Note that not all OIDC providers support setting `max_age`. Google and GitLab are both known not to support it and authentication with those providers will not work when the `max_age` field is set.

### Optional: Prompt

Set the Authorization Server prompt for the End-User for reauthentication and consent per the OIDC protocol. If no `prompt` value is set, Teleport uses `select_account` as default.

```
# Extra parts of OIDC yaml have been removed.
spec:
  # Valid values as defined from https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
  # none: The Authorization Server must not display any authentication or consent user interface pages.
  # select_account: The Authorization Server should prompt the End-User to select a user account.
  # login: The Authorization Server should prompt the End-User for reauthentication.
  # consent: The Authorization Server should prompt the End-User for consent before returning information to the Client.
  prompt: 'login'

```

### Optional: Redirect URL and Timeout

The redirect URL must be accessible by all user, optional redirect timeout.

```
# Extra parts of OIDC yaml have been removed.
spec:
  redirect_url: https://<cluster-url>.example.com:3080/v1/webapi/oidc/callback
  # Optional Redirect Timeout.
  # redirect_timeout: 90s

```

### Optional: Disable email verification

By default, Teleport validates the `email_verified` claim, and users who attempt to sign in without a verified email address are prevented from doing so:

```
ERROR: SSO flow failed.
identity provider callback failed with error: OIDC provider did not verify email.
        email not verified by OIDC provider

```

For testing and other purposes, you can opt out of this behavior by enabling `allow_unverified_email` in your OIDC connector. This option weakens the overall security of the system, so we do not recommend enabling it.

```
kind: oidc
version: v2
metadata:
  name: connector
spec:
  allow_unverified_email: true

```

### Optional: Specify a claim to use as the username

By default, Teleport expects an `email` claim to be present in the OIDC claim. The value from the `email` claim is used as a username in Teleport. If you wish to use another claim to configure username, you can override the default expected `email` claim with the `username_claim` field in the auth connector spec.

The example below shows configuring the `username_claim` field with `preferred_username` value. This will configure Teleport to query `preferred_username` claim instead of the `email` claim.:

```
kind: oidc
metadata:
  # ...
spec:
  # ...
  username_claim: preferred_username

```

---

USERNAME CLAIM

Ensure that the claim value you use to configure `username_claim` is a uniquely identifiable value for the user.

---

### Optional: Request object mode

Teleport supports the ability to send authorization request parameters in a JSON Web Token (JWT), referred to as "request objects", following RFC 9101. Presently, Teleport only supports signed request objects sent by value. This option necessitates that the IdP be provided with, or configured to discover, Teleport's JSON Web Key Sets (JWKS) used for OIDC IdP integration in order to verify request object signatures. This JWKS can be found at the `/.well-known/jwks-oidc` path of the Web API.

Additionally, the public key to be used for verifying request object signatures can be found via `tctl`.

```
$ tctl get cert_authority/oidc_idp/$CLUSTER_NAME --format=json | jq -r .[].spec.active_keys.jwt[].public_key
```

By default, `request_object_mode` is unset, meaning authorization request parameters will be sent in the query string of the authorization endpoint.

```
kind: oidc
version: v2
metadata:
  name: connector
spec:
  # Use signed request objects when making authorization requests to the IdP.
  request_object_mode: signed

```

Request objects are also supported for MFA checks. If `request_object_mode` is not explicitly set on the MFA client, the login client's request object mode will be used by default. If desired, you can explicitly configure the MFA client to use a separate request object mode.

```
kind: oidc
version: v2
metadata:
  name: connector
spec:
  client_id: teleport_login
  client_secret: abc123...
  request_object_mode: none
  mfa:
    client_id: teleport_mfa
    client_secret: mfa123...
    request_object_mode: signed

```

Note: Support for request objects is available in Teleport Enterprise versions `17.7.2` or later and `18.1.6` or later.

### Test the connector

Before applying the connector to your cluster, you can test that it's configured correctly:

```
$ cat oidc-connector.yaml | tctl sso test
```

This should open up your web browser and attempt to log you in to the Teleport cluster through your IdP. If it fails, review the output of this command for troubleshooting details.

---

TIP

The "\[OIDC] Claims" section of the CLI output provides all the details of your user provided by the IdP. This is a good starting point while troubleshooting errors like `Failed to calculate user attributes.`

---

### Create the connector

After your tests are successful, create the connector:

```
$ tctl create -f oidc-connector.yaml
```

## Step 3/3. Enable default OIDC authentication

Edit your cluster authentication preferences so you can make the authentication connector you configured in this guide the default authentication method for your Teleport cluster.

Open the Teleport Web UI. From the left sidebar, navigate to **Zero Trust Access** > **Auth Connectors**. Find the connector you would like to make the default and, from its three-dot menu, select **Set as default**.

If you are managing your Teleport resources as configuration files, you can choose a default authentication connector using a dynamic resource. In this case, use `tctl` to edit the `cluster_auth_preference` value:

```
$ tctl edit cluster_auth_preference
```

Set the value of `spec.type` to `oidc`:

```
kind: cluster_auth_preference
metadata:
  ...
  name: cluster-auth-preference
spec:
  ...
  type: oidc
  ...
version: v2

```

After you save and exit the editor, `tctl` will update the resource:

```
cluster auth preference has been updated

```

Additional ways to edit cluster auth preferences

The cluster auth preference is available as a Teleport Terraform provider resource. Find a list of configuration options in the [Cluster Auth Preferences Resource Reference](https://goteleport.com/docs/reference/infrastructure-as-code/teleport-resources/cluster-auth-preferences.md).

If you self-host Teleport, you can edit your Teleport Auth Service configuration file to include the following:

```
# Snippet from /etc/teleport.yaml
auth_service:
  authentication:
    type: oidc

```

If you need to log in again before configuring your identity provider, use the flag `--auth=local`.

## Next steps

Now that you have connected Teleport to your identity provider, you can customize the way Teleport includes IdP data in Teleport roles.

With **role templates**, you can include user data from your IdP directly in Teleport roles. If you use the `external` template variable in the value of a role field, Teleport passes that value from your IdP. In this example, all of the role options you can use for allowing users to assume certain principals on remote systems come from your IdP:

```
kind: role
version: v7
metadata:
  name: sso-users
spec:
  allow:
    logins: ['{{external.logins}}']
    aws_role_arns: ['{{external.aws_role_arns}}']
    azure_identities: ['{{external.azure_identities}}']
    db_names: ['{{external.db_names}}']
    db_roles: ['{{external.db_roles}}']
    db_users: ['{{external.db_users}}']
    desktop_groups: ['{{external.desktop_groups}}']
    gcp_service_accounts: ['{{external.gcp_service_accounts}}']
    host_groups: ['{{external.host_groups}}']
    host_sudoers: ['{{external.host_sudoers}}']
    kubernetes_groups: ['{{external.kubernetes_groups}}']
    kubernetes_users: ['{{external.kubernetes_users}}']
    windows_desktop_logins: ['{{external.windows_desktop_logins}}']

```

For more information on using the `external` template variable, see [Role Templates](https://goteleport.com/docs/zero-trust-access/rbac-get-started/role-templates.md).

For an explanation of the fields listed above, see the [Role Reference](https://goteleport.com/docs/reference/access-controls/roles.md).

If you need to transform your IdP user data before you include it in Teleport roles, you can do so using **Login Rules**. Login Rules allow you to include external traits within Teleport roles even if your IdP provides user data in a different format than the one expected by Teleport. Read more about [Login Rules](https://goteleport.com/docs/zero-trust-access/sso/login-rules.md).

## Troubleshooting

Troubleshooting SSO configuration can be challenging. Usually a Teleport administrator must be able to:

- Be able to see what SAML/OIDC claims and values are getting exported and passed by the SSO provider to Teleport.
- Be able to see how Teleport maps the received claims to role mappings as defined in the connector.
- For self-hosted Teleport Enterprise clusters, ensure that HTTP/TLS certificates are configured properly for both the Teleport Proxy Service and the SSO provider.

If something is not working, we recommend to:

- Double-check the host names, tokens and TCP ports in a connector definition.

### Using the Web UI

If you get "access denied" or other login errors, the number one place to check is the Audit Log. To view the recording, select **Audit** in the Teleport Web UI, then click **Session Recordings** in the menu.

![Audit Log Entry for SSO Login error](/docs/assets/images/teleportauditlogssofailed-4e41f7109e748750a157651c2f702dac.png)

Example of a user being denied because the role `clusteradmin` wasn't set up:

```
{
  "code": "T1001W",
  "error": "role clusteradmin is not found",
  "event": "user.login",
  "message": "Failed to calculate user attributes.\n\trole clusteradmin is not found",
  "method": "oidc",
  "success": false,
  "time": "2024-11-07T15:41:25.584Z",
  "uid": "71e46f17-d611-48bb-bf5e-effd90016c13"
}

```

### Teleport does not show the expected Nodes

When the Teleport Auth Service receives a request to list Teleport-connected resources (e.g., to display resources in the Web UI or via `tsh ls`), it only returns the resources that the current user is authorized to view.

For each resource in the user's Teleport cluster, the Auth Service applies the following checks in order and, if one check fails, hides the resource from the user:

- None of the user's roles contain a `deny` rule that matches the resource's labels.
- At least one of the user's roles contains an `allow` rule that matches the resource's labels.

If you are not seeing resources when expected, make sure that your user's roles include the appropriate `allow` and `deny` rules as documented in the [Access Controls Reference](https://goteleport.com/docs/reference/access-controls/roles.md).

When configuring SSO, ensure that the identity provider is populating each user's traits correctly. For a user to see a Node in Teleport, the result of populating a template variable in a role's `allow.logins` must match at least one of a user's `traits.logins`.

In this example a user will have usernames `ubuntu`, `debian` and usernames from the SSO trait `logins` for Nodes that have a `env: dev` label. If the SSO trait username is `bob` then the usernames would include `ubuntu`, `debian`, and `bob`.

```
kind: role
metadata:
  name: example-role
spec:
  allow:
    logins: ['{{external.logins}}', ubuntu, debian]
    node_labels:
      'env': 'dev'
version: v5

```

### Single sign-on fails with OIDC

When encountering the error message **"Failed to verify JWT: oidc: unable to verify JWT signature: no matching keys"**, it typically indicates a discrepancy between the algorithm used to sign the JWT token and the algorithm(s) supported by the JSON Web Key Set (JWKS). Specifically, the token might be signed with one algorithm, e.g., HS256, while the JWKS only lists keys for a different algorithm. e.g., RS256. This issue predominantly arises when using identity providers that offer extremely low-level functionality.

Here are some things to check:

- Verify the JWT header specifies the correct signing algorithm. This should match one of the algorithms listed in the keys section of the JWKS endpoint response.
- Ensure the JWKS endpoint is returning all relevant public keys. Sometimes key rotation can cause valid keys to be omitted.

To resolve the issue, align the JWT algorithm header with a supported algorithm in the JWKS. Rotate keys if necessary. Verify the JWKS only publishes the active public keys. With proper configuration, the signature should validate successfully.
