OpenID Connect (OIDC)

CILogon provides a standards-compliant OpenID Connect (OAuth 2.0) interface to federated authentication for cyberinfrastructure (CI).

We recommend using a Certified OpenID Connect Implementation when connecting to CILogon. We plan to obtain OpenID Certification for CILogon's OIDC implementation in the future.

Client Registration

To get started, register your client at https://cilogon.org/oauth2/register and wait for notice of approval. Please register your callback URLs on that page with care. They are the only callback URLs that may be used by your client unless you later contact help@cilogon.org and request a change to your registration.

Kubernetes users: It is recommended that you specify a refresh token lifetime of 10 days (864000 seconds) or longer if your cluster requires authentication.

Client Configuration

OpenID Connect (OIDC)

CILogon's OpenID Connect (OIDC) endpoint:

OAuth 2.0

CILogon's OAuth 2.0 endpoints:

Scopes

Please configure your client to request only the scope(s) it requires. CILogon will prompt users to approve release of their information to your client. The less information your client requests (via fewer scopes), the more likely users are to approve. Also note that your client can request AT MOST the scopes that are registered, i.e., the "set intersection" of requested scopes and registered scopes is calculated for the set of returned claims. If you need additional scopes after you have registered your client, please email help@cilogon.org for assistance.

JupyterHub users: If you are using the JupyterHub OAuthenticator plugin with CILogon, please request the following three (3) scopes: openid, email, and org.cilogon.userinfo.

CILogon currently supports the following scopes:

      • openid: required

          • resulting claims:

              • sub - a unique identifier for the user, e.g., "http://cilogon.org/serverA/users/12345"

              • iss - the issuer of the id_token, e.g., "https://cilogon.org"

              • aud - the audience of the id_token, which is the client_id of the OIDC client, e.g., "cilogon:/client_id/123456789"

              • token_id - an identifier for the returned id_token, e.g., "https://cilogon.org/oauth2/idToken/abcdef123456"

      • email: optional

          • potential resulting claim:

              • email - an email address, e.g., "johnsmith@example.edu"

      • profile: optional

          • potential resulting claims:

              • given_name - first name, e.g., "John"

              • family_name - last name, e.g., "Smith"

              • name - display/full name, e.g., "John A Smith"

      • org.cilogon.userinfo: CILogon-specific scope, optional

          • potential resulting claims:

              • idp - identity provider identifier (a.k.a., entityID) , e.g., "https://idp.example.edu/idp/shibboleth"

              • idp_name - identity provider display name, e.g., "Example University"

              • eppn - eduPersonPrincipalName, e.g., "jsmith@example.edu"

              • eptid - eduPersonTargetedID, e.g., "https://idp.example.edu/idp/shibboleth!https://cilogon.org/shibboleth!23aiejfJVIFavDJFaj8bwsHJaxs="

              • affiliation - group membership, e.g., "student@example.edu;member@example.edu"

              • ou - organizational unit, e.g., "Student Senate"

              • oidc - the "sub" claim as reported by GitHub, Google, ORCID, and Microsoft, e.g., "106198179643554287195" from Google

              • cert_subject_dn - the subject distinguished name of an X.509 certificate, e.g., "/DC=org/DC=cilogon/C=US/O=Example University/CN=John Smith A12345"

              • others listed at https://cilogon.org/.well-known/openid-configuration in the claims_supported section

      • edu.uiuc.ncsa.myproxy.getcert: optional, allows fetching an X.509 certificate from the getcert endpoint

      • offline_access: optional, used only for clients that have refresh tokens enabled. This scope requests that CILogon issue a refresh token that can be used to obtain an access token for use with the userinfo endpoint when the user is not logged in. If the offline_access scope is given, the prompt parameter must include "consent".

Note that if a user attribute is missing, the corresponding claim will not be asserted, i.e., empty claims are never returned as empty strings. This is the reason for the "potential" qualifier above; your client might request the profile scope, but if the IdP does not assert any names for the user, there will be no given_name, family_name, or name claims.

Confidential Clients vs Public Clients

