# Teleport Authentication with Microsoft Entra ID (formerly Azure AD)

This guide will cover how to configure Microsoft Entra ID to issue credentials to specific groups of users with a SAML Authentication Connector. When used in combination with role-based access control (RBAC), it allows Teleport administrators to define policies like:

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

The following steps configure an example SAML authentication connector matching Microsoft Entra ID groups with security roles. You can choose to configure other options.

## How it works

You can register your Teleport cluster as an application with Microsoft Entra ID, then create an **authentication connector** resource that provides Teleport with information about your application. When a user signs in to Teleport, Microsoft Entra ID 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 Microsoft Entra ID with the names of one or more Teleport roles.

## Prerequisites

Before you get started, you’ll need:

- A Microsoft Entra ID admin account with access to creating non-gallery applications (P2 License).
- To register one or more users in the directory.
- To create at least two security groups in Microsoft Entra ID and assign one or more users to each group.
- A Teleport role with access to maintaining `saml` resources. This 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/ver/17.x/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/ver/17.x/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  17.7.20
  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 an enterprise application

1. Select **Entra ID -> Enterprise Applications**

   ![Select Enterprise Applications From Manage](/docs/assets/images/azuread-1-home-15da0a6472e5bcbdb959b7129783dc89.png)

2. Select **New application**

   ![Select New Applications From Manage](/docs/assets/images/azuread-2-newapp-089683b09d03701be36f2fb89de84500.png)

3. Select **Create your own application**, enter the application name (for example, Teleport), and select **Integrate any other application you don't find in the gallery (Non-gallery)**.

   ![Select Non-gallery application](/docs/assets/images/azuread-3-createnongalleryapp-2c6add53106f3a165e592bcb715fc74b.png)

4. Select **Properties** under **Manage** and set **Assignment required?** to **No**

   ![Turn off user assignment](/docs/assets/images/azuread-4-turnoffuserassign-b14490f8b92546f021dc13c8688c4366.png)

   Click **Save** before proceeding to the next step.

### Configure SAML

1. Select **Single sign-on** under **Manage** and choose **SAML**

   ![Select SAML](/docs/assets/images/azuread-5-selectsaml-2de730e6a915f874691a5616ed68e3c0.png)

2. Edit the **Basic SAML Configuration**

   ![Edit Basic SAML Configuration](/docs/assets/images/azuread-6-editbasicsaml-9124b4fb4626e974cffdabd4118fe647.png)

3. Enter the URL for your Teleport Proxy Service host in the **Entity ID** and **Reply URL** fields, for example:

   ```
   https://mytenant.teleport.sh:443/v1/webapi/saml/acs/ad
   ```

   ![Put in Entity ID and Reply URL](/docs/assets/images/azuread-7-entityandreplyurl-7d3e9f8a5fb05b7e080f8e14cc39f8d8.png)

   Click **Save** before proceeding to the next step.

4. In **SAML Certificates** section, copy the **App Federation Metadata URL** link and save it for use in our Teleport connector configuration:

   ![Download Federation Metadata XML](/docs/assets/images/azuread-9-fedmeatadataxml-55c40affb7922d41a8e03fee65ae1f14.png)

### Edit attributes & claims

1. Click on **Unique User Identifier (Name ID)** under **Required claim**.

2. Change the "name identifier format" to **Default**. Make sure the source attribute is `user.userprincipalname`.

   ![Confirm Name Identifier](/docs/assets/images/azuread-8a-nameidentifier-10d5031979b40b1809d1cb5ad1e0fa07.png)

3. Add a group claim to make user security groups available to the connector:

   ![Put in Security group claim](/docs/assets/images/azuread-8b-groupclaim-35f70f9fa71f7734ae3a49adbac6c9c5.png)

4. (optional) Add a claim that transforms the format of the Entra ID username to lower case, in order to use it inside Teleport roles as the `{{external.username}}` property.

   Set the Source to "Transformation". In the new panel:

   - Set the Transformation value to "Extract()"

   - Set the Attribute name to `user.userprincipalname`.

   - Set the Value to `@`.

   - Click "Add Transformation" and set the Transformation to `ToLowercase()`.

     ![Add a transformed username](/docs/assets/images/azuread-8c-usernameclaim-d894dfd3e06c9fa38c200b90827ceace.png)

## Step 2/3. Create a new Teleport role

Create a Teleport role resource that will use external username data from the Entra ID connector to determine which Linux logins to allow on a host.

