Auth0

Auth0 provides authentication and authorization as a service. For small projects that need to manage a user base but are concerned about security issues associated with local user credentials, Auth0 can offload the responsibility of managing a local datastore to Auth0. This capability is free for up to 7500 users. Auth0 manages the user accounts, and project clients can fetch user attributes using standard OAuth2/OIDC protocols. 

CILogon can be added to Auth0 as a "custom social connection", enabling users to log in with their university identity provider through CILogon. This document describes how to register a new Auth0 OAuth2/OIDC client and how to connect CILogon as a custom social connection.

The first step is to sign up for an Auth0 account. After verifying your account, you should log in and be directed to the Dashboard. Here is where you will create a new application and connect CILogon as a social connection.

Click the "Create Application" button.

In the "Create Application" popup window, enter a name for your application (e.g., "My Test App") and select "Regular Web Applications" for the application type. Then click the "Create" button.

On the next page, click the "Skip Integration" button. For testing, we will be using mod_auth_openidc example code.

A new application will be created and you will be shown the "Settings" page. You should see the important parameters which will be needed when configuring this Auth0 application with your local OAuth2/OIDC client. Note the following configuration settings for later use.

Scroll down the page a bit until you see "Allowed Callback URLs". In this text box, enter the callback URL for your OAuth2/OIDC client. Using the mod_auth_openidc example, this corresponds to the "redirect" directory under the "oidc" directory where your application will extract the user attributes. You will need this URL when registering the Auth0 application with CILogon.

Finally, click the "Save Changes" button.

Now you can register this Auth0 application with CILogon. Go to https://cilogon.org/oauth2/register and fill in the requested information. The important configuration is the Callback URL. This value is formed from the "Domain" value for the Auth0 application followed by "/login/callback". Also be sure to select Scopes "email", "profile", and "org.cilogon.userinfo" in order to get additional user attributes from CILogon.

After you click the "Register Client" button, you will be shown a new Client Identifier and Client Secret. RECORD THESE VALUES. The Client Secret will not be shown to you again. Your client registration request is not active until it has been approved by CILogon Administrators. The CILogon Client Identifier and Client Secret will be used on the Auth0 site when configuring CILogon as a "custom social connection".

Back on the Auth0 Dashboard, click the "Authentication" drop-down in the left column, then click "Social". 

On the "Social Connections" page, click the "Create Connection" button.

On the "New Social Connection" page, scroll to the bottom and click "Create Custom".

On the "New Custom Social Connection" page, enter configuration as shown below.

function fetchUserProfile(accessToken, context, callback) {

  request.get(

    {

      url: 'https://cilogon.org/oauth2/userinfo',

      headers: {

        'Authorization': 'Bearer ' + accessToken,

      }

    },

    (err, resp, body) => {

      if (err) {

        return callback(err);

      }

      if (resp.statusCode !== 200) {

        return callback(new Error(body));

      }

      let bodyParsed;

      try {

        bodyParsed = JSON.parse(body);

      } catch (jsonError) {

        return callback(new Error(body));

      }


      const profile = {};

      profile.user_metadata = {};

      profile.user_id = bodyParsed.sub; 


      const optional = [

        "email", "family_name", "given_name", "name"

      ];

      optional.forEach((opt) => {

        if (bodyParsed[opt]) {

          profile[opt] = bodyParsed[opt];

        }

      });


      const attributes = [

        "acr", "affiliation", "amr", "entitlement", "eppn", "eptid",

        "eduPersonAssurance", "eduPersonOrcid", "idp", "idp_name",

        "isMemberOf", "itrustuin", "member_of", "oidc", "ou",

        "pairwise_id", "preferred_username", "sub", "subject_id",

        "uid", "uidNumber", "voPersonExternalID"

      ];

      attributes.forEach((attr) => {

        if (bodyParsed[attr]) {

          profile['user_metadata'][attr] = bodyParsed[attr];

        }

      });

      callback(null, profile);

    }

  );

}

Scroll to the bottom and click the "Create" button.

Back on the "CILogon" Social Connections page, click the "Applications" tab and turn on the the green toggle for "My Test App". 

Auth0 asserts only the basic user profile (e.g., names) and email claims to clients. This means CILogon user attributes such as ePPN (eduPersonPrincipalName) do not pass through automatically. However, it is possible to assert CILogon attributes in special Auth0 attributes by using a custom "Action". 