When registering a new client, you are asked to select a Client Type, either Confidential or Public. A Confidential client has an associated client_id and client_secret. The client_secret must be used when authenticating the OIDC client to the token endpoint. A Public client has an associated client_id, but no client_secret. A Confidential client can request the full range of scopes, while a Public client can request only the "openid" scope. This means that a Public client can receive only the "sub" claim (i.e., the CILogon-specific user identifier).

Confidential clients can be converted to Public clients by sending a request to help@cilogon.org. Public clients cannot be converted to Confidential clients.

Optional Authorization Parameters

CILogon's Authorization endpoint (https://cilogon.org/authorize) supports the following optional query parameters:

      • idphint or selected_idp: A comma-separated list of url-encoded SAML EntityIDs and/or OIDC issuers to be shown to the user in the "Select an Identity Provider" selection list. This parameter complies with AARC-G049 - A specification for IdP hinting and allows a client to specify one or more Identity Providers to be shown to the user. For SAML-based IdPs (e.g., those registered by InCommon and eduGAIN), the entityID value is used. For OIDC-based IdPs (e.g., Google, GitHub, ORCID, Microsoft), the "iss" (issuer) value is used. See https://cilogon.org/idplist/ for the list of identity providers supported by CILogon. https://cilogon.org/include/idplist.xml is also available if more details on SAML entities are needed. If multiple IdPs are specified, the first IdP in the list is used as the initially displayed IdP for new visitors. Example showing Google, GitHub, ORCID, and UIUC: https://cilogon.org?idphint=https%3A%2F%2Faccounts.google.com,https%3A%2F%2Fgithub.com,https%3A%2F%2Forcid.org,urn%3Amace%3Aincommon%3Auiuc.edu

      • initialidp: A url-encoded SAML EntityID or OIDC issuer to be initially selected in the "Select an Identity Provider" selection list. Typically, ORCID is shown as the default IdP for new users. The "initialidp" parameter allows a client to specify a different IdP to be initially selected. See "idphint" above for the format of the value of this parameter (i.e., entityID for InCommon/eduGAIN IdPs, "iss" (issuer) for OIDC-based IdPs). Notes: (1) The "idphint" parameter takes precedence over "initialidp" since the first IdP in the "idphint" list is used as the default IdP. (2) The "initialidp" parameter only affects new users since a user's previously selected IdP is saved in a browser cookie for future visits. Example showing ORCID as the default IdP: https://cilogon.org?initialidp=https%3A%2F%2Forcid.org

      • skin: The name of the custom CILogon interface skin for your application. Skins are available for Essential and Full Service subscriptions. Contact help@cilogon.org to request a custom skin.

See below for examples using curl, mod_auth_openidc, and OAuth for MyProxy.

See also: Drupal, Globus, JupyterHub, Galaxy, and Open OnDemand

User Identifiers and Other Claims

As illustrated in the examples below, CILogon supports standard OpenID Connect claims via the standard openid, email, and profile scopes, in addition to custom claims (eppn, eptid, etc.) via the org.cilogon.userinfo scope. To perform simple authentication, the openid scope is all you need. Quoting the OpenID Connect core specification:

The sub (subject) and iss (issuer) Claims, used together, are the only Claims that an RP can rely upon as a stable identifier for the End-User, since the sub Claim MUST be locally unique and never reassigned within the Issuer for a particular End-User, as described in Section 2. Therefore, the only guaranteed unique identifier for a given End-User is the combination of the iss Claim and the sub Claim.


All other Claims carry no such guarantees across different issuers in terms of stability over time or uniqueness across users, and Issuers are permitted to apply local restrictions and policies. For instance, an Issuer MAY re-use an email Claim Value across different End-Users at different points in time, and the claimed email address for a given End-User MAY change over time. Therefore, other Claims such as email, phone_number, and preferred_username and MUST NOT be used as unique identifiers for the End-User.

As the specification states, the sub claim is the user identifier that clients should rely on. CILogon provides eppn and eptid claims for applications that need insight into the SAML attributes provided to CILogon, but be aware that not all identity providers support eppn or eptid, whereas CILogon will always provide the sub claim.

