Initial implementation of server-side auth
Fixes #221 (closed), #219 (closed).
Backend
This MR implements the authorization code flow as defined in the OAuth2 specification. A login request is initiated when a user agent navigates to /api/auth/login
. This login endpoint does the following:
- it generates a cryptographic nonce which is stored encrypted as a cookie,
- constructs a URL which can be used to authorize the user using the OAuth Provider,
- this URL contains an opaque string parameters (
state
) which we use to save the redirect_url & the nonce, - we then redirect the user to that URL
After the user completes the login action he gets redirected back to /api/auth/callback
where the callback handler is executed. There we
- check whether the state we get as a query parameter has a matching nonce,
- extract the authorization code passed as a query parameter,
- use the code and our client_secret to request a set of tokens,
- store these tokens and redirect the user back to the path they came from.
The logout endpoint simply clears all of these cookies by responding with set-cookie headers which have an expiration date in the past.
A /api/auth/refresh
endpoint can be used by the FE to ensure that the cookies always contain valid tokens. Before they expire the client simply has to create a request to the endpoint, the backend will then exchange the refresh token + client_secret for a new token set.
Frontend
We use a non-httpOnly cookie to detect the validity of the tokens stored in our cookies (which the frontend can't read because they are httpOnly). We schedule a /refresh
request just before the access token expires and once the token is about to expire also block new API calls by awaiting a global promise.
Deployment
Code flow has to be enabled prior to a production deployment. Legacy user session themselves will continue to work, the auth_backend.py
changes are backwards compatible and will accept requests from old frontend instances.
TODO
-
Check if refreshing really work -
Figure out how to handle CNAMES <- help wanted