Single signon and signout




Introduction


Most of the applications created by third parties, which will use aID as an identity service, will probably want to make the use of aID seamless to the user. For this to work, it’s important that the user only needs to log in and out once on a publication domain (most users use one publication only, but logging out will always be performed globally for all publications).

Here’s an example: Donald is not logged in to aID, he visits  Budstikka.no  and takes a look at their awesome archive. In order to do so, he needs to log in. When he logs in, he will first create an aID session, and once that’s done, the archive application will receive an access_token and the user will be logged in to the archive as well. When the user logs out, the user now expects to be logged out of the entire publication, both the normal web session, and all other OAuth applications he has used during this session. In Donald’s mind, all these applications are the same, they are Budstikka.

In order to support single signon and single signout, we have introduced some concepts that will be explained here.


Single signon


When  authorizing  your application, you will get single signon by default. If the user is logged in, the user will see no user interface, and the application will receive a code that’s linked to the user’s current web session. If the user is not logged in, he has no session, so the user will be presented with a login screen. Once the user logs in, a session is created, and the authorization completes. The application will receive a code that’s linked to the newly created session, and the user is logged in with a main aID session that will be used for ePaper, pluss articles etc (or authorizing other applications).

The problem with this solution is that the login might come as a surprise to the user. Often the application will need to inform the user beforehand that he needs to log in. To accommodate this, we have created something we call stealth mode.


Stealth mode / No prompt mode


When the application needs to present the user with a login button (or otherwise wants the user to perform an action) in order to log in, stealth mode may be used. The goal of stealth mode is to log the user in “under the radar”. We perform normal authorization, but if the user doesn’t have a session, we fail authorization instead of sending him to login.

The effect is that once the user has returned from a stealthy authorization, you know if the user has a session or not. If you now have an access_token, it succeeded. If not, the user needs to log in, and you can show the login button to trigger a non stealthy authorization.
Stealth mode is triggered by adding a parameter called stealth_mode with the value true to the authorization request (or by using prompt=none as described by OpenID). If this parameter is present, the OAuth service will skip straight from step 3 above to step 8 (see  authorization ) if the user is not logged in. If he is, it will work the same as without. The effect is that the user will never see any user interface before the browser is directed back to redirect_uri.

If stealthy login fails, stealth_login_status=failed will be appended to the redirect_uri. When this parameter is present, a pre approved ( See details ) application will know that the user is not currently logged in to aID in the current browser session. Applications that are not pre approved will also get this error when the user is logged in to aID, but has not yet granted the requested scope for the current application. The user will not see the grant scope dialogue in stealth mode, it will be rejected unless the user previously has granted the same scope, or a super set, before (ie. ‘uuid email’ will be ok if user previously granted ‘uuid email phone’, but not the other way around).

Stealth mode could also be used in an iframe to check if the user is logged in without sending the user through a long redirect chain. The application could then default to the logged out version, trigger stealth mode in an iframe, and then reload the parent if authorization was successful.


Logout cascading


When the user logs out of aID on the newspaper, the session will be invalidated. After it has been invalidated, the OAuth engine will be informed that all access_tokens created from this session should be invalidated also (and all access_grants). The effect of this is that the user will be logged out of all third party apps when he logs out.

The flip side of this is when an app revokes a token as described  here . The OAuth engine will then find all other access_tokens and access_grants created from the same session, and revoke those as well. Once that’s done, it will tell the aID session engine (checkpoint) to delete the session, which in effect logs the user out of the newspaper in the browser.

Note that the user can have multiple sessions active at any one time, in different browsers. The sessions (and related tokens) in other browsers will not be affected by the cascade.


Third party session invalidation cascade


A normal way to handle session for third party apps using OAuth is to have a separate session for that app, and store the access_token in that session. This will let the application work in a logged in state without having to call aID for each request to check if the user is logged in.

The problem with this approach is that the user will continue to be logged in even after he has logged out and the cascade has revoked the access_token. And then when the application does something that requires usage of that token, aID will respond with invalid_token, and the user will suddenly be logged out.

If your application use a session like this, you can create an endpoint that responds to HTTP DELETE on a URL that contains the access_token. We can then register that endpoint on your application in aID. When this is done, this endpoint will be called with an HTTP DELETE each time any of your application’s access_tokens are revoked.

If we configure aID with an external revoke endpoint on this form:

https://www.example.com/aid/oauth/access_token/:access_token

The aID OAuth engine will perform a request like this when the access_token d4bbad00 is revoked:

curl -X DELETE https://www.example.com/aid/oauth/access_token/d4bbad00

The application on www.example.com should then mark its internal session owning the token d4bbad00 as logged out.

The endpoint should return a 20x response indicating that it succeeded. Currently the response is ignored, and the request is never retried. For this reason it’s a good idea to not rely only on getting this DELETE, but also check every once in a while if the token is still valid.

(A note on security of this endpoint: The access_token is a shared secret between aID and your app. No other parties should know this token, and if they do, they can miss use it for worse things than logging out. No further security than HTTPS should therefor be needed for this endpoint.)


Cascading without a session


If your application for some reason can not respond to an HTTP DELETE request and thus invalidate the token, the application should check the token for each request. If this is not done, the application will think that the user is logged in, even after logout.