CILogon's sub claim is customizable. If the default value doesn't meet your needs, please contact help@cilogon.org for assistance.

CILogon will also include an Authentication Context Class Reference (acr) claim containing the SAML AuthnContextClassRef value provided by the SAML identity provider. For example, to determine if multi-factor authentication was performed, check for an acr value of "https://refeds.org/profile/mfa".

What claims can you expect to receive?

CILogon will always provide the sub (subject) and iss (issuer) claims, but no other claims are guaranteed to be provided. While CILogon will provide requested claims when possible, there are a variety of reasons why CILogon may not be able to provide a requested claim. CILogon clients should be prepared to handle a required claim not being provided, for example by prompting the user for the required information and/or providing a clear error message that specifies what information is needed.

As a REFEDS R&S service, CILogon can usually provide name, email, and affiliation claims when requested. However, not all eduGAIN identity providers supports the REFEDS R&S program, and even those that do may not provide these user attributes for all members of their population (e.g., faculty versus students, full-time versus visiting researchers, FERPA opt-out, etc.).

CILogon subscribers can control the claims returned on a per-client basis via COmanage.

For More Info

Any questions? View our FAQ or contact help@cilogon.org.

Example using curl

Once you have a registered and approved client, it may be helpful to test/debug using curl on the command-line. The command line JSON parsing tool jq is also helpful.

1. Authorization

First, set environment variables containing your registered and approved client_id, client_secret, and redirect_uri values. For example:

export CILOGON_CLIENT_ID=cilogon:/client_id/6e8fdae3459dac6c685c6b6de37c188c

export CILOGON_CLIENT_SECRET=euWajTysidMofassawoigDiweoj1olwa

export CILOGON_REDIRECT_URI=https://localhost/callback

Be sure to substitute your own client values in the above commands! The CILOGON_CLIENT_SECRET value shown above is not an actual valid client_secret.

Next, visit the Authorization endpoint in your browser. For example:

https://cilogon.org/authorize?response_type=code&client_id=cilogon:/client_id/6e8fdae3459dac6c685c6b6de37c188c&redirect_uri=https://localhost/callback&scope=openid+profile+email+org.cilogon.userinfo+edu.uiuc.ncsa.myproxy.getcert

Be sure to substitute your own client_id and redirect_uri values in the above example! You can experiment with requesting different scope values here. Only the openid scope is required. You must include the edu.uiuc.ncsa.myproxy.getcert scope if you want to retrieve a certificate. Remember that the redirect_uri value must exactly match one of the callback URLs you registered previously with CILogon.

After you successfully authenticate, CILogon will return your browser to the redirect_uri with a code parameter. For example:

https://localhost/callback?code=NB2HI4DTHIXS6Y3JNRXWO33OFZXXEZZPN5QXK5DIGIXTMYZTMU4TQMLDGVRGMY3EGA4TSNLDGFQTSNRXGVSTSMBZGIZDKNJ7OR4XAZJ5MF2XI2D2I5ZGC3TUEZ2HGPJRGYZTOMZVGM3TANRVHE3SM5TFOJZWS33OHV3DELRQEZWGSZTFORUW2ZJ5HEYDAMBQGA

Your browser will probably show a "connection refused" error for that localhost location. That's OK. We just need the code parameter from the browser's address bar.

Save the code in an environment variable. For example:

export CILOGON_CODE=\

NB2HI4DTHIXS6Y3JNRXWO33OFZXXEZZPN5QXK5DIGIXTMYZTMU4TQMLDGVRGMY3EGA4TSNLDGFQTSNRXGVSTSMBZGIZDKNJ7OR4XAZJ5MF2XI2D2I5ZGC3TUEZ2HGPJRGYZTOMZVGM3TANRVHE3SM5TFOJZWS33OHV3DELRQEZWGSZTFORUW2ZJ5HEYDAMBQGA

2. Get a Token

Now you're ready for the first curl command, to exchange the code for a token:

curl -d grant_type=authorization_code \

-d client_id=$CILOGON_CLIENT_ID \

-d client_secret=$CILOGON_CLIENT_SECRET \

-d code=$CILOGON_CODE \

-d redirect_uri=$CILOGON_REDIRECT_URI \

