The Gatekeeper, OAuth2 OIDC authentication handling as a microservice
Tags: oauth2, oidc, opensource, express
Published: 2020-09-18 06:59:25

## Motivation
Ever since I started programming I've been afraid of authentication. It seemes infinitely complex with sink holes around every corner. When implementing authentication in a web app, I wished login was as easy as ```html
<a href="AUTH_URL/login"></a>
``` and logout was as easy as ```javascript
axios.post('AUTH_URL/logout')
``` Since I was always dodging /outsourcing authentication, I never acquired the knowledge as to whether it was even possible. Due to a situation at work, I was forced to indulge and so; queue, the Gatekeeper.


![Alt Logo](https://dev-to-uploads.s3.amazonaws.com/i/fdmsdaj6dvh3ss74r23a.png)

The Gatekeeper API is minimal. It exposes four endpoints:
```yaml
gatekeeper.url/login?redirect=<return url>
gatekeeper.url/logout
gatekeeper.url/userinfo
gatekeeper.url/api
```
`/login?redirect=<return url>` redirects the user to the authentication provider's login screen, and makes sure the user gets returned to return url upon successful login
`/logout` logs a user out
`/userinfo` returns a JSON object containing the logged in user's info
`/api` converts cookie to authentication header and proxies requests to backend services while making sure the session stays alive. 

## What it is
* It is a service designed to handle integration against an OAuth2 OpenID Connect authentication provider. Instead of implementing the Authorization Code Flow in each of your frontends, the Gatekeeper will handle it for them.
* It's a tool for generating access tokens and refresh tokens for your web application and storing them in a best practice way. More specifically, as HttpOnly and Secure cookies.
* Ever wondered how you can set the authentication token as a HttpOnly cookie in your SPA? Gatekeeper knows. 

## What it isn't
* It's not an authentication provider, it's a tool for integrating your frontend with an OAuth2 OpenID Connect authentication provider.
* It's not a tool for validating tokens, though it can be used as such by sending the token to /userinfo and handling the 200 or 401. 

## Usage
To run the Gatekeeper in a docker container, run the following ```sh
docker run -p 4554:4554 \
  --env BASE_URL=http://localhost:4554 \
  --env CLIENT_ID=<a client id from your auth provider> \
  --env CLIENT_SECRET=<a secret for the client in the auth provider> \
  --env DISCOVERY_URL=<the discovery url for your client provider> \
  --env ORIGIN_WHITELIST=http://localhost:8080 \
  --env TOKEN_COOKIES_SECURE=false \
  docker.pkg.github.com/oslokommune/gatekeeper/gatekeeper:1.0.35
```

By navigating from your frontend application to http://localhost:4554/login, the Gatekeeper will redirect you to your auth providers login screen. Upon a successful login, the Gatekeeper will set the access token and refresh token as HttpOnly cookies. To clear these cookies and invalidate the refresh token, simply post to http://localhost:4554/logout.

To fetch information about the currently logged in user, your frontend app can GET http://localhost:4554/userinfo. Requests to /userinfo will automatically refresh the access token if need be. 

You can also configure the Gatekeeper to check and refresh the access token on demand with ```sh
  --env UPSTREAMS=my-service=http://my-service.mydomain.org
```
All the requests going through the proxy at http://localhost:4554/api/my-service/ will now get their access tokens refreshed when the need arise.

## Disclaimer
- The Gatekeeper currently only supports the Authentication Code Flow.
- The Gatekeeper should in theory support all OAuth2 OIDC providers, and it will at some point, but for now it's only been tested with Keycloak and Auth0.

## Contribution
The code is available at https://github.com/oslokommune/gatekeeper and we'd very much appreciate PR's, comments and issues.