Set up Keycloak as an OIDC Identity Provider

This guide provides step-by-step instructions on configuring Keycloak as an OpenID Connect (OIDC) identity provider (IdP) for NGINX Management Suite. By using OpenID authentication with NGINX Management Suite, you can implement role-based access control (RBAC) to limit user access to specific features available in NGINX Management Suite.

Overview

This guide explains how to configure Keycloak as an identity provider (IdP) for NGINX Management Suite. By implementing OIDC for authentication, administrators can simplify user management in NGINX Management Suite. Instead of creating and managing users individually, administrators can create user groups in NGINX Management Suite that align with groups in their Identity Provider. Access and permissions for users are determined by the roles assigned to their respective user groups. Users from the Identity Provider who are not part of a group with an assigned role will not have access to NGINX Management Suite.

We strongly recommend Open ID Connect (OIDC) as the preferred authentication method for the NGINX Management Suite. OIDC brings several benefits, including Single Sign-On (SSO) and simplified user management through user groups.

Requirements

To successfully follow the instructions in this guide, complete the following requirements for your Keycloak server and NGINX Management Suite host:

Keycloak Server

  • Set up a Keycloak server. See the Keycloak Getting Started and Server documentation for configuration instructions. You will need to create a Realm with an OpenID Endpoint Configuration enabled.

NGINX Management Suite

On the NGINX Management Suite host, take the following steps:

Configure Keycloak

Create Keycloak Client

Follow these steps to configure Keycloak.

  1. Log in to Keycloak as an administrator.
  2. On the navigation menu, select Clients.
  3. Select Create.
  4. On the Add Client form, in the Client ID box, type “nms” as name for the client.
  5. On the Client Protocol list, select openid-connect.
  6. Set the Root URL to the URL of the NGINX Management Suite instance, for example, https://<your instance IP>:443/_codexch.
  7. Select Save.

After the client has been created, add the following configuration:

  1. On the Settings tab, in the Access Type list, select confidential.
  2. On the Mappers tab, select Add Builtin, and select groups. This will export the user’s Keycloak Realm Role information for NGINX Management Suite to use.

Create Keycloak Roles

NGINX Management Suite User Groups will be mapped from Keycloak Realm Roles; Keycloak Client Roles are not mapped. Make sure to use Keycloak top-level roles (Realm Roles).

  1. On the navigation menu, select Realm Roles (or select Roles and then the Realm Roles tab if you are in an older version of Keycloak).
  2. Select Create Role.
  3. In the Role Name box, type the name of the first group you created in NGINX Management Suite, for example “nms-admins”.
  4. Select Save.
  5. Repeat steps 1–3 until you’ve recreated all the groups you want to provide access to, for example “nms-users” and “nms-nap-users”.

Create Keycloak Users

Create the users that will be allowed to log in to NGINX Management Suite.

  1. On the navigation bar, select Users.
  2. Select Add User.
  3. In the Username box, type the user name.
  4. In the Email box, type the user’s email address. NGINX Management Suite will use this email address as the user’s identifier when setting its headers.
  5. Select Save.
  6. After creating the user, select the Credentials tab.
  7. Provide a Password, confirm it, and select Set Password.
  8. On the Role Mappings tab, select the desired roles from the list, for example, “nms-admins”, “nms-users”, or “nms-nap-users”.
  9. Select Add selected.

Configure NGINX Management Suite

Create Roles in NGINX Management Suite

Roles within NGINX Management Suite are a critical component of role-based access control (RBAC). By defining roles, you specify access levels and permissions for different user groups that map to groups in your Identity Provider (IdP).

NGINX Management Suite comes pre-configured with an administrator role called admin. Additional roles can be created as needed.

The admin user or any user with CREATE permission for the User Management feature can create a role.

Here’s how to create a role and set its permissions:

  1. In a web browser, go to the FQDN for your NGINX Management Suite host and log in.

  2. Select the Settings (gear) icon in the upper-right corner.

  3. Select Roles from the left navigation menu.

  4. Select Create.

  5. On the Create Role form, provide the following details:

    • Name: The name to use for the role.
    • Display name: An optional, user-friendly name to show for the role.
    • Description: An optional, brief description of what the role is.
  6. To add permissions:

    1. Select Add Permission.

    2. Choose the NGINX Management Suite module you’re creating a permission for from the Module list.

    3. Select the feature you’re granting permission for from the Feature list. To learn more about features, refer to Getting Started with RBAC.

    4. Select Add Additional Access to add a CRUD (Create, Read, Update, Delete) access level.

      • Choose the access level(s) you want to grant from the Access list.
    5. Select Save.

  7. Repeat step 6 if you need to add more permissions for other features.

  8. When you’ve added all the necessary permissions, select Save to create the role.