https://cilogon.org/oauth2/token \

> cilogon-token-response.json


export CILOGON_ACCESS_TOKEN=$(jq -r .access_token < cilogon-token-response.json)
export CILOGON_REFRESH_TOKEN=$(jq -r .refresh_token < cilogon-token-response.json)

In the above example, we use jq with the raw output flag to parse the response and store the access token and refresh token values in environment variables. The response (stored in the cilogon-token-response.json ) will look similar to the following:

{

"access_token":"NB2HI4DTHIXS6Y3JNRXWO33OFZXXEZZPN5QXK5DIGIXTEMZXG4YDCZTFGAYGIN3CHFTGMMZVGFQTONBQGVRDMZTCGQ4DSMJ7OR4XAZJ5MFRWGZLTONKG623FNYTHI4Z5GE3DGNZTGUZTSMJRGU2TQJTWMVZHG2LPNY6XMMROGATGY2LGMV2GS3LFHU4TAMBQGAYA",

"refresh_token":"NB2HI4DTHIXS6Y3JNRXWO33OFZXXEZZPN5QXK5DIGIXTIN3BGQ2TKYJUMNQTOMJUMY4DCZRZHE2DAOBSGNSDKNZSGRTDMNR7OR4XAZJ5OJSWM4TFONUFI33LMVXCM5DTHUYTMMZXGM2TGOJRGE2TKOBGOZSXE43JN5XD25RSFYYCM3DJMZSXI2LNMU6TKMBQGAYDA",

"id_token":"eyJ0eXAiOiJKV1QiLCJraWQiOiIyNDRCMjM1RjZCMjhFMzQxMDhEMTAxRUFDNzM2MkM0RSIsImFsZyI6IlJTMjU2In0.eyJlbWFpbCI6InRmbGV1cnlAaWxsaW5vaXMuZWR1IiwiZ2l2ZW5fbmFtZSI6IlRlcnJlbmNlIiwiZmFtaWx5X25hbWUiOiJGbGV1cnkiLCJuYW1lIjoiVGVycmVuY2UgRmxldXJ5IiwiY2VydF9zdWJqZWN0X2RuIjoiL0RDPW9yZy9EQz1jaWxvZ29uL0M9VVMvTz1OYXRpb25hbCBDZW50ZXIgZm9yIFN1cGVyY29tcHV0aW5nIEFwcGxpY2F0aW9ucy9DTj1UZXJyZW5jZSBGbGV1cnkgRDM1MTEwIiwiaWRwIjoiaHR0cHM6Ly9pZHAubmNzYS5pbGxpbm9pcy5lZHUvaWRwL3NoaWJib2xldGgiLCJpZHBfbmFtZSI6Ik5hdGlvbmFsIENlbnRlciBmb3IgU3VwZXJjb21wdXRpbmcgQXBwbGljYXRpb25zIiwiZXBwbiI6InRmbGV1cnlAbmNzYS5pbGxpbm9pcy5lZHUiLCJlcHRpZCI6Imh0dHBzOi8vaWRwLm5jc2EuaWxsaW5vaXMuZWR1L2lkcC9zaGliYm9sZXRoIWh0dHBzOi8vZGV2LmNpbG9nb24ub3JnL3NoaWJib2xldGghODVFTmhNU3hXV3crbTBMOFd4OUxEaUgrakRFPSIsInN1YmplY3RfaWQiOiJ0ZmxldXJ5QG5jc2EuaWxsaW5vaXMuZWR1IiwiYWZmaWxpYXRpb24iOiJtZW1iZXJAbmNzYS5pbGxpbm9pcy5lZHU7ZW1wbG95ZWVAbmNzYS5pbGxpbm9pcy5lZHU7c3RhZmZAbmNzYS5pbGxpbm9pcy5lZHUiLCJhY3IiOiJodHRwczovL3JlZmVkcy5vcmcvcHJvZmlsZS9tZmEiLCJpc3MiOiJodHRwczovL2Rldi5jaWxvZ29uLm9yZyIsInN1YiI6Imh0dHA6Ly9jaWxvZ29uLm9yZy9zZXJ2ZXJEL3VzZXJzLzM1MTEwIiwiYXVkIjoibXlwcm94eTpvYTRtcCwyMDEyOi9jbGllbnRfaWQvNzdlMDUwYzY4ZTdkNjcyOGI2MGFjOWU5MTljNjQ5NDQiLCJ0b2tlbl9pZCI6Imh0dHBzOi8vZGV2LmNpbG9nb24ub3JnL29hdXRoMi9pZFRva2VuLzRjMTBkYjJjOGRjMmUwMmQwNzk1ZTZjM2EzNDA3NjNkLzE2MzczNTM3MDgzODMiLCJhdXRoX3RpbWUiOjE2MzczNTMwNjAsImV4cCI6MTYzNzM1NDYwOCwiaWF0IjoxNjM3MzUzNzA4fQ.MLF4j9lkRKUCLPP5NsHjMlwLWbDrjsEULAT6YFrrlMfXBoFdTISQ9pcK5Zz0NsO1K16gVIKfp-Jf0AW9Q2y9duAuqv48y9m9wg_7nfG5lVR-w8w-LQK1oVodH8i-aofKj3lt6ZDPzG662FyWWtyY9dpoZxrp5y9sClDdBh6zKDxFUMycupwvXYmADMFvcaKCzm_m7sIvumeGcqFQNLa-y1MIY7qDUaIw85F8fsrCHBWDLyfjJlOCsbOp5UMUfFT6wj6tR4jckjIyHtNoF6Hi5zLyRYUDkIfXb2eHZJXHVWDLh2wtz39WqtFS0Y1cGZ6-icnwfsdSdP5AnPKdNy5YcA",

"token_type":"Bearer",

"expires_in":900}

