In this post, let’s examine how to integrate OpenID Connect authentication with the XenApp (XA) environment.
The integration will allow a user to login through Google and seamlessly launch a published XenApp application, without providing Active Directory (AD) creds.
For this post, the user is given ‘https://oauth2.lab.com’. As the user browses to the URL, they are directed to Google for authentication. After logging in through Google, using a Gmail address and password, the user is presented with published XenApp applications in NetScaler Gateway. The application launches with no additional authentication prompt – No requirement for Active Directory creds.
For our endeavor, we will leverage a few new NetScaler 11.0 features, listed as follows:
- oAuth 2.0 (Under AAA)– providing OpenID Connect authentication
- Unified Gateway – unifies AAA and NetScaler Gateway (NG) authentication
- Content Switch – The ability to switch traffic to a NG vServer. Previously traffic can only be switched to a LB vServer
Additionally, the following StoreFront (SF) features are put into action:
- Protocol Transition through SmartCard authentication
- Kerberos Constraint Delegation (KCD) for XA6.5 Delivery Controllers (XML Brokers)
Finally, the following Active Directory features are required, as well:
- Kerberos and Delegation
- Explicit User Principal Name (eUPN) and Implicit UPN (iUPN)
To deliver the aforementioned user experience, four (4) rounds of Single Sign-On (SSO) must happen in the background. They are listed, as follows, in chronological order:
- Google to NetScaler (AAA) through OpenID Connect
- NetScaler (AAA) to NG through Unified Gateway
- NG to SF through SmartCard authentication
- SF to XA Delivery Controller and Session Hosts through Kerberos Constraint Delegation (KCD)
In the following sections, we will delve into technical details, which made our user experience possible.
OpenID Connect / oAuth 2.0
We use OpenID Connect to offload authentication from NetScaler Gateway to Google.
oAuth 2.0, an authorization framework, is described here at https://tools.ietf.org/html/rfc6749.
OpenID Connect, an identity layer built on top of oAuth 2.0, making it an authentication protocol, is described here at http://openid.net/connect/faq/
The purpose of OpenID Connect, is to provide the ability for a web application to offload authentication to a third party.
The following screenshot demonstrates that you can sign up or log into Quora through third party authentication providers, such as Google, Facebook or Twitter.
To understand how the protocol works in a nut shell, and its implementation on the NetScaler, please take a look at below diagram.
Hopefully, the pictorial depiction of traffic flow, above, is straightforward. If you fancy the hundred page-long protocol specification, please find links in the prior section.
oAuth 2.0 happens between flow 4 to 7.
OpenID Connect, an identity piece built on top of oAuth 2.0, is shown in flow 8 and 9.
If you are familiar with SAML, you might notice that the abovementioned communication flows share a few similarities.
However, in SAML, the Service Provider (SP) and the Identity Provider (IDP) never communicated between themselves via a physical network connection, as the messages are relayed via the user agent (e.g. web browser) through HTTP redirects.
In oAuth 2.0 / OpenID Connect, a direct network connection between the NetScaler and Google is required, supporting flows from 6 to 9.
In order to use oAuth 2.0 with Google, you must obtain oAuth 2.0 credentials, such as client ID and client secret that are known to both Google and the NetScaler. This process is documented by Google at https://developers.google.com/identity/protocols/OAuth2?hl=en
The following screenshot shows what this might look like.
Once the details are obtained from Google, we can then configure the NetScaler accordingly, as shown below.
Since OpenID Connect / oAuth 2.0 is an advanced authentication feature, it falls under AAA, and is therefore not available as an authentication option for NG.
As a result, the only way to use them involves binding oAuth policy to an AAA vServer and then associate the AAA vServer to a LB vServer.
Let’s take a look at how they work in practice.
Below screenshot is a client side HTTP traffic trace, it captures HTTP transactions over the authentication process. Traffic not relevant to authentication is greyed out.
Please note that HTTP is a transaction based protocol, meaning a HTTP Request must correspond to a HTTP Response. Request is shown above Response, and the two are separated by a blank line, in below analysis.
For brevity, only relevant info within each HTTP transaction will be shown.
Transaction 1 (Number shown on the left), below, shows that the user is redirected to Google for authentication, via a HTTP 302 response, which provides the URL for the next HTTP request.
The ‘Location’ header value in HTTP response contains information obtained at oAuth registration with Google. E.g. client ID
Transactions 2 ~ 13 (greyed out), involving Google login processes, are not relevant, hence skipped for brevity.
Transaction 14, below, shows that the user is redirected back to the NetScaler (https://oauth2.lab.com), via a HTTP 302, after having authenticated successfully at Google.
Please note that grant code (4/NdXsMCIwy38cCVeHg7tyJfBlR2bYL8m4Dz6YNUD8_ss) is returned by Google.
The following shows request portion of transaction 15, which matches the ‘Location’ header value (URL) of HTTP response in Transaction 14.
The above GET request, forwards grant code to the NetScaler, as is indicated by the ‘Host’ header.
Once the NetScaler received the grant code, it subsequently contacts Google in the background, submits the grant code, in exchange for an Access Token.
As stated earlier, this communication happens directly between the NetScaler and Google, and is therefore not available in the client side trace, shown throughout.
However, the following text extracted from NetScaler log, highlighted in red, shows that Access Token.
Authorization is granted once the NetScaler received this Access Token from Google.
This concludes oAuth authorization.
As mentioned prior, oAuth is an authorization framework, which does not reveal user identity.
OpenID Connect, built on top of oAuth, is an authentication protocol. As such, id_token, shown above, highlighted in blue, containing encrypted user identity info, is also returned by Google.
The following log shows that the NetScaler makes a second call to Google, decrypts id_token, and consequently obtains user identity information (e.g. Gmail address).
This concludes OpenID Connect authentication.
Once OpenID Connect completes successfully, the NetScaler creates a session under AAA, sends the user AAA cookies (shown in red below, Response portion of Transaction 15), and redirects the user to the initial requested resource (https://oauth2.lab.com/), via a HTTP 302.
Please note that HTTP is not a stateful protocol by itself, and cookies are used to track states.
In subsequent HTTP requests, as long as NSC_TMAA and NSC_TMAS cookies are present, and have the correct values, the NetScaler will serve requested resources, bypassing authentication.
So the user has authenticated at the NetScaler through OpenID Connect, what next?
How can we leverage an authenticated session and hook it to NetScaler Gateway, and ultimately XenApp?
The hook up, requires Unified Gateway, a NetScaler 11.0 feature, which ties AAA and Gateway authentication together. In other words, with Unified Gateway, we can transition an AAA session into a NG session, and vice versa.
How does this unification work?
At a low level, when AAA cookies are presented to NG, Gateway verifies if they are valid AAA cookies, if so, creates a Gateway session, and issues the Gateway cookie.
Transaction 17, below, shows that request for ‘/vpn/index.html’, destined to Gateway, contains the AAA cookies (NSC_TMAA and NSC_TMAS).
Upon validation of the two (2) AAA cookies, the NetScaler creates a Gateway session, and subsequently sets the Gateway cookie (NSC_AAAC) in its response.
As a result, as long as the Gateway cookie is present in all follow up requests, no authentication is required.
In order to achieve the aforementioned session transitioning, the ‘loginOnce’ option, provided by Unified Gateway, must be turned on at the Gateway vServer, as shown below.
So far we have covered how to setup oAuth 2.0 / OpenID Connect, which requires a LB vServer and its associated AAA vServer; session migration from AAA to Gateway via Unified Gateway.
The question is can we merge OpenID Connect and Gateway traffic such that they can share a single IP.
Fortunately, NetScaler 11.0 released a new feature within Content Switch, which allows traffic to be switched to a backend Gateway vServer, in addition to a LB vServer.
The following CS configuration shows that Gateway / StoreFront traffic, identifiable by URL path, is switched to the Gateway vServer.
Traffic not involving Gateway / StoreFront, is switched to the default LB vServer, which has the sole purpose of invoking OpenID Connect authentication at the very beginning.
‘aaa_path’, shown below, is a pre-defined pattern set on the NetScaler, which contains the following entries, is used to identify all traffic associated with Gateway. ‘Citrix’ as a URL path identifier, is used to switch traffic destined to StoreFront.
Once OpenID Connect is complete, a Responder policy is required to redirect traffic to the Gateway login page, as shown below.
The content switch evaluates the URL (/vpn/index.html) and subsequently sends matching traffic to the backend Gateway vServer.
The overall flow looks like the following,
- User enters https://oauth2.lab.com in browser and traffic hits the CS vServer
- Traffic gets switched to the default backend LB vServer
- LB vServer invokes AAA vServer and subsequently initiates OpenID Connect authentication
- Upon OpenID Connect completion, AAA creates an authenticated session and issues the user AAA cookies to maintain session
- User is redirected back to https://oauth2.lab.com by AAA, with AAA cookies
- Traffic hits the CS vServer, gets switched to the default backend LB vServer again. Due to the presence of AAA cookies, user is not challenged for authentication
- User is redirect to https://oauth2.lab.com/vpn/index.html, via a Responder policy, bound to the LB vServer
- CS vServer receives redirected traffic, switches it to the Gateway vServer, based on CS policies.
- Gateway vServer sees the AAA cookies, redeems them for a Gateway session, and issues the user Gateway cookie (NSC_AAAC)
StoreFront and Kerberos Constraint Delegation
Once the user logged into the Gateway, StoreFront kicks in.
The question is how do we SSO the user to StoreFront, XA Delivery Controllers and Session Hosts without AD credentials.
For password-less SSO, we need to leverage StoreFront SmartCard authentication, Protocol Transition and Kerberos Constraint Delegation (KCD), which is supported since StoreFront 2.6.
However, KCD is only supported on XenApp 6.5.
SmartCard authentication allows StoreFront to accept authentication without a password.
Protocol Transition allows authentication to transition from previous OpenID Connect to Kerberos for the XenApp environment.
Constraint Delegation, a secure enhancement to unconstraint delegation, introduced in Windows Server 2003, allows administrator to specify exactly which services on a downstream server (e.g. Session Host/XML Broker) can be accessed when using an impersonated user’s security context.
The followings show selected and specific StoreFront configuration items that must be correctly configured. Non-critical settings are omitted for brevity.
Within StoreFront console, Under ‘Authentication’, make sure ‘Smart card’ and ‘Pass-through from NetScaler Gateway’ are enabled.
Within ‘Pass-through from NetScaler Gateway’ authentication method, enable the following.
Within ‘Manage Delivery Controller’, make sure the host portion of the Service Principal Name for the XML broker is specified. It is typically the FQDN or hostname registered within the domain. Specifying an IP address will result in a failure in obtaining a Kerberos service ticket.
Ensure the following is enabled,
Within ‘Receiver for Web’, make sure the followings are enabled for the newly created site.
Add user or group that use OpenID Connect authentication to C:\Program Files\Citrix\Receiver StoreFront\Services\ProtocolTransitionService\AccessList.txt, assign ‘Read’ and ‘Read & execute’ access. For simplicity, ‘Domain Users’ are added.
For Kerberos Delegation, please follow Dimitrios Samorgiannidis’ rock solid blog published at /blogs/2012/03/05/troubleshooting-smart-card-sso-with-access-gateway-enterprise-edition-part-2/. Kerberos protocol is notoriously complex to understand and debug, Dimitrios’ blog provided much needed information in great detail.
In a nut shell, as is mentioned in Dimitrios’ blog.
StoreFront should delegate:
- HTTP service to all of the XML brokers (might be itself for some designs)
XML Broker should delegate:
- CIFS & LDAP (all Domain Controllers)
- HOST (all XenApp servers in the same farm)
- HOST to itself
- HTTP to itself
XenApp should delegate:
- CIFS & LDAP (all Domain Controllers)
- HOST to itself
- HTTP service to all of the XML brokers
The next question is, since Google ID and AD username are completely separate, how do we link Google ID to an AD user?
In AD, there is a LDAP attribute, User Principal Name (UPN). A UPN can be implicitly or explicitly defined. An implicit UPN is of the form username@domain. An explicit UPN is of the form name@suffix, where name and suffix can be any arbitrary value. Both UPN, although defined differently, link to the same user.
The following screenshot shows that Google ID is linked to AD user ‘chris’.
The following screenshot shows that Kerberos is using the Gmail address as the Principal, when requesting a service ticket.
The following shows that once the user logged in, user is identified as AD user ‘chris’.
In summary, we looked at OpenID Connect authentication, Unified Gateway, Content Switching, supporting configuration on StoreFront and Kerberos Constraint Delegation.
Hope you have enjoyed the ride!