Example Scenario

Imagine you need to create an “app-developer” role. This role permits users to create and edit applications without allowing them to delete or perform administrative tasks. You would name the role ‘app-developer,’ select one or more features, and grant permissions that align with the requirements of application development, avoiding features and permissions that enable deletion or other administrative functions.

Create User Groups in NGINX Management Suite

Group names must match with your IdP
To ensure that NGINX Management Suite and your Identity Provider (IdP) work together seamlessly, group names must exactly match between the two systems. If the group names do not correspond, the OIDC integration will not work, preventing users from accessing the NGINX Management Suite. For instance, if you have a group named “app-developers” in your IdP, you must create a user group named “app-developers” in NGINX Management Suite. The group claim must also be part of the token your IdP generates. For guidance on how to add group claims, refer to your IdP’s documentation.

Users from an external identity provider can’t be assigned roles directly in NGINX Management Suite, but they inherit roles through group memberships.

Here’s how to create a user group and assign roles to it:

  1. In a web browser, go to the FQDN for your NGINX Management Suite host and log in.

  2. Select the Settings (gear) icon in the upper-right corner.

  3. From the left navigation menu, select User Groups.

  4. Select Create.

  5. In the Create Group form, provide information for the group:

    • (Required) Group Name: The name or Object ID of the group. It’s essential to carefully follow these guidelines:

      • The value must exactly match the group name or Object ID used in the identity provider.
      • A group can be linked to only one identity provider.
      • You must add a group claim to your token within your identity provider.
    • Display Name: Enter a friendly name for the group.

    • Description: Provide a brief summary of the group.

  6. (Required) Choose one or more roles from the Roles list to assign to the group.

    Important:
    To ensure full access to the NGINX Management Suite platform, you must assign the admin role to at least one user group. This role grants users comprehensive privileges and permissions within the platform.
  7. Select Save to create the group.

Example Scenario

Imagine you’ve created a role called “app-developer” that lets people develop, create, and modify applications, but not delete them or perform administrative tasks. You want this role to correspond to a group in your IdP named “app-developers.”

In this case, you’d select the “app-developer” role when creating the “app-developers” user group in NGINX Management Suite. Users from the Identity Provider who belong to the “app-developers” group will then inherit the “app-developer” role and the associated permissions in NGINX Management Suite.

Configure NGINX Management Suite to Use Keycloak

To configure NGINX Management Suite to use Keycloak as the OIDC identity provider, take the following steps.

Set Keycloak Secret as an Environment Variable

Set the Keycloak secret as an environment variable on the NGINX Management Suite host.

Security consideration
When setting a client secret as an environment variable, ensure that the environment where the variable is set has strict access controls. Only authorized users or processes should have access to view or modify the environment variables. You may want to take other precautions as well, such as encrypting the value and regularly rotating the client secret.

To copy the Keycloak secret:

  1. Open the Keycloak user interface.
  2. Select the Clients tab, and then select the nms client.
  3. On the Credentials tab, copy the Secret value.

To set the Keycloak secret as an environment variable:

  1. Open an SSH connection to your NGINX Management Suite host and log in.

  2. Run the following command, replacing <secret> with the secret value you copied above:

    export KEYCLOAK_SECRET=<secret>
    

Configure OIDC Settings

In this section, we will show you how to update NGINX Management Suite OIDC configuration with the appropriate values.

