Pin it
4 1 1 1 1 1 1 1 1 1 1 Rating 4.00 (1 Vote)

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, Netscaler ADC acts as OpenId Connect SP protecting a web application with Google Identity Plaform acting as Identity Provider. Netscaler 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 Netscaler 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.

Netscaler ADC high level design for OpenId connect authentication

 

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"
 ]
}

Netscaler configuration

Netscaler platform & limitations

Netscaler 12.0 build 58.15 has been used for this scenario. Netscaler 12.0 can act as an OpenID Connect SP or IDP :

  • When acting as SP (Service Provider), Netscaler 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), Netscaler 12.0 doesn't support custom attributes insertion in the ID token.

Enterprise or Platinium license is required to unlock Netscaler authentication features.

Content-Switching virtual server

The Citrix NetScaler ADC content switching feature enables the NetScaler 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.

The expression is_vpn_url matches the majority of Netscaler ADC AAA URL pattern, but doesn't match oauth2 URL patterns yet. The specific HTTP.REQ.URL.STARTSWITH(\"/oauth/\") statement has to be added to the Content Switching policy to divert requests to https://<public endpoint/oauth/login (redirections from OpenId Connect IDP with Grant code) to the authentication virtual server

add cs action CS_A_AAA-Frontend -targetVserver frontend.domain-test.com_AAA

add cs policy CS_P_AAA-Frontend-rule "http.req.url.eq(\"/\").not && (is_vpn_url||HTTP.REQ.URL.STARTSWITH(\"/nf/auth/\")||HTTP.REQ.URL.STARTSWITH(\"/oauth/\"))" -action CS_A_AAA-Frontend


Detailed content switching architecture is provided below.

Netscaler ADC detailled content switching architecture for 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 Netscaler 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

Netscaler 12 OAuth action - AuthorizationEndpoint and TokenEndpoint configurationNetscaler 12 OAuth action - CertEndpoint and attribute extraction

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

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 Netscaler AAA vserver with OpenId Connect grant code
  • Netscaler 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 Netscaler 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

Netscaler OpenId Connect with Google Identity Platform flowchart

Note : Netscaler 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 NetScaler