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.
Domain (Also required when registering this Auth0 client with CILogon)
Client ID
Client Secret (You need to click the "Eye" icon to view this value)
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.
Name: CILogon
Authorization URL: https://cilogon.org/authorize
Token URL: https://cilogon.org/oauth2/token
Scope: openid email profile org.cilogon.userinfo
Separate scopes using a space: On (Green)
Client ID: the Client Identifier you got when you registered your CILogon client
Client Secret: the Client Secret you got when you registered your CILogon client
Fetch User Profile Script:
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:
Name: CILogon Claims
Trigger: Login / Post Login
Runtime: Node XX (Recommended) (i.e., select the latest "recommended" runtime node)
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:
Company Logo: https://cilogon.org/images/cilogon-logo-64x64-b.png
Primary Color: #4b794b
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.