We stored the access_token value in the CILOGON_ACCESS_TOKEN environment variable and stored the refresh_token value in the CILOGON_REFRESH_TOKEN environment variable. Note that a refresh_token will only be returned only if refresh tokens are enabled for your client (i.e., you set a refresh token lifetime when you registered your client or you later asked help@cilogon.org to enable refresh tokens for your client).

3. Get UserInfo

Next, you can use the token to get your user information:

curl -d access_token=$CILOGON_ACCESS_TOKEN \

https://cilogon.org/oauth2/userinfo \

| jq

The command should produce output similar to the following:

{

"subject_id": "tfleury@ncsa.illinois.edu",

"sub": "http://cilogon.org/serverD/users/35110",

"idp_name": "National Center for Supercomputing Applications",

"eppn": "tfleury@ncsa.illinois.edu",

"cert_subject_dn": "/DC=org/DC=cilogon/C=US/O=National Center for Supercomputing Applications/CN=Terrence Fleury D35110",

"eptid": "https://idp.ncsa.illinois.edu/idp/shibboleth!https://dev.cilogon.org/shibboleth!85ENhMSxWWw+m0L8Wx9LDiH+jDE=",

"iss": "https://dev.cilogon.org",

"given_name": "Terrence",

"acr": "https://refeds.org/profile/mfa",

"aud": "cilogon:/client_id/6e8fdae3459dac6c685c6b6de37c188c",

"idp": "https://idp.ncsa.illinois.edu/idp/shibboleth",

"token_id": "https://cilogon.org/oauth2/idToken/4c10db2c8dc2e02d0795e6c3a340763d/1637353708383",

"affiliation": "member@ncsa.illinois.edu;employee@ncsa.illinois.edu;staff@ncsa.illinois.edu",

"name": "Terrence Fleury",

"family_name": "Fleury",

"email": "tfleury@illinois.edu"

}

4. Refresh your tokens

If refresh tokens are enabled for your client, then you can used the refresh token to obtain a new access token.

curl -d grant_type=refresh_token \

-d client_id=$CILOGON_CLIENT_ID \

-d client_secret=$CILOGON_CLIENT_SECRET \

-d refresh_token=$CILOGON_REFRESH_TOKEN \

-d scope=scope=openid+profile+email+org.cilogon.userinfo \

https://cilogon.org/oauth2/token \

> cilogon-token-response.json