Create a file called `dev.yaml` with the following content:

```
kind: role
version: v5
metadata:
  name: dev
spec:
  options:
    max_session_ttl: 24h
  allow:
    # only allow login as either ubuntu or the 'windowsaccountname' claim
    logins: [ '{{external["http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"]}}', ubuntu ]
    node_labels:
      access: relaxed

```

Users with the `dev` role are only allowed to log in to nodes with the `access: relaxed` Teleport label. They can log in as either `ubuntu` or a username that is passed in from the Entra ID connector using the `windowsaccountname` attribute.

The login `{{external["http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname"]}}` configures Teleport to look at the `http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname` attribute and use that field as an allowed login for each user. Since the name of the attribute contains characters besides letters, numbers, and underscores, you must use double quotes (`"`) and square brackets (`[]`) around the name of the attribute.

Create the role:

```
$ tctl create dev.yaml
```

---

TIP

You can also create and edit roles using the Web UI. Go to **Access -> Roles** and click **Create New Role** or pick an existing role to edit.

---

## Step 3/3. Create a SAML connector

Now, create a SAML connector resource using `tctl`.

```
$ tctl sso configure saml --preset ad \
--entity-descriptor https://login.microsoftonline.com/ff882432.../federationmetadata/2007-06/federationmetadata.xml\?appid\=b8d06e01... \
--attributes-to-roles http://schemas.microsoft.com/ws/2008/06/identity/claims/groups,41c94563...,dev \
--attributes-to-roles http://schemas.microsoft.com/ws/2008/06/identity/claims/groups,8adac502...,access > azure-connector.yaml
```

In the example above:

- `--entity-descriptor` specifies the app federation metadata URL saved in the previous step.
- Each `--attributes-to-roles` specifies the name of the schema definition for groups, groups, the UUID of an AD group, and the Teleport role that members of the group will be assigned.

The file `azure-connector.yaml` should now resemble the following:

```
kind: saml
metadata:
  name: ad
spec:
  acs: https://mytenant.teleport.sh/v1/webapi/saml/acs/ad
  attributes_to_roles:
  - name: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups
    roles:
    - dev
    value: 41c94563...
  - name: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups
    roles:
    - access
    value: 8adac502...
  audience: https://mytenant.teleport.sh/v1/webapi/saml/acs/ad
  cert: ""
  display: Microsoft
  entity_descriptor: ""
  entity_descriptor_url: https://login.microsoftonline.com/ff882432.../federationmetadata/2007-06/federationmetadata.xml?appid=b8d06e01...
  issuer: ""
  service_provider_issuer: https://mytenant.teleport.sh/v1/webapi/saml/acs/ad
  sso: ""
version: v2


```

With the connector in place on the cluster, you can test it with `tctl`:

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

Your browser should open and log you in to the Teleport cluster using your Entra ID credentials. If there are any problems, the CLI output will help you debug the connector configuration.

To create the connector using the `tctl` tool, run the following command:

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

### Enable default SAML authentication

Configure Teleport to use SAML authentication as the default instead of the local user database.

Use `tctl` to edit the `cluster_auth_preference` value:

```
$ tctl edit cluster_auth_preference
```

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

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

```

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

```
cluster auth preference has been updated

```

---

TIP

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

---

## Token encryption (Optional)

Entra ID's SAML token encryption encrypts the SAML assertions sent to Teleport during SSO redirect.

Token encryption is an Azure Active Directory premium feature and requires a separate license. Since traffic between Entra ID and the Teleport Proxy Service already uses HTTPS, token encryption is optional. To determine whether you should enable token encryption, read the Entra ID [documentation](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/howto-saml-token-encryption).

### Set up Teleport token encryption

Start with generating a public/private key and a certificate. You will set up the public certificate with Entra ID and the private key with Teleport.

```
$ openssl req -nodes -new -x509 -keyout server.key -out server.cer
```

If you are modifying the existing connector, open it in your editor:

```
$ tctl edit saml
```

You will notice that Teleport has generated a `signing_key_pair`. This key pair is used to sign responses.

```
kind: saml
metadata:
  name: ad
