Assign Auth0 Roles Based on Okta Groups Using Post-Login Action

Overview

This article provides a code example for a Post-Login Action. The script verifies the group assignment of a user signing in through an Okta OpenID Connect (OIDC) connection, assigns the corresponding Auth0 role, and updates the user's application metadata.

Applies To
  • Auth0 Post-Login Actions
  • Okta OpenID Connect (OIDC) Connections
Solution
  1. Configure the following secrets in the Action: ROLE_ID_ADMIN, ROLE_ID_USER, M2M_DOMAIN, M2M_CLIENT_ID, and M2M_CLIENT_SECRET.

  2. Add the auth0 npm module to the Action's dependencies.

  3. Use the following code to implement the logic. Ensure that the connection name in the code matches the Okta connection name (currently set to "okta").

const { ManagementClient } = require('auth0');

exports.onExecutePostLogin = async (event, api) => {
  console.log(`[debug] Connection Strategy: ${event.connection.strategy}, Name: ${event.connection.name}`);

  const isOkta = event.connection.strategy === "oidc" &&
                 event.connection.name === "okta";

  const adminRoleId = event.secrets.ROLE_ID_ADMIN;
  const userRoleId = event.secrets.ROLE_ID_USER;

  let role = event.user.app_metadata?.role || userRoleId;

  if (isOkta) {
    const identity = event.user.identities.find(id => id.provider === 'oidc');
    
    console.log(`[debug] Raw Profile Groups: ${JSON.stringify(identity?.profileData?.groups)}`);
    console.log(`[debug] Root User Groups: ${JSON.stringify(event.user.groups)}`);

    const groups = 
      event.user.groups || 
      identity?.profileData?.groups || 
      [];

    console.log(`[debug] Final Groups Array used for logic: ${JSON.stringify(groups)}`);

    let roleIdToAssign = null;

    if (groups.includes("Admin")) {
      console.log("[debug] match: Admin Group detected.");
      role = adminRoleId;
      roleIdToAssign = adminRoleId;
    } else if (groups.includes("Users")) {
      console.log("[debug] match: User Group detected.");
      role = userRoleId;
      roleIdToAssign = userRoleId;
    } else {
      console.log("[debug] no match: No specific group matched. Keeping default role.");
    }

    if (roleIdToAssign) {
      if (!event.secrets.M2M_CLIENT_ID) {
        console.log("[error] M2M_CLIENT_ID secret is missing. Cannot call API.");
      } else {
        try {
          console.log("[debug] Attempting Management API connection.");
          
          const management = new ManagementClient({
            domain: event.secrets.M2M_DOMAIN,
            clientId: event.secrets.M2M_CLIENT_ID,
            clientSecret: event.secrets.M2M_CLIENT_SECRET,
          });

          const userId = event.user.user_id;

          console.log(`[debug] API Call: Assigning role ${roleIdToAssign}...`);
        await management.users.roles.assign({ id: userId }, { roles: [roleIdToAssign] });
          
          
          console.log("[debug] API Success: Roles updated.");

        } catch (err) {
          console.log("[error] Management API Failed:", err);
          console.log("[error] Full Error Object:", JSON.stringify(err));
        }
      }
    }
  }

  const isDatabase =
    event.connection.strategy === "auth0" ||
    event.connection.strategy === "email";

  if (isDatabase) {
    if (event.user.app_metadata?.role) {
      role = event.user.app_metadata.role;
    }
  }

  console.log(`[debug] Final Role ID in Token: ${role}`);

  api.idToken.setCustomClaim("https://<namespace>/role", role);
  api.accessToken.setCustomClaim("https://<namespace>/role", role);

  api.user.setAppMetadata("role", role);
};

Recommended content

No recommended content found...