Connect to your NGINX Management Suite instance and run the following commands:

  • Export the environment variables:

    # Either the FQDN or the IP address is suitable for these environment variables.
    export KEYCLOAK_IP="<insert-keycloak-IP>"
    export NMS_IP="<insert-NMS-IP>"
    
    export KEYCLOAK_CLIENT_ID="<insert-keycloak-client-id>"
    export KEYCLOAK_CLIENT_SECRET="<insert-kecloak-client-secret>"
    
    # Choose an appropriate Hash-Based Message Authentication Code (HMAC)
    export HMAC_KEY="<insert-HMAC>"
    
    export KEYCLOAK_AUTH_ENDPOINT=$(curl -k "https://$KEYCLOAK_IP:8443/auth/realms/<realm-name>/.well-known/openid-configuration" | jq -r ".authorization_endpoint")
    export KEYCLOAK_TOKEN_ENDPOINT=$(curl -k "https://$KEYCLOAK_IP:8443/auth/realms/<realm-name>/.well-known/openid-configuration" | jq -r ".token_endpoint")
    export KEYCLOAK_KEYS_ENDPOINT=$(curl -k "https://$KEYCLOAK_IP:8443/auth/realms/<realm-name>/.well-known/openid-configuration" | jq -r ".jwks_uri")
    
  • Back up the original configuration files.

    sudo cp /etc/nms/nginx/oidc/openid_configuration.conf ~/openid_configuration.conf.orig
    sudo cp /etc/nginx/conf.d/nms-http.conf ~/nms-http.conf.orig
    
  • Copy the OpenID configuration for NGINX to /tmp so you can replace the necessary values.

    sudo cp /etc/nms/nginx/oidc/openid_configuration.conf /tmp/openid_configuration.conf
    
    sudo sed -i'.bak' \
    -e "s%OIDC_CLIENT_ID%${KEYCLOAK_CLIENT_ID}%"  \
    -e "s%SERVER_FQDN%${NMS_IP}%"  \
    -e "s%OIDC_AUTH_ENDPOINT%${KEYCLOAK_AUTH_ENDPOINT}%"  \
    -e "s%OIDC_TOKEN_ENDPOINT%${KEYCLOAK_TOKEN_ENDPOINT}%" \
    -e "s%OIDC_KEYS_ENDPOINT%${KEYCLOAK_KEYS_ENDPOINT}%"  \
    -e "s%OIDC_CLIENT_SECRET%${KEYCLOAK_CLIENT_SECRET}%" \
    -e "s%OIDC_HMAC_KEY%${HMAC_KEY}%" \
    /tmp/openid_configuration.conf
    
  • Uncomment the section of /tmp/openid_configuration.conf required for Keycloak as in the following example:

    # Enable when using OIDC with keycloak
    map $http_authorization $groups_claim {
        default $jwt_claim_groups;
    }
    
    
    map $http_authorization $user_email {
        "~^Bearer.*" '$jwt_clientId@$oidc_domain';
        default $jwt_claim_email;
    }
    
  • Copy the nms-http.conf file to /tmp so you can replace the necessary values.

    sudo cp /etc/nginx/conf.d/nms-http.conf /tmp/nms-http.conf
    
  • Uncomment the OIDC sections in nms-http.conf as in the following examples:

    # Enable when using OIDC
     log_format oidc_jwt '$remote_addr - $jwt_claim_sub [$time_local] "$request" '
                         '$status $body_bytes_sent "$http_referer" "$http_user_agent" '
                         '"$http_x_forwarded_for"';
    
    # OIDC -- client configuration uncomment include to enable
    include /etc/nms/nginx/oidc/openid_configuration.conf;
    
    ## For OIDC Authentication: authorization code flow and Relying Party processing
    # OIDC - remove comment from following directives to enable
    add_header Nginx-Management-Suite-Auth "OIDC";
    include /etc/nms/nginx/oidc/openid_connect.conf;
    
    # OIDC: use email as a unique identifier
    # NOTE: the username is dependent upon claims provided by your IdP
    proxy_set_header Nginx-Management-Suite-Auth "OIDC";
    proxy_set_header Nginx-Management-Suite-User $user_email;
    proxy_set_header Nginx-Management-Suite-Groups $groups_claim;
    proxy_set_header Nginx-Management-Suite-ExternalId $jwt_claim_sub;
    

    Also uncomment all the sections starting with # OIDC authentication (uncomment to enable).

  • Comment out all the Basic Auth sections in nms-http.conf as in the following examples:

    ## For use with basic auth
    #auth_basic_user_file /etc/nms/nginx/.htpasswd;
    ## auth type indication to the client
    #add_header Nginx-Management-Suite-Auth "Basic";
    
    # HTTP Basic:
    #proxy_set_header Nginx-Management-Suite-User $remote_user;
    #proxy_set_header Nginx-Management-Suite-Groups "";
    #proxy_set_header Nginx-Management-Suite-ExternalId "";
    

    Also comment out all the sections starting with # HTTP Basic authentication (comment if using OIDC auth) or # HTTP Basic authentication (disable if using OIDC).

  • Copy the modified configuration files back to their original locations.

    sudo cp /tmp/nms-http.conf /etc/nginx/conf.d/nms-http.conf
    sudo cp /tmp/openid_configuration.conf /etc/nms/nginx/oidc/openid_configuration.conf
    
  • Run sudo nginx -t to verify the config has no errors.

  • Reload NGINX running sudo nginx -s reload.

Troubleshooting

You can revert to Basic Auth to troubleshoot authentication issues by running the following commands:

sudo cp ~/openid_configuration.conf.orig /etc/nms/nginx/oidc/openid_configuration.conf
sudo cp ~/nms-http.conf.orig /etc/nginx/conf.d/nms-http.conf

sudo nginx -s reload

Try It Out

Open NGINX Management Suite by going to https://<your-nginx-instance-manager>/ui.

You should be redirected to the Keycloak login page. Log in with the credentials you created in Keycloak.