Sometimes an Hypermedia Authentication API (HAAPI) flow requires the use of a browser window to be completed. This can happen for two main reasons:
Note
The first reason will not be the case by the time HAAPI support is finalized.
To handle this scenario, it is possible for the HAAPI flow to require the creation of a browser window to complete part of the flow. On a native client this may be achieved by using the system browser or one of the methods recommended on RFC 8252. On a browser-based client, a solution is to open a separate window or tab, so that the client doesn’t loose its state.
To illustrate how this is achieved, in this section we describe a flow using an external SAML identity provider.
The initial part is similar to the previous examples and we will not be showing it here: the client starts with an authorization request, is redirected to the authentication service and receives an authenticator selection representation.
If the user selects a SAML authenticator, then the client performs a GET request to the associated href:
GET
href
GET /dev/authn/authenticate/saml1 HTTP/1.1 Host: example.com Accept: application/vnd.auth+json Authorization: DPoP ey...-g DPoP: ey...ww
The response is an authentication step containing the special client-operation action:
client-operation
HTTP/1.1 200 OK Content-Type: application/vnd.auth+json { "type": "authentication-step", "actions": [ { "template": "client-operation", "kind": "external-browser", "title": "The authentication process needs to use an external browser", "model": { "name": "external-browser-flow", "arguments": { "href": "https://localhost:8443/dev/authn/authenticate/saml1?_launch_nonce=Gxs557NFwUTe5kwH8GjFK3MENoQVbHLe", }, "continueActions": [ { "template": "form", "kind": "continue", "title": "If you are not redirected automatically, click here to continue authenticating", "model": { "href": "https://localhost:8443/dev/authn/authenticate/saml1", "method": "GET", "type": "application/x-www-form-urlencoded", "fields": [ { "name": "_resume_nonce", "type": "context" } ] } } ] } } ] }
It is the presence of this client-operation action with the name field, present inside model, set to external-browser-flow that signals to the client that an external browser needs to be used to continue with the flow. The action’s href field, present inside arguments, contains the URL where the browser window should be opened. The client should react to the previous response by opening a browser window/tab to that URL, eventually after requesting permission from the user and showing the action’s title string.
name
model
external-browser-flow
arguments
title
The client then needs to wait until the external browser sub-flow is completed before resuming the HAAPI flow, using the action inside continueActions. That is triggered by the browser sending a nonce back to the client, which is then used as the source for the context field in the continuation action. The way this information is passed back to the client depends on the client type.
continueActions
context
On a native client, the browser can be redirected to the application by using an HTTP URI or a custom scheme URI associated to the application. The nonce will then be present in the query string. The redirect URI needs to be registered for the client and also needs to be passed on the browser launch’s URL (see redirect_uri query-string parameter):
redirect_uri
https://example.com/dev/authn/authenticate/saml1?_launch_nonce=cE...EB&redirect_uri=https://client.example.net/client-callback
On a browser-based client, the external window posts a message (via postMessage) to the opener window, i.e., the window where the HAAPI client is running. The nonce will be present in that message. This means that the client application, i.e. the opener window, can receive the nonce via an event listener for the message type. To trigger this behavior, the for_origin needs to be passed on the browser launch’s URL:
postMessage
message
for_origin
https://example.com/dev/authn/authenticate/saml1?_launch_nonce=cE...EB&for_origin=https://client.example.net
In this case, the client should also validate the nonce’s origin, namely the postMessage source window.
Upon receiving the nonce, the client performs the action inside continueActions, using the nonce as the source for the context type field:
GET dev/authn/authenticate/saml1?_resume_nonce=t9...kH HTTP/1.1 Host: example.com Accept: application/vnd.auth+json Authorization: DPoP ey...-g DPoP: ey...1A
If this SAML authenticator is the only one required authenticator, then the authentication process is completed and the response is a redirect back to the token service:
HTTP/1.1 200 OK Content-Type: application/vnd.auth+json { "type": "authentication-step", "actions": [ { "template": "form", "kind": "redirect", "model":{ "href": "/dev/oauth/authorize?client_id\u003dhaapi-client", "method": "POST", "type": "application/x-www-form-urlencoded", "title": "Login", "actionTitle": "Please click this button if you are not redirected", "fields": [ { "name": "token", "type": "hidden", "value": "xk...5s" }, { "name": "state", "type": "hidden", "value": "R_...SX" } ] } } ] }
When following this last redirect:
POST /dev/oauth/authorize?... HTTP/1.1 Host: example.com Accept: application/vnd.auth+json Content-Type: application/x-www-form-urlencoded Authorization: DPoP ey...6w DPoP: ey...Kg token=...&state=...
The response is an authorization response, similar to the one described in the previous examples:
HTTP/1.1 200 OK Content-Type: application/vnd.auth+json { "type": "oauth-authorization-response", "properties": { "code": "3H...h3", "state":"..." }, "links": [ { "href": "https://client.example.net/client-callback?code\u003d3H...h3\u0026state\u003d...", "rel": "authorization-response" } ] }