spec:
  acs: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
  attributes_to_roles:
  - name: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups
    roles:
    - editor
    - access
    - auditor
    value: '*'
  audience: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
  cert: ""
  display: Microsoft
  entity_descriptor:
  entity_descriptor_url: https://login.microsoftonline.com/ff882432.../federationmetadata/2007-06/federationmetadata.xml?appid=b8d06e01...
  issuer: https://sts.windows.net/your-id-here/
  service_provider_issuer: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
  signing_key_pair:
    cert: |
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
    private_key: |
      -----BEGIN RSA PRIVATE KEY-----
      ...
      -----END RSA PRIVATE KEY-----
  sso: https://login.microsoftonline.com/your-id-here/saml2
version: v2

```

Add `assertion_key_pair` using the data from `server.key` and `server.cer`.

```
kind: saml
metadata:
  name: azure-saml
spec:
  acs: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
  attributes_to_roles:
  - name: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups
    roles:
    - editor
    - access
    - auditor
    value: '*'
  audience: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
  cert: ""
  display: Microsoft
  entity_descriptor:
  entity_descriptor_url: https://login.microsoftonline.com/ff882432.../federationmetadata/2007-06/federationmetadata.xml?appid=b8d06e01...
  issuer: https://sts.windows.net/your-id-here/
  service_provider_issuer: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
  signing_key_pair:
    cert: |
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
    private_key: |
      -----BEGIN RSA PRIVATE KEY-----
      ...
      -----END RSA PRIVATE KEY-----
  sso: https://login.microsoftonline.com/your-id-here/saml2
version: v2

```

---

WARNING

Make sure to have the same indentation for all lines of the certificate and key, otherwise Teleport will not parse the YAML file.

---

After your edits, the file will look like this:

```
kind: saml
metadata:
  name: azure-saml
spec:
  acs: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
  attributes_to_roles:
  - name: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups
    roles:
    - editor
    - access
    - auditor
    value: '*'
  audience: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
  cert: ""
  display: Microsoft
  entity_descriptor:
  entity_descriptor_url: https://login.microsoftonline.com/ff882432.../federationmetadata/2007-06/federationmetadata.xml?appid=b8d06e01...
  issuer: https://sts.windows.net/your-id-here/
  service_provider_issuer: https://mytenant.teleport.sh/v1/webapi/saml/acs/azure-saml
  assertion_key_pair:
    cert: |
      -----BEGIN CERTIFICATE-----
      New CERT
      -----END CERTIFICATE-----
    private_key: |
      -----BEGIN RSA PRIVATE KEY-----
      New private key
      -----END RSA PRIVATE KEY-----
  signing_key_pair:
    cert: |
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
    private_key: |
      -----BEGIN RSA PRIVATE KEY-----
      ...
      -----END RSA PRIVATE KEY-----
  sso: https://login.microsoftonline.com/your-id-here/saml2
version: v2

```

Update the connector by saving and closing the file in your editor.

### Activate token encryption

- Navigate to **Token Encryption**:

![Navigate to token encryption](/docs/assets/images/azuread-token-encryption-0-f5910e95dfd7ef64111f1a9ced6ddba2.png)

- Import certificate

![Import certificate](/docs/assets/images/azuread-token-encryption-1-import-647cc55d5b6506f01261096e2ae4d243.png)

- Activate it

![Activate certificate](/docs/assets/images/azuread-token-encryption-2-activate-a0ed0bf4350a06de9288b025a487d78c.png)

If the SSO login with this connector is successful, the encryption works.

## 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 Teleport's Auth Service receives a request to list Teleport Nodes (e.g., to display Nodes in the Web UI or via `tsh ls`), it only returns the Nodes that the current user is authorized to view.

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

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

If you are not seeing Nodes 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/ver/17.x/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.

### Failed to process SAML callback

If you encounter a "Failed to process SAML callback" error, take a look at the audit log.

```
Special characters are not allowed in resource names. Use a name composed only from
alphanumeric characters, hyphens, and dots: /web/users/ops_example.com#EXT#@opsexample.onmicrosoft.com/params

```

The error above is caused by a Name ID format that is not compatible with Teleport's naming conventions.

Change the Name ID format to use email instead:

![Change NameID format to use email](/docs/assets/images/azuread-nameid-31a674b242a331dbec6a7060b0cf43d1.png)

## Further reading

- [Teleport Configuration Resources Reference](https://goteleport.com/docs/ver/17.x/reference/resources.md)
- In the Teleport role we illustrated in this guide, `external` traits are replaced with values from the single sign-on provider that the user used to authenticate to Teleport. For full details on how traits work in Teleport roles, see the [Access Controls Reference](https://goteleport.com/docs/ver/17.x/reference/access-controls/roles.md).
