The Nonce Authenticator Pattern

The Nonce Authenticator Pattern

On this page

In some OAuth application scenarios, there may be technical barriers that prevent a Single Sign-On (SSO) solution from working as intended. This can lead to end users having to perform an initial login, then being prompted very soon afterwards to sign in again. When software companies consider this a blocking issue and need a workaround, the nonce authenticator pattern can be used.

Mobile Web Use Case

Single Sign-On may not work reliably when different applications use different cookie jars. This is often the case for a web view, which uses a private browser session. Another example is on iOS, where a mobile app uses an ASWebAuthenticationSession window, and a web app usually uses the Safari browser. Cookies are not shared between these browsers, which can prevent SSO from working.

Insecure Solutions

One attempt to work around the problem might involve passing a token in a URL, as in the following example. In scenarios where mobile web views are used, it is also possible to use a Javascript Interface, to call from the web view and pull a token from the mobile app.

text
1
https://www.example.com/mylocation?token=abc123...

These solutions will not work when the web app uses HTTP-only cookies. They are also not secure designs, since tokens should not be passed in URLs. Doing so could reveal them in the browser history or server logs. Different apps should not share tokens, since this can lead to escalation of privileges in some cases. Instead, each client application must receive tokens issued to itself, with the expected scopes and claims.

One-time Tokens

Whenever you need to pass tokens in URLs, use a nonce as a one-time token. Your authorization server should provide a flow for issuing these to applications. A nonce is safe to use in a URL because it is a number that can only be used once, and is very short lived. So even if a nonce is revealed in the browser history or server logs, it cannot be exploited.

Traditionally, a client makes use of SSO to seamlessly authenticate and obtain tokens. However, SSO commonly relies on cookies and if for some reason these are not sent or accessible, the user will be reprompted for authentication. To avoid this, pass a one-time (authentication) token, the nonce.

Creating a One-time Token

To create a nonce, the source application sends its ID token as a proof, to the nonce issuing endpoint of the authorization server. The ID token must also include the nonce endpoint in its configured audiences, as in this example ID token payload:

json
12345678910111213141516171819202122
{
"exp": 1670844872,
"nbf": 1670841272,
"jti": "d86bc4a8-9107-4d49-89ef-7ed6b6551b10",
"iss": "https://login.example.com/oauth/v2/oauth-anonymous",
"aud": [
"mobile-client",
"https://login.example.com/authn/anonymous/nonce1"
],
"sub": "demouser",
"auth_time": 1670841272,
"iat": 1670841272,
"purpose": "id",
"at_hash": "Q3ej554syBcZfy89CWd8wA",
"acr": "urn:se:curity:authentication:html-form:htmlform1",
"delegation_id": "7b5f9257-031e-44b4-b2a8-344810fb03dc",
"s_hash": "oOe-4pj1BjluIopExD-dwA",
"azp": "mobile-client",
"amr": "urn:se:curity:authentication:html-form:htmlform1",
"nonce": "B_lOPl85v4y_BRfTY-FK7T5xVPqY4cZ6ixgnoWNzRag",
"sid": "bSziokYTJRNHvbn4"
}

The following POST shows the input in an example request to get a nonce:

bash
123
curl -X POST 'https://login.example.com/authn/anonymous/nonce1' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'token=eyJraWQi...'

The nonce issuing endpoint will cryptographically verify the signature of the ID token, then check its issuer, audience and expiry. The required audience will be the HTTPS URL of the nonce issuing endpoint. If all checks pass, a nonce will be issued and returned to the source application:

json
123
{
"nonce": "OFiicYQJYY2phWnD5nFMflid5Du82ycW"
}

The source application can then navigate to the target application and supply the nonce as a query parameter:

text
1
https://www.example.com/mylocation?nonce=OFiicYQJYY2phWnD5nFMflid5Du82ycW

Authenticating with a One-time Token

The target application then needs to run an OpenID Connect flow that includes the nonce. The authentication request will use the acr_values field to ensure that the nonce authenticator is used. It will also send the nonce in the login_hint_token field, and prompt=login to ensure that the nonce is used:

text
1234567891011
http://login.example.com/oauth/v2/oauth-authorize
?client_id=web-client
&redirect_uri=http%3A%2F%2Fwww.example.com%2F
&response_type=code
&code_challenge=l9QIPE4TFgW2y7STZDSWQ4Y4CQpO8W6VtELopzYHdNg
&code_challenge_method=S256
&state=NlAoISfdL1DxPdNGFBljlVuB1GDjgGARmqDcxtHhV8iKNYu6ECS2KOavDHpI3eLN
&scope=openid%20profile
&login_hint_token=OFiicYQJYY2phWnD5nFMflid5Du82ycW
&acr_values=urn:se:curity:authentication:nonce:nonce1
&prompt=login

This redirect will be to the authorization endpoint of the authorization server, after which a temporary cookie is set and there is a second redirect to the nonce authenticator.

iframe redirects

Running this redirect on a hidden iframe in a web client will not work as expected, unless the web app shares the same parent domain as the authorization server. This is due to recent browser restrictions on third party sites, that cause the temporary cookie to be dropped.

Mobile Web Code Example

The Mobile Web SSO code example provides an end-to-end solution that you can run from a development computer, to demonstrate the use of the nonce authenticator pattern. Basic Android and iOS mobile clients are provided, along with a minimal web application that can be run in a web view or system browser.

Conclusion

The nonce authenticator pattern enables Single Sign-On navigation from a source application to a target application. It does so by creating a short-lived one-time token, using the ID token of the source application as a proof. This nonce is then used to bootstrap a session in the target application. Usage should be restricted to specific clients, who opt into allowing the nonce authenticator, by including it in their audience restrictions.