# Teleport Authentication with Microsoft Entra ID (OIDC)

This guide shows how to configure Microsoft Entra ID (formerly Azure AD) as an OIDC identity provider for Teleport. With this configuration, users can access Teleport by authenticating with Entra ID, and be granted with permissions to access or manage resource in Teleport based on their group membership in Entra ID.

A SAML-based Entra ID IdP configuration version is available in this [guide](https://goteleport.com/docs/zero-trust-access/sso/integrate-idp/entra-id.md).

## How it works

In the Microsoft Entra ID tenant, you will create an enterprise application and set it up as an OIDC identity provider for Teleport. You will also configure the `groups` claim, which will be included in the user's OIDC ID Token.

In Teleport, you will create an Auth Connector resource and set up Microsoft Entra ID as an OIDC identity provider. You will also map Entra ID groups to Teleport roles.

When a user signs in to Teleport by authenticating with their Microsoft Entra ID account, Teleport first creates a temporary user account with Teleport roles mapped from `groups` claim and traits. Traits are user attributes (key-value format). Any claim that is present in the OIDC ID Token is preserved as user traits. Teleport then starts a new session for the user by issuing a pair of short-lived TLS and SSH certificates. These certificates encodes user's identity, roles and traits, which are evaluated to grant access in Teleport.

To demonstrate Microsoft Entra ID group to Teleport role mapping, we will have two user groups created in the Microsoft Entra ID tenant:

1. `ad-app-support`. We will map this group to Teleport preset `requester` role. The preset `requester` role grants permission to request access to resources that are enrolled in Teleport.
2. `ad-app-admin`. We will map this group to Teleport preset `reviewer` and `editor` roles. The preset `editor` role grants permission to manage resource in Teleport. The preset `reviewer` grants permission to review access to resources in Teleport.

Instead of creating new groups, you may use an existing Microsoft Entra ID groups to follow this guide.

## Prerequisites

- Permissions to create an enterprise application, configure and grant Microsoft Graph API permissions and manage groups in the Microsoft Entra ID tenant.
- Teleport user with a preset `editor` role or an equivalent role that allows you to read and write Auth Connectors, users and roles.
- 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  18.7.3
  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 Microsoft Entra ID

### Create groups

---

NEW GROUP

You may skip this step if you are using existing Microsoft Entra ID groups to follow this guide.

---

In the Azure portal, select the "Groups" menu which is available under the "Azure services" menu.

From the "Groups" UI, click the "New group" button to create a new user group named `ad-app-admin`.

![Entra ID create group](/docs/assets/images/entra-id-create-group-2a327cb2756319143037dea51c3a7fc7.png)

You may add desired users to this group. Repeat this step to create another group named `ad-app-support`.

### Create an enterprise application

In the Azure Portal, from the “Azure services” menu, select “Enterprise applications”. Click on the `+ New Application` button, then click `+ Create your own application` button. Enter a name for your application and create the application.

![Entra ID create application](/docs/assets/images/entra-id-create-application-6d615e9576405444972bedc0ec34960a.png)

### Assign groups

In the Azure Portal, in the enterprise application UI, select the "Users and groups" menu, which can be located under the "Manage" menu.

In the "Users and groups" UI, click `+Add user/group` button.

Now assign the two groups you created in Step 1. If you are following this guide with an existing user groups, select those groups in this step.

![Entra ID assign](/docs/assets/images/entra-id-assign-group-d005c4d1f3c0c6274a0f4195e1a13e57.png)

### Configure OIDC

Configuring OIDC involves setting up a redirect URI for the relying party (Teleport in this case), setting up the OIDC claims and a client credential.

These OIDC configurations are available in the "App registrations" service.

In the Azure Portal, from the “Azure services” menu, select "App registrations". In the "App registrations" UI, search and select the enterprise application you created while following this guide.

In the "App registrations" UI for the enterprise application, from the “Manage” menu, select the “Authentication” menu. In this configuration UI, under the "Platform configurations" section, click `+ Add a platform` button.

OIDC redirect URI for Teleport should point to the OIDC callback endpoint, which has the following URI format: `https://example.teleport.sh/v1/webapi/oidc/callback`.

Enter the Teleport Proxy Service hostname of your Teleport cluster below to generate the OIDC callback URI. Then copy and paste the value in the Azure Portal to configure OIDC redirect URI.

```
https://example.teleport.sh/v1/webapi/oidc/callback
```

![Entra ID OIDC redirect URI](/docs/assets/images/entra-id-oidc-redirect-uri-56068c819444273720f857aacf1dba14.png)

Save the configuration once the redirect URI is configured.

### Set up client credentials

Teleport uses the OIDC authorization code flow to exchange an OIDC authorization code for the user's ID Token. To exchange the ID Token, a client credential must be set up for Teleport.

In the "App registrations" UI for the enterprise application, from the "Manage" menu, select "Certificates & secrets". Now select the "Client secrets" tab and click on the `+ New client secret` button. Create a new client secret.

![Entra ID OIDC client credential](/docs/assets/images/entra-id-oidc-client-credential-a757f0acb36bf096931ea6a78d756f66.png)

Once the secret is created, copy the value and save it in your working environment:

```
$ echo 'secret value copied from entra id' > /tmp/client-secret
```

### Configure groups claims

You need to configure `groups` claim to configure access in Teleport.

In the "App registrations" UI for the enterprise application, from the "Manage" menu, select "Token configuration".

In the "Token configuration" UI, click `+ Add groups claim` button.

Select group type you wish to include in user's OIDC `groups` claim.

The reference image below shows that a "Security groups" type is selected.

![Entra ID OIDC groups claim](/docs/assets/images/entra-id-oidc-group-claim-ff480af427e5ad88ff04fac47b4ef01d.png)

You may configure other claims as desired. All the claims issued by Microsoft Entra ID are preserved as user's traits in the user resource.

### (Optional) Groups overage claim

If user's group membership exceeds the 200 group limit, Microsoft Entra ID issues a groups overage claim instead of the expected `groups` claim. The groups overage claim contains an Azure AD Graph API link, which indicates that the user's group membership is to be queried from the Microsoft Graph API.

If your user's group membership do not exceed the group limit, you can skip this step. Otherwise, you will need to grant Teleport with a Microsoft Graph API permission so it can retrieve user's group membership using the Microsoft Graph API.

To query user's group membership, Teleport requires `User.ReadBasic.All` permission. To grant this permission, in the "App registrations" UI for the enterprise application, from the "Manage" menu, select "API permissions".

Next, click `+ Add a permission` button and then select "Microsoft APIs > Microsoft Graph > Application permissions". In the permission filter search bar, type `User.ReadBasic.All`.

Select the permission and add it to the application by clicking on the `Add permissions` button.

![Entra ID OIDC graph permission](/docs/assets/images/entra-id-oidc-graph-permission-db1e401237318f387617dce33a63b61c.png)

Once you add the permission, you will need to grant an admin consent.

In the same "API permissions" UI, click the `Grant admin consent` button.

A consent confirmation prompt will appear, click "Yes" to grant the consent.

The Graph API permission to fetch user's group membership is now configured. Should the user's group membership exceed 200 groups, Teleport will follow through the groups overage claim issued by Entra ID and fetch user's groups detail using the Microsoft Graph API.

## 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 Microsoft Entra ID 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

Note that the Entra ID `groups` claim includes group's object ID. As such, you will need to map groups by using groups object ID. Update the `groups` value in mapping\_1 to the object ID of `ad-app-admin` and mapping\_2 to the object ID of `ad-app-support`.

### Create an OIDC connector

Before creating the Auth Connector resource, its useful to first generate the configuration spec and test the configuration.

The Auth Connector spec can be configured by using the `tctl sso configure` command. We will show you how to run the command with the following flags:

- `--name`: Teleport resource name for the Microsoft Entra ID Auth Connector.
- `--display`: Display name for the Microsoft Entra ID Auth Connector
- `--issuer-url`: Microsoft Entra ID OIDC issuer URL. You need your Microsoft Entra ID tenant ID to configure this URL. Assign it to Entra ID tenant ID.
- `--id`: The application (client) ID of the enterprise application you created in Step 2. This value can be copied from the "Overview" section of the enterprise application in the Azure Portal. Assign it to Enterprise application client ID.
- `--secret`: The client secret we created earlier.

```
$ tctl sso configure oidc --name "entra-id" \
  --display "Entra ID" \
  --issuer-url https://login.microsoftonline.com/Entra ID tenant ID/v2.0 \
  --id Enterprise application client ID \
  --secret $(cat /tmp/client-secret) \
  --claims-to-roles groups,mapping_1 \
  --claims-to-roles groups,mapping_2 \
  --scope openid \
  --scope email \
  --scope profile > entraid-oidc-connector.yaml
```

Example YAML Auth Connector resource file created by the `tctl sso configure` command

```
kind: oidc
metadata:
  name: entra-id
spec:
  claims_to_roles:
  - claim: groups
    roles:
    - editor
    - reviewer
    value: da770259-8007-42da-a9c2-3b366a88bc1c
  - claim: groups
    roles:
    - requester
    value: ed5763df-9465-45e8-b10b-06a8979b072e
  client_id: d40666f7-3352-43e8-a8ad-b75e7a0a7be3
  client_secret: example-secret-value
  display: Entra ID
  issuer_url: https://login.microsoftonline.com/0297d2f3-62c3-4598-aaa1-2104929ba73c/v2.0
  redirect_url: https://example.teleport.sh:443/v1/webapi/oidc/callback
  scope:
  - openid
  - email
  - profile
version: v3

```

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.

---

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'

```

### Test the connector

Now test the connector resource by piping the file to `tctl sso test` command:

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

If the configuration test fails, the `tctl sso test` command will print helpful information to debug the issue.

### Create the connector

If the configuration is working for you, proceed creating the connector resource by using the `tctl create` command:

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

The Auth Connector resource for Microsoft Entra ID is now configured.

## Step 3/3. Configure authentication preferences

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`.

## FAQ

### I want to customize how Teleport follows the groups overage claim

Groups overage claim setting can be customized by using the `entra_id_groups_provider` field in the Auth Connector spec.

```
kind: oidc
metadata:
  name: entra-id
spec:
  ... # other fields not displayed for brevity
  entra_id_groups_provider:
    disabled: false # set value to "true" to turn off the groups overage claim
    group_type: "security-groups" # can be "directory-roles", "all-groups"
    graph_endpoint: "https://graph.microsoft.com" # update this value to point to another official Graph API endpoint

```

## Next steps

Now that you know how to integrate Microsoft Entra ID with Teleport, you can refine your configuration to better suit your organization.

### Edit your OIDC setup

Learn more about other [OIDC](https://goteleport.com/docs/zero-trust-access/sso/integrate-idp/oidc.md)-related configurations that Teleport supports.

### Integrate IdP traits in Teleport roles

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.

### Identity provider callback failed, missing parameter "Name"

Teleport uses the `email` claim as user's username. This error indicates that an `email` claim was not found in user's OIDC ID Token claims.

This can happen if the user does not have a domain verified email account.

Alternatively, you can update the connector spec to use a different claim value (must be a uniquely identifiable value) as an alternative of `email` claim.

Example:

```
kind: oidc
metadata:
  name: entra-id
spec:
  ... # other fields not displayed for brevity
  username_claim: oid

```

### oid claim not found

The user may receive this error if a groups overage claim was issued for the user but Teleport could not find the `oid` claim.

To resolve this, ensure that the `profile` scope is configured in the Auth Connector.

```
kind: oidc
metadata:
  name: entra-id
spec:
  ... # other fields not displayed for brevity
  scope:
  - openid
  - email
  - profile

```
