Introduction
Based on simplicity with JWT tokens delivered through OAuth2 flows, OpenID Connect has become the leading standard for single sign-on of the Internet.
In this scenario, Citrix ADC acts as OpenId Connect SP protecting a web application with Google Identity Plaform acting as Identity Provider. Citrix ADC leverages it’s Content Switching capability to unify load-balancing and authentication virtual server behind a single public IP to avoids multiple public endpoints and multiple certificates (or wildcard certificates).
OpenID Connect code flow is used in this scenario for optimal security. An initial browser redirection redirects user to the Google Identity Provider for user authentication and consent. User is provided with a grant code which is then forwarded to Citrix ADC which use it through a back-channel request to retrieve the ID token from Google Identity Provider . This flow offers optimal security, as tokens are kept in the datacenter and never forwarded to the browser.
Google Identity Platform
Google OpenID Connect discovery document
The OpenID Connect protocol requires the use of multiple endpoints for authenticating users, and for requesting resources including tokens, user information, and public keys. Google Identity Platform endpoints can be retrieved from the https://accounts.google.com/.well-known/openid-configuration JSON Discovery Document. This discovery document provides details about the Gogle OpenID Connect provider’s configuration, including the URLs of the authorization, token, userinfo, and public-keys endpoints.
{
"issuer": "https://accounts.google.com",
"authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
"token_endpoint": "https://oauth2.googleapis.com/token",
"userinfo_endpoint": "https://www.googleapis.com/oauth2/v3/userinfo",
"revocation_endpoint": "https://oauth2.googleapis.com/revoke",
"jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
"response_types_supported": [
"code",
"token",
"id_token",
"code token",
"code id_token",
"token id_token",
"code token id_token",
"none"
],
"subject_types_supported": [
"public"
],
"id_token_signing_alg_values_supported": [
"RS256"
],
"scopes_supported": [
"openid",
"email",
"profile"
],
"token_endpoint_auth_methods_supported": [
"client_secret_post",
"client_secret_basic"
],
"claims_supported": [
"aud",
"email",
"email_verified",
"exp",
"family_name",
"given_name",
"iat",
"iss",
"locale",
"name",
"picture",
"sub"
],
"code_challenge_methods_supported": [
"plain",
"S256"
]
}
Citrix ADC configuration
Citrix ADC platform & limitations
Citrix ADC 12.0 build 58.15 has been used for this scenario. Citrix ADC 12.0 can act as an OpenID Connect SP or IDP :
- When acting as SP (Service Provider), Citrix ADC 12.0 allows extraction of user claims included in the OpenID Connect ID Token but doesn’t support OAuth 2.0 Token Exchange features, JWT Token propagation, or OpenID Connect / OAuth 2.0 SSO with backend servers.
- When acting as IDP (Identity Provider), Citrix ADC 12.0 doesn’t support custom attributes insertion in the ID token.
Enterprise or Platinium license is required to unlock Citrix ADC authentication features.
Content-Switching virtual server
The Citrix ADC content switching feature enables the Citrix ADC appliance to distribute client requests to several virtual servers based on the content of the HTTP request : FQDN, URL pattern matching, User Agent, client IP, …. A specific CS policy is required to divert appropriate traffic to authentication vserver.
Detailed content switching architecture is provided below with non-adressable load-balancing and AAA virtual servers.
Warning : Do NOT configure any Content Switching policy for redirecting trafic to the AAA vServer acting as an OpenId Connect Relying Party / SP. All the trafic is handled by the attached load-balacing virtual server. Configuring a CS policy to redirect /oauth/ URI to the AAA vserver breaks OpenId Connect Authentication.
Authentication virtual server
Create a new non adressable authentication virtual server and configure apropriate SSL settings and server certificate. The Authentication virtual server will be accessed through the Content Switching virtual server and doesn’t need a public IP.
add authentication vserver frontend.domain-test.com_AAA SSL 0.0.0.0
bind ssl vserver frontend.domain-test.com_AAA -certkeyName frontend.domain-test.com
Create an OAuth2 authentication action linked to Google Identity Provider. AuthorizationEndpoint, TokenEndpoint, and CertEndpoint are mandatory and are retrieved from the Google OpenID discovery document.
URL provided in the example below are subject to change at any time by Google. The TokenEndpoint is the URL at which Citrix ADC will download the Access and ID tokens. The CertEndpoint is mandatory as it provides the JWK certificate required to check JWT tokens validity by verifying that the tokens are properly signed by the issuer.
add authentication OAuthAction Auth_A_OAuth-SP
-authorizationEndpoint "https://accounts.google.com/o/oauth/v2/auth?client_id=<GOOGLE-APP-ID>&response_type=code&scope=openid%20email"
-tokenEndpoint "https://www.googleapis.com/oauth2/v4/token"
-CertEndpoint "https://www.googleapis.com/oauth2/v3/certs"
-clientID <GOOGLE-APP-ID>
-clientSecret <GOOGLE-APP-SECRET>
-Attribute1 name
-Attribute2 email
-userNameField email
Configure the OAuth2 authentication policy, link it with the OAuth2 authentication action, and bind the policy to the authenticationirtual server previously created.
add authentication Policy Auth_P_OAuth-SP -rule true -action Auth_A_OAuth-SP
bind authentication vserver frontend.domain-test.com_AAA -policy Auth_P_OAuth-SP -priority 100 -gotoPriorityExpression NEXT
Load-Balancing virtual server
Load-balancing virtual server provides access to backend resources protected by the OpenId Connect authentication virtual server. As the AAA virtual server, the LB virtual server doesn’t need an IP address as it is accessed through the Content Switching virtual server.
The load-balancing virtual server redirects unauthenticated user requests to the authentication virtual server FQDN which is the same than it’s FQDN because of the Content Switching virtual server deployed in front of both LB and AAA virtual server.
add service www.frontend.fr_http 216.58.208.163 HTTP 80
-gslb NONE
-maxClient 0
-maxReq 0
-cip DISABLED
-usip NO
-useproxyport YES
-sp ON
-cltTimeout 180
-svrTimeout 360
-CKA YES
add lb vserver frontend.domain-test.com_vsrv HTTP 0.0.0.0 0
-persistenceType NONE
-cltTimeout 180
-AuthenticationHost frontend.domain-test.com
-Authentication ON
-authVsName frontend.domain-test.com_AAA
bind lb vserver frontend.domain-test.com_vsrv www.frontend.fr_http
Troubleshooting
User authentication flow
The overall application access flow with OpenId Connect authentication looks like the following,
- User enters https://frontend.domain-test.com in browser. Traffic hits the CS vServer and gets switched to the default backend LB vServer without authentication cookies.
- LB vServer redirects user to AAA vServer which sets up the NSC_TASS session cookie and initiates OpenID Connect authentication.
- User gets redirected to Google Identity Platform for authentication and explicit authorization to share name, email address and profile data with frontend.domain-test.com
- Upon OpenID Connect authentication/authorization completion, the user gets redirected back to Citrix ADC AAA vserver with OpenId Connect grant code
- Citrix ADC AAA vserver uses the grant code to get the authorization and identity tokens from Google token endpoint. JWT signature of the identity token is verified and user identity + claims are extracted from the token.
- User is then redirected to the /cgi/selfauth URI of the LB virtual server which creates an authenticated session and provides the browser with AAA cookies to maintain session.
- User is finally redirected back to https://frontend.domain-test.com, with Citrix ADC AAA session cookies
- Traffic hits the CS vServer, gets switched to the default backend LB vServer again. Due to the presence of AAA session cookies, user is not challenged again for authentication
Note : Citrix ADC 12.1 now provides ability to access the userinfo endpoint after having successfully received the authorization and identity tokens. Userinfo endpoint provides access to additional user claims not included in the idenity token.
Retrieve tokens manually from Google
Tokens can be manually retrieved from google for testing purposes. The first step is to retrieve an authorization code from the authorization endpoint using the following command in a web browser. Do not use curl as you will be promped for authentication and consent.
https://accounts.google.com/o/oauth2/auth?client_id=[Application Client Id]&redirect_uri=[Redirect URL]&scope=openid&response_type=code
After authentication and consent, extract the authorization code from the HTTP response and pass it to the token endpoint. Two tokens are provided by Google :
- An opaque OAuth2 authorization token for Google API access
- A JWT Identity Token containing user claims
# Exchange Authorization code for an access token and a refresh token.
curl \
--request POST \
--data "code=[Authentcation code from authorization link]&client_id=[Application Client Id]&client_secret=[Application Client Secret]&redirect_uri=[Redirect URL]&grant_type=authorization_code" \
https://accounts.google.com/o/oauth2/token
{
"access_token" : "<oauth2 access token>",
"expires_in" : 3316,
"id_token" : "<JWT identity tojen>",
"scope" : "https://www.googleapis.com/auth/plus.me",
"token_type" : "Bearer"
}
The access token validity can be verified by calling the tokeninfo endpoint with the access token.
curl https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=[access token]
{
"issued_to": "<client id>",
"audience": "<client id>",
"user_id": "<user id>",
"scope": "https://www.googleapis.com/auth/plus.me",
"expires_in": 2085,
"access_type": "online"
}
References
https://support.citrix.com/article/CTX201949 : One Public IP for AAA-TM Deployments on Citrix ADC