Replacing Session Tokens with OAuth Access Tokens
Summary
Using OAuth 2 to authenticate with Synapse has many benefits over using older authentication mechanisms. We can try to consolidate authentication services to using OAuth flows wherever possible. This document focuses on replacing session tokens with OAuth access/refresh tokens for first-party browser-based requests.
We primarily use the session token to authorize a user by storing it in the browser in a *.synapse.org HttpOnly cookie. On the client side, the same mechanism can be used with OAuth access tokens (and optionally, refresh tokens).
These access and refresh tokens can be bound to our bootstrapped, ‘first-party’ OAuth client with ID 0. Currently, Client 0 is only used to generate internal access tokens. Client 0 cannot be used to issue tokens with the authorization code flow, so users can only generate these external access tokens using their username and password, or authentication with an external identity provider.
Open question: should our default approach be extending the login services, or deprecating them for new ‘v2’ services? (If we want to eventually get rid of session tokens, it may be easier to ensure clients are using the a new login endpoint, rather than potentially modifying a response body.
To use OAuth tokens in place of session tokens, we must
Add functionality to return a client 0 bound access token (and optional refresh token) when
A user authenticates with username and password
A user authenticates with an external IdP (e.g. Google)
Allow client 0 to refresh tokens without a password (see also: Requirements for OAuth 2 public clients)
Permitting the creation of public clients is not necessary for this feature, but may influence the design/implementation because client 0 is a kind of public client because it has no credentials--but it’s also kind of not a public client because it is bootstrapped and first-party only.
Extend services that require a session token to accept an access token
POST /termsOfUse
Services
If we have the opportunity, we can also clean up the API a bit (decisions depend on whether these services are new
LoginResponse could extend Session (LoginResponse contains the same fields, and an authenticationReceipt)
Endpoint | Request Body | Response Body | Notes |
---|---|---|---|
LoginRequest may support an additional boolean In addition to the existing fields, LoginResponse will include The tokens are bound to client 0, the “first-party” Synapse OAuth client. | |||
This is the default login endpoint for users who sign in through external IdPs, like Google. Session can be extended to return an | |||
None | Extension/replacement of Session as stated above, requiring a valid This request requires a Session because a user must agree to the terms of use before a token can be used to authenticate. |
Other Considerations and Questions
Should access/refresh tokens issued to client 0 have different durations?
Should we implement the single-use refresh token revocation scheme outlined in Requirements for OAuth 2 public clients?
Refresh tokens are already single-use. The gist of the extension is that if an expired refresh token is used, the related active refresh token is also expired.