export CILOGON_ACCESS_TOKEN=$(jq -r .access_token < cilogon-token-response.json)
export CILOGON_REFRESH_TOKEN=$(jq -r .refresh_token < cilogon-token-response.json)

The output stored in the cilogon-token-response.txt file will be similar to before, except it will contain new tokens. Note that refresh tokens may be used only once, so the output contains a new refresh_token that we can use to refresh again later. We store the new tokens in the CILOGON_ACCESS_TOKEN and CILOGON_REFRESH_TOKEN environment variables as before.

5. Get a Certificate

If you requested the edu.uiuc.ncsa.myproxy.getcert scope, you can also use your token to get a certificate. First, generate a private key and certificate request:

openssl genrsa -out key.pem 2048


openssl req -new -key key.pem -subj "/CN=ignore" \
| sed '/----/d' | tr -d '\n' > req.string

Then, submit the certificate request to the GetCert endpoint to retrieve a certificate:

curl -d access_token=$CILOGON_ACCESS_TOKEN \

-d client_id=$CILOGON_CLIENT_ID \

-d client_secret=$CILOGON_CLIENT_SECRET \

--data-urlencode certreq=`cat req.string` \

https://cilogon.org/oauth2/getcert

The command should return a certificate in the output. For example:

-----BEGIN CERTIFICATE-----

MIIE8jCCA9qgAwIBAgIDJxlNMA0GCSqGSIb3DQEBCwUAMGsxEzARBgoJkiaJk/IsZAEZFgNvcmcx

FzAVBgoJkiaJk/IsZAEZFgdjaWxvZ29uMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHQ0lMb2dvbjEc

MBoGA1UEAxMTQ0lMb2dvbiBTaWx2ZXIgQ0EgMTAeFw0yMTExMTkyMDMyNDRaFw0yMTExMjkyMDM3

NDRaMIGWMRMwEQYKCZImiZPyLGQBGRYDb3JnMRcwFQYKCZImiZPyLGQBGRYHY2lsb2dvbjELMAkG

A1UEBhMCVVMxODA2BgNVBAoTL05hdGlvbmFsIENlbnRlciBmb3IgU3VwZXJjb21wdXRpbmcgQXBw

bGljYXRpb25zMR8wHQYDVQQDExZUZXJyZW5jZSBGbGV1cnkgRDM1MTEwMIIBIjANBgkqhkiG9w0B

AQEFAAOCAQ8AMIIBCgKCAQEA0PtvB3H6qpkTFDJf62jf2tHincGXY/B3UZGmFjwNBdGlYwwKPcaE

c+HP169/4eHVrtxhMpRnf2sdLL0+kG41ze4jVBz1SnbBnjxX6CDFFhIljA+oWpffEMZc/U+jbeqX

dZioXBww8HrNB+bJoFjgNH1KUrNBjNA6LTMUnJJavco0iXBmiq9pZZCAzIaUoLGLO1A1TvAnGuAw

rebnFbuT+g2PqJoKJ7onjseCcc9Hl9RM4beHA3aPG5ACP4T51GRDtGWg27KHjI893g7y3CfcfnPJ

r+dzZqkCS/kpdsEzlyh2b9EEMJs9u5RH7RWcxgCb67E50Bgm0vuQYPKBuKMtJwIDAQABo4IBcTCC

AW0wKgYLKwYBBAGuIwEBAQYEGwwZdGZsZXVyeUBuY3NhLmlsbGlub2lzLmVkdTB9BgsrBgEEAa4j

AQEBCgRuDGxodHRwczovL2lkcC5uY3NhLmlsbGlub2lzLmVkdS9pZHAvc2hpYmJvbGV0aCFodHRw

czovL2Rldi5jaWxvZ29uLm9yZy9zaGliYm9sZXRoITg1RU5oTVN4V1d3IG0wTDhXeDlMRGlIIGpE

RT0wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBLAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsG

AQUFBwMEMCYGA1UdIAQfMB0wDQYLKwYBBAGCkTYBAQ0wDAYKKoZIhvdMBQICBTA6BgNVHR8EMzAx