(NOTE: Previously, CILogon attributes were asserted via a custom "Rule". However, by November 18, 2024, all Auth0 Rules must be migrated to Actions. For details, see Auth0's documentation on Converting Custom Claims in Tokens. Previous Auth0 documentation using Rules can be found here.)

Click the "Actions" drop-down in the left column, then click "Library".

On the "Library" page, click the "Create Action" button, then "Build from scratch" from the drop-down.

In the "Create Action" popup window, enter the following:

Then click the "Create" button.

The "CILogon Claims" Custom Action page will be shown with a code block. Replace the exports.onExecutePostLogin code block with the following code. Then click the "Deploy" button.

exports.onExecutePostLogin = async (event, api) => {

  const namespace = "https://cilogon.org/";

  const attributes = [

    "acr", "affiliation", "amr", "entitlement", "eppn", "eptid",

    "eduPersonAssurance", "eduPersonOrcid", "idp", "idp_name",

    "isMemberOf", "itrustuin", "member_of", "oidc", "ou",

    "pairwise_id", "preferred_username", "sub", "subject_id",

    "uid", "uidNumber", "voPersonExternalID"

  ];

  attributes.forEach((attr) => {

    if (event['user']['user_metadata'][attr]) {

      api.idToken.setCustomClaim(namespace + attr, event['user']['user_metadata'][attr]);

    }

  });

};

Click the "Actions" drop-down in the left column, then click "Flows".

On the "Flows" page, click the "Login" button.

On the "Login" flow page, click the "Custom" column in the "Add Action" section. You should see "< > CILogon Claims". 

Drag the "< > CILogon Claims" block to the main window, between "Start" and "Complete". The resulting flow should look like this.

Finally, click the "Apply" button.

Optionally, we can configure this client to allow JUST CILogon and not any other Auth0 authentication. 

Click the "Applications" drop-down in the left column, then click "Applications". This will show the list of available applications. 

Click "My Test App". 

Click the "Connections" tab and click both the "Username-Password-Authentication" and "google-aouth2" green toggle buttons to turn them off.

Also optionally, we can configure the Login box to show the CILogon icon. This simply modifies the Login screen a bit. 

Click the "Branding" drop-down in the left column, then click "Universal Login". 

On the "Universal Login", enter the following values in the "Quick Start" section:

Then, click the "Save" button.

Next, scroll to the bottom of the page and click the "Advanced Options" button.

Select the "Login" tab and turn on the "Customize Login Page" toggle (to Green).

Scroll down to the "HTML" section and look for a "theme" block in the "new Auth0Lock()" function. Add the following code in the "theme" block so it looks like the screenshot below. 

        authButtons: {

          "CILogon": {

            displayName: "CILogon",

            primaryColor: "#4b794b",

            foregroundColor: "#fff",

            icon: "https://cilogon.org/images/cilogon-logo-40x40-b.png"

          }

        },

Then, scroll to the bottom and click the "Save Changes" button.

Finally, we are ready to configure the local OAuth2/OIDC client to use Auth0 and CILogon for authentication. Using the mod_auth_openidc example, enter the Client ID and Client Secret from the "My Test App" Settings page.

OIDCProviderMetadataURL https://dev-6y8b2h2hokjgf8yn.us.auth0.com/.well-known/openid-configuration

OIDCProviderIssuer https://dev-6y8b2h2hokjgf8yn.us.auth0.com/

OIDCClientID "MY TEST APP CLIENT ID COPIED FROM AUTH0 SETTINGS PAGE"

OIDCClientSecret "MY TEST APP CLIENT SECRET COPIED FROM AUTH0 SETTINGS PAGE"


OIDCCryptoPassphrase ThisIsARandomPassphraseCHANGEIT

OIDCRedirectURI https://example.org/oidc/redirect

OIDCScope "openid profile email"


<Location /oidc/>

   AuthType openid-connect

   Require valid-user

</Location>

After adding the sample PHP code and navigating to it (e.g., https://example.org/oidc/index.php), you should see a JavaScript-based popup box to "Sign in with CILogon".

Click the "Sign in with CILogon" button to be redirected to CILogon. Select your Identity Provider (IdP), then click the "Log On" button.

After authenticating with your IdP, you will be shown the HTTP environment variables that were set by mod_auth_openidc.

OIDC_CLAIM_aud                              IKTrI3l4ms3nyUF6GObI1Wkt9yrmyEEM

OIDC_CLAIM_email                            jsmith@illinois.edu

OIDC_CLAIM_exp                              1709286360

OIDC_CLAIM_family_name                      Smith

OIDC_CLAIM_given_name                       John

OIDC_CLAIM_https---cilogon_org-acr          urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport

OIDC_CLAIM_https---cilogon_org-affiliation  member@illinois.edu;staff@illinois.edu;employee@illinois.edu

OIDC_CLAIM_https---cilogon_org-entitlement  urn:mace:dir:entitlement:common-lib-terms

OIDC_CLAIM_https---cilogon_org-eppn         jsmith@illinois.edu

OIDC_CLAIM_https---cilogon_org-eptid        urn:mace:incommon:uiuc.edu!https://cilogon.org/shibboleth!X321mZDx3i9o386dbn8jwxV8uxw=

OIDC_CLAIM_https---cilogon_org-idp          urn:mace:incommon:uiuc.edu

OIDC_CLAIM_https---cilogon_org-idp_name     University of Illinois at Urbana-Champaign

OIDC_CLAIM_https---cilogon_org-itrustuin    654321987

OIDC_CLAIM_https---cilogon_org-sub          http://cilogon.org/serverA/users/123456

OIDC_CLAIM_https---cilogon_org-uidNumber    123456

OIDC_CLAIM_iat                              1709250360

OIDC_CLAIM_iss                              https://dev-6y8b2h2hokjgf8yn.us.auth0.com/

OIDC_CLAIM_name                             John A Smith

OIDC_CLAIM_nickname                         jsmith

OIDC_CLAIM_nonce                            slY75mN5ZrlB5rj-RxnlyoCN8mFdNdELcWEsF0ts5oI

OIDC_CLAIM_picture                          https://s.gravatar.com/avatar/e3a1be26a9434c33762ed070384f8273?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Ftf.png

OIDC_CLAIM_sid                              JeMIaPTCBqRpPGU8o6UpIc6-zSclOBDg

OIDC_CLAIM_sub                              oauth2|CILogon|http://cilogon.org/serverA/users/123456

OIDC_CLAIM_updated_at                       2024-02-29T23:45:59.778Z

OIDC_access_token                           eyJhbGciOiJkaXIiLCJlbmMiOiJ...

OIDC_access_token_expires                   1709336761

Some explanation of the various attributes coming from Auth0 is in order. Internally, Auth0 automatically creates a new user account for users logging in with Custom Social Connections. The user_id for these accounts is formed as "oauth2|CONNECTION|CONNECTION_USER_IDENTIFIER". In the case of CILogon, this means that the "sub" (OIDC_CLAIM_sub above) is set to "oauth2|CILogon|http://cilogon.org/serverX/users/XXXXX" where the part after the last "|" (vertical bar) is the unique user identifier for the CILogon user. So if your application wants to use the CILogon user id, it needs to strip off the extra prefix added by Auth0. (Alternatively, your application could use the "OIDC_CLAIM_https---cilogon_org-sub" claim which is also the CILogon unique user identifier but without the prefix added by Auth0.)

Tip: If you want to shorten the CILogon unique user identifier, you can use the letter after "/server" and the number after "/users/" to get a "short" CILogon identifier. For safety, you should "scope" this short identifier to CILogon by appending "@cilogon.org". For example, the "long" version "http://cilogon.org/serverA/users/123456" could be shortened to "A123456@cilogon.org".

As stated earlier, the only user attributes that are asserted by Auth0 are the names and email claims as requested by the "profile" and "email" scopes. So you see above that "family_name", "given_name" and "name" values all transferred from CILogon to Auth0 to the client in the usual OIDC claims.

The additional user attributes as requested by the "org.cilogon.userinfo" scope come through in the special "https---cilogon_org-" scoped values. This is handled by the special "CILogon Claims" Action created earlier. So again your application will need to perform some post-processing of these claim names to strip off "https---cilogon_org-" in order to get the actual claims asserted by CILogon.