Skip to content

Commit

Permalink
integration of CZERTAINLY with MS ADFS throught Keycloak (#149)
Browse files Browse the repository at this point in the history
  • Loading branch information
semik authored Apr 26, 2024
1 parent dff0e82 commit b21ae75
Show file tree
Hide file tree
Showing 15 changed files with 490 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Overview

This integration guide describes how to use [Microsoft Active Directory Federation Services](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/ad-fs-overview) (AD FS) as an Identity Provider (IdP) for CZERTAINLY platform and enable SSO. AD FS is integrated using Security Assertion Markup Language 2.0. The platform is internally using OIDC and Keycloak is used as a bridge and mapping of user attributes between AD FS and platform.

This integration guide was tested using:
- Keycloak version 24
- AD FS 3.0

:::info[SAML 2.0]
Security Assertion Markup Language 2.0 (SAML 2.0) is a version of the SAML standard for exchanging authentication and authorization identities between security domains. SAML 2.0 is an XML-based protocol that uses security tokens containing assertions to pass information about a principal (usually an end-user) between a SAML authority, named an Identity Provider, and a SAML consumer. The assertions are digitally signed and can be verified with the public key and certificate of the SAML authority.
:::

## Active Directory Federation Services presence

Before you start with the integration, make sure that you have AD FS installed and configured. If you don't have AD FS installed, you can follow the official Microsoft documentation on how to [Install Active Directory Federation Services](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/deployment/install-the-ad-fs-role-service).

## Prerequisites

We assume that the integration is done using existing Keycloak. Although any OpenID Connect (OIDC) enabled provider can be used with the platform, there is an existing Keycloak integration using [Helm chart](../../installation-guide/deployment/deployment-helm/overview).

Be sure that you provider is properly configured and integrated with CZERTAINLY platform. For more information, see integration guide on [Keycloak Authentication Server](../keycloak/overview).

## Integration

Integration consists of the following steps:

| # | Step | Description |
|---|--------------------------------------------|-----------------------------------------------------------------------------------------------------------------|
| 1 | [Configure Keycloak](./configure-keycloak) | Configure AD FS as SAML 2.0 IdP for Keycloak, define attribute mappings and export SAML XML metadata for AD FS. |
| 2 | [Configure AD FS](./configure-adfs) | Import SAML metadata from Keycloak, establish trust and define attribute mappings for CZERTAINLY. |

## Login using AD FS

After successful integration, you will be able to see additional login button in Keycloak login screen with the name of the configured identity provider display name, e.g. `AD FS`.

<center>
<div style={{width: "40%"}}>

![AD FS login button](../../../assets/adfs/adfs-czertainly-login.png)

</div>
</center>

When you click on the button, you will be redirected to the AD FS login page where you can authenticate using your AD FS credentials.

## Troubleshooting

For common issues and troubleshooting, refer to [Troubleshooting](./troubleshooting).

## References

- [How to Setup MS AD FS 3.0 as Brokered Identity Provider in Keycloak](https://www.keycloak.org/2017/03/how-to-setup-ms-ad-fs-30-as-brokered)
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
# Configure Keycloak

We need to create a new Identity Provider in Keycloak and configure Mappers. This will allow us to authenticate users against AD FS.

Login to your Keycloak instance as an administrator, where you have CZERTAINLY realm configured and follow the steps below:

1. From the menu, select **`Identity Providers`** and add new **`SAML v2.0`** identity provider.
2. Insert **`alias`** and **`Display name`** of your choice. We are going to use **`adfs-idp-alias`** and **`AD FS`** respectively in this guide.
3. Insert **`SAML entity descriptor`**, which is the metadata of your AD FS. You can find it at `https://adfs.example.com/FederationMetadata/2007-06/FederationMetadata.xml`. Replace **`adfs.example.com`** with your AD FS hostname.
4. Click on **`Add`** button to save the new Identity Provider.
5. Change **`Name ID Policy Format`** to **`Windows Domain Qualified Name`**.
6. Enable **`Want AuthnRequests signed`** option.
7. Change **`SAML signature key name`** to **`CERT_SUBJECT`**.
8. Change **`First login flow override`** to **`first broker login`**.
9. Change **`Sync mode`** to **`Force`**. This will ensure that the attribute coming from AD FS will overwrite local values in Keycloak and will be always current.

:::tip[Manual import of AD FS metadata]
In case you are unable to provide AD FS metadata from AD FS from URL, you can import it manually into Keycloak. To do so, disable `Use entity descriptor`, and the option `Import config from file` will be displayed.
:::

:::warning[Keycloak version]
The configuration options may vary depending on the Keycloak version. The instructions are based on Keycloak 24.
:::

## Mappers

Mappers are used to transform the information from the SAML assertion into Keycloak user attributes. SAML Assertion is a set of attributes about the user that is sent from the Identity Provider to the Service Provider in XML format. The Service Provider can use this information to create or update the user account in its system. In our case, the Service Provider is Keycloak and the Identity Provider is AD FS.

Example of SAML Assertion providing user's email address:

```xml
...
<AttributeStatement>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress">
<AttributeValue>some.user@example.com</AttributeValue>
</Attribute>
...
```

The configuration of Mappers depends on your AD FS configuration. The following is a typical configuration to map the user's first name, last name, email, and groups from AD FS to Keycloak.

To create Mappers, go to the Identity Provider configuration and switch to the Mappers tab. Click the `Add mapper` button and define the mappers as shown below:

### Attribute: firstName

1. Name: **Attribute: firstName**
2. Sync mode override: **Inherit**
3. Mapper type: **Attribute Importer**
4. Attribute Name: **`http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname`**
5. Friendly Name: *keep empty*
6. Name Format: **ATTRIBUTE_FORMAT_BASIC**
7. User Attribute Name: **firstName**

<center>
<div style={{width: "80%"}}>

![Keycloak mapper First Name](../../../assets/adfs/mapper-keycloak-firstname.png)

</div>
</center>

### Attribute: lastName

1. Name: **Attribute: lastName**
2. Sync mode override: **Inherit**
3. Mapper type: **Attribute Importer**
4. Attribute Name: **`http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname`**
5. Friendly Name: *keep empty*
6. Name Format: **ATTRIBUTE_FORMAT_BASIC**
7. User Attribute Name: **lastName**

<center>
<div style={{width: "80%"}}>

![Keycloak mapper Last Name](../../../assets/adfs/mapper-keycloak-lastname.png)

</div>
</center>

### Attribute: email

1. Name: **Attribute: email**
2. Sync mode override: **Inherit**
3. Mapper type: **Attribute Importer**
4. Attribute Name: **`http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`**
5. Friendly Name: *keep empty*
6. Name Format: **ATTRIBUTE_FORMAT_BASIC**
7. User Attribute Name: **email**

<center>
<div style={{width: "80%"}}>

![Keycloak mapper Email](../../../assets/adfs/mapper-keycloak-email.png)

</div>
</center>

### Attribute: groups

1. Name: **Attribute: groups**
2. Sync mode override: **Inherit**
3. Mapper type: **Attribute Importer**
4. Attribute Name: **`http://schemas.xmlsoap.org/claims/Group`**
5. Friendly Name: *keep empty*
6. Name Format: **ATTRIBUTE_FORMAT_BASIC**
7. User Attribute Name: **groups**

<center>
<div style={{width: "80%"}}>

![Keycloak mapper Groups](../../../assets/adfs/mapper-keycloak-groups.png)

</div>
</center>

## Export service provider metadata

After you have configured the Identity Provider and Mappers, you need to export the SAML 2.0 service provider metadata. This metadata will be used to configure the AD FS.

1. Go to the Identity Provider configuration and switch to the `Settings` tab.
2. Click on the link `SAML 2.0 Service Provider Metadata` to download the metadata file.

The metadata file contains the information about the Identity Provider, including the public key used to sign the SAML assertions.

<center>
<div style={{width: "80%"}}>

![Keycloak mapper Groups](../../../assets/adfs/keycloak-saml-metadata.png)

</div>
</center>

:::tip[Metadata validation]
Before you proceed with the AD FS configuration, validate the metadata file to ensure that it contains the correct information. You can use online tools like [SAML Metadata Validator](https://www.samltool.com/validate_xml.php) to validate the metadata file. It should contain the correct entity ID, public key, and attribute mappings.
:::

## JSON configuration

The following JSON configuration can be used to automate the configuration of the Identity Provider and Mappers in Keycloak. You can use the [Keycloak Admin REST API](https://www.keycloak.org/docs-api/24.0.1/rest-api/index.html#_identity_providers) to import this configuration.

### Identity provider

The following JSON configuration can be used to create the Identity Provider in Keycloak. Change the values according to your AD FS configuration.

```json
{
"alias": "adfs-idp-alias",
"displayName": "AD FS",
"providerId": "saml",
"enabled": true,
"updateProfileFirstLoginMode": "on",
"trustEmail": false,
"storeToken": false,
"addReadTokenRoleOnCreate": false,
"authenticateByDefault": false,
"linkOnly": false,
"firstBrokerLoginFlowAlias": "first broker login",
"config": {
"postBindingLogout": "true",
"postBindingResponse": "true",
"singleLogoutServiceUrl": "https://adfs.example.com/adfs/ls/",
"backchannelSupported": "false",
"xmlSigKeyInfoKeyNameTransformer": "CERT_SUBJECT",
"loginHint": "false",
"allowCreate": "true",
"authnContextComparisonType": "exact",
"syncMode": "FORCE",
"singleSignOnServiceUrl": "https://adfs.example.com/adfs/ls/",
"wantAuthnRequestsSigned": "true",
"allowedClockSkew": "0",
"encryptionPublicKey": "MIIC5jCCAc6...",
"validateSignature": "false",
"hideOnLoginPage": "false",
"signingCertificate": "MIIC4DCC...",
"nameIDPolicyFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName",
"entityId": "https://keycloak.example.com/realms/CZERTAINLY",
"signSpMetadata": "false",
"signatureAlgorithm": "RSA_SHA256",
"wantAssertionsEncrypted": "false",
"useJwksUrl": "true",
"sendClientIdOnLogout": "false",
"wantAssertionsSigned": "false",
"sendIdTokenOnLogout": "true",
"postBindingAuthnRequest": "true",
"forceAuthn": "false",
"attributeConsumingServiceIndex": "0",
"addExtensionsElementWithKeyInfo": "false",
"principalType": "SUBJECT"
}
}
```

### Mappers

The following JSON configuration can be used to create the Mappers in Keycloak. Change the values according to your AD FS configuration.

```json
{
"name": "Attribute: firstName",
"identityProviderAlias": "adfs-idp-alias",
"identityProviderMapper": "saml-user-attribute-idp-mapper",
"config": {
"syncMode": "INHERIT",
"user.attribute": "firstName",
"attribute.name.format": "ATTRIBUTE_FORMAT_BASIC",
"attribute.name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"
}
}
```

```json
{
"name": "Attribute: lastName",
"identityProviderAlias": "adfs-idp-alias",
"identityProviderMapper": "saml-user-attribute-idp-mapper",
"config": {
"syncMode": "INHERIT",
"user.attribute": "lastName",
"attribute.name.format": "ATTRIBUTE_FORMAT_BASIC",
"attribute.name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"
}
}
```

```json
{
"name": "Attribute: email",
"identityProviderAlias": "adfs-idp-alias",
"identityProviderMapper": "saml-user-attribute-idp-mapper",
"config": {
"syncMode": "INHERIT",
"user.attribute": "email",
"attribute.name.format": "ATTRIBUTE_FORMAT_BASIC",
"attribute.name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
}
}
```

```json
{
"name": "Attribute: groups",
"identityProviderAlias": "adfs-idp-alias",
"identityProviderMapper": "saml-user-attribute-idp-mapper",
"config": {
"syncMode": "INHERIT",
"user.attribute": "groups",
"attribute.name.format": "ATTRIBUTE_FORMAT_BASIC",
"attribute.name": "http://schemas.xmlsoap.org/claims/Group"
}
}
```
Loading

0 comments on commit b21ae75

Please sign in to comment.