MC+gLaArhilodHRwOi8vY3JsLmNpbG9nb24ub3JnL2NpbG9nb24tc2lsdmVyLmNybDAfBgNVHREE

GDAWgRR0ZmxldXJ5QGlsbGlub2lzLmVkdTANBgkqhkiG9w0BAQsFAAOCAQEA0c+XrPWwIs7fTffl

UBQnkO4sS86AKq0qhppwYQoeYoQJiA2nRBRdWdxIFDlNgS7nMAklB19BQnQvjwNgD11HUHoFyon6

m0fgOSqyC+LjGNbf9bDdi8tmBuhc9Z72eNyxclWT4H82xokiSYKDBn2lNkDGwznUpq8l9zytQoJy

VUfrOmvuNOE00VnzM4N22SmaQ2nb8BmQfVONybTuPrM27nizYw3WBNty2563ZqWqL2at7woQpAmd

B0mbqknDMJELpxk5Ci1Rob8qj9ilQD/1uOjBWT1GBpZGmC5lsoLrfW/DShUy58XfI7wZ8F5BF/aN

ZeC7gE7dBuE6gwaJrZl5ZQ==

-----END CERTIFICATE-----

Example using mod_auth_openidc

mod_auth_openidc is an Apache HTTPD 2.x module which provides client authentication to an OpenID Connect server. It can be used to restrict access to a directory using OpenID Connect authentication. HTTP header variables are populated with OIDC claims which can be used to identify the user.

1. Install mod_auth_openidc - Download the latest version for your operating system from the Releases page. Consult documentation for your O/S on specific installation instructions. Note that other software may be required by mod_auth_openidc for installation. For example, the RPM for CentOS requires libhiredis.so which is provided by the hiredis-devel RPM available from the EPEL repository.

2. Register your client - Use the instructions above to register your client. For this example, assume that the hostname is www.example.org, and we require OpenID Connect authentication to the https://www.example.org/oidc/ directory. Your HTTPD server should be configured for https connections. You can use a self-signed certificate for testing purposes. Note that the Callback URL refers to an empty directory within the /oidc/ directory. This is a requirement of mod_auth_openidc for proper redirection.

Client Name: My Example Client

Contact Email: help@example.org

Home URL: https://www.example.org/

Callback URL(s): https://www.example.org/oidc/redirect

Scopes: openid, email, profile, org.cilogon.userinfo

After you click the "submit" button, the next page will show you your "client identifier" and "client secret". SAVE THESE VALUES as only you have access to the "client secret". You will need both values in the configuration section below.

3. Configure mod_auth_openidc - In the configuration directory for your Apache HTTPD installation (on CentOS, this is /etc/httpd/conf.d/), create a new file openidc.conf with the following configuration. Enter your "client identifier" and "client secret" you got from the previous step. Also set a passphrase of your choosing.

LoadModule auth_openidc_module /usr/lib64/httpd/modules/mod_auth_openidc.so

OIDCProviderMetadataURL https://cilogon.org/.well-known/openid-configuration


OIDCClientID "YOUR CLIENT IDENTIFIER"

OIDCClientSecret "YOUR CLIENT SECRET"


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

OIDCScope "openid email profile org.cilogon.userinfo"

OIDCCryptoPassphrase "A PASSPHRASE OF YOUR CHOOSING"


### OPTIONAL CONFIGURATION PARAMETERS. FOR MORE INFO, SEE:

### https://raw.githubusercontent.com/zmartzone/mod_auth_openidc/master/auth_openidc.conf

OIDCPassRefreshToken On # If your application works with access tokens

OIDCSessionInactivityTimeout 3600 # If your application doesn't save user attributes

OIDCSessionMaxDuration 86400 # If your application doesn't save user attributes


<Location /oidc/>

AuthType openid-connect

Require valid-user

</Location>

Note that you will need to reload the httpd service configuration after creating this file. On CentOS, this can be accomplished as root with "service httpd reload".

4. Set up the "oidc" directory - In the Apache HTTPD DocumentRoot directory (on CentOS, this is /var/www/html/), create new directorires "oidc" and "oidc/redirect" and a simple file to test your setup. Below is an example PHP script which prints out the HTTP header variables set by the mod_auth_openidc module.

mkdir -p /var/www/html/oidc/redirect


echo '<html><head><title>OIDC Variables</title></head><body>

<table>

<?php

ksort($_SERVER);

foreach ($_SERVER as $key => $value) {

if ((preg_match("/^OIDC/",$key)) ||

(preg_match("/^REMOTE_USER/",$key))) {

echo "<tr><td>$key</td><td>$value</td></tr>\n";

}

}

?>

</table>

</body></html>' > /var/www/html/oidc/index.php

5. Test your setup - Open a web browser, go to https://www.example.org/oidc/index.php , select an identity provider, authenticate with your chosen identity provider, and view the results. Here is example output using Google as the Identity Provider:

OIDC_CLAIM_aud myproxy:oa4mp,2012:/client_id/43e14600b717850993fdc2cae9096f6e5

OIDC_CLAIM_auth_time 1452882451

OIDC_CLAIM_email johndoe@gmail.com

OIDC_CLAIM_exp 1452883351

OIDC_CLAIM_family_name Doe

OIDC_CLAIM_given_name John

OIDC_CLAIM_iat 1452882451

OIDC_CLAIM_idp http://google.com/accounts/o8/id

OIDC_CLAIM_idp_name Google

OIDC_CLAIM_iss https://cilogon.org

OIDC_CLAIM_name John Doe

OIDC_CLAIM_nonce h4XYvjDIjeiieZpgIaktGKGgbfcLgzCh_IASh4ige6M4

OIDC_CLAIM_oidc 103128145647504487161

OIDC_CLAIM_openid https://www.google.com/accounts/o8/id?id=AItOawngeTuRlYDj3ifDis5Cci8e0-E-rh329fg

OIDC_CLAIM_sub http://cilogon.org/serverA/users/1234

OIDC_access_token https://cilogon.org/oauth2/accessToken/4871b3cb13982468b4e41f940ffd5d2c1/1451657451704

OIDC_access_token_expires 1452883351

REMOTE_USER http://cilogon.org/serverA/users/1234@cilogon.org

The OIDC_CLAIM_sub value is a CILogon-specific identifier that is unique and persistent for the user. Alternatively, REMOTE_USER can be used since (by default) mod_auth_openidc forms this value from OIDC_CLAIM_sub and OIDC_CLAIM_iss as "sub@iss".

6. Handling Errors - In the default configuration, mod_auth_openidc simply prints out the error message and description thrown by OpenID Connect Providers. You can configure mod_auth_openidc to redirect to a different page where you can better handle OIDC errors. Add the following line to your openidc.conf file:

OIDCHTMLErrorTemplate /etc/httpd/conf.d/oidcErrorTemplate.html

This HTML file can reside anywhere, but must be readable by the Apache httpd process. Then create the HTML file as follows:

echo '<html><body onload="document.forms[0].submit()">

<form method="post" action="http://www.example.org/error">

<input name="error" value="%s">

<input name="error_description" value="%s">

</form>

</body></html>' > /etc/httpd/conf.d/oidcErrorTemplate.html

Change http://www.example.org/error to a valid location on your server which can handle the submitted form. Note that you will need to reload the httpd service configuration to pick up the new error template file.

Example using OAuth for MyProxy (OA4MP)

Below is a complete sample configuration for an OA4MP OIDC client that talks to the main CILogon server. This assumes this client has been registered and approved. You will get the client id and secret from the server at registration time.

<config>

<client name="cilogon-client">

<id>myproxy:oa4mp,2012:/client_id/7a76544eb234d6c5436fcb9f710480669</id>

<serviceUri>https://cilogon.org/oauth2</serviceUri>

<authorizeUri>https://cilogon.org/authorize</authorizeUri>

<callbackUri>https://myclient.bigstate.edu/client2/ready</callbackUri>

<secret>qhkEE47e54sXMD1E6EpyDaauvMAu02uUoXeRlLX0o915i6Cb_GArkN</secret>

<skin>dataOne</skin> <!-- optional -->

</client>

</config>

A full explanation of OA4MP configuration files and how they work is here.