# OIDC Authentication

Authentication filter has all the information needed to initiate an authentication handshake with an OpenID Connect provider. It begins by checking whether a request contains an access token in a specified location (header, query string, or cookie). If it exists, it assumes that the token was verified at least once by previous filters in the chain and passes the request onto the next filter. If an access token was not found, it will check for the query token to see if there is an access code. This happens when a request is coming back from the identity provider (specified by callback URL). If the code is found, it will exchange it for a bearer token and an id token - both of them will then be stored in specified locations. If no access code was found, the authentication process gets kicked off by forwarding the user to the identity provider.

## Filter Configuration Options

| Name                               | Type                                         | Default | Example                                                    | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ---------------------------------- | -------------------------------------------- | ------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| accessToken.location               | enum\[header, cookie, queryString, metadata] | header  |                                                            | The location where the filter expects an access token to be.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| accessToken.key                    | string                                       | ""      | access\_token                                              | The key of the access token in the above location.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| accessToken.metadataFilter         | string                                       | ""      | "gm.oidc\_validation"                                      | The name of the filter to read dynamic metadata from. Required if accessToken.location=metadata                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| accessToken.cookieOptions.httpOnly | bool                                         | false   | true                                                       | Whether the cookie being created should be [httpOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies).                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| accessToken.cookieOptions.secure   | bool                                         | false   | true                                                       | Whether the cookie being created should only be sent to the server over HTTPS.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| accessToken.cookieOptions.maxAge   | string                                       | ""      | 12h                                                        | The `Max-Age` of the new cookie. The value is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "s", "m", "h" ("ns", "us"/"µs", and "ms" are also valid but the value gets rounded to the nearest second as `Max-Age` is defined as "number of seconds until the cookie expires"). If `maxAge` is not set, the cookie will have `Expires/Max-Age` of `Session`.true. If the access token expires before the specified max age, the actual token expiration is used instead. |
| accessToken.cookieOptions.path     | string                                       | ""      | /                                                          | Path indicates a URL path that must exist in the requested URL in order to send the Cookie header.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| accessToken.cookieOptions.domain   | string                                       | ""      | \*.greymatter.io                                           | Domain specifies allowed hosts to receive the cookie. If unspecified, it defaults to the host of the current document location, excluding subdomains. If Domain is specified, then subdomains are always included.                                                                                                                                                                                                                                                                                                                                                                |
| idToken                            |                                              |         |                                                            | idToken block is optional. If there is no need to keep idToken, remove this block entirely.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| idToken.location                   | enum\[header, cookie, queryString, metadata] | header  |                                                            | The location where the filter expects an ID token to be                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| idToken.key                        | string                                       | ""      | id\_token                                                  | The key of the ID token in the above location                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| idToken.cookieOptions.httpOnly     | bool                                         | false   | true                                                       | Whether the cookie being created should be [httpOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies).                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| idToken.cookieOptions.secure       | bool                                         | false   | true                                                       | Whether the cookie being created should only be sent to the server over HTTPS.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| idToken.cookieOptions.maxAge       | string                                       | ""      | 12h                                                        | The `Max-Age` of the new cookie. The value is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "s", "m", "h" ("ns", "us"/"µs", and "ms" are also valid but the value gets rounded to the nearest second as `Max-Age` is defined as "number of seconds until the cookie expires"). If `maxAge` is not set, the cookie will have `Expires/Max-Age` of `Session`. If the ID token expires before the specified max age, the actual token expiration is used instead.          |
| idToken.cookieOptions.path         | string                                       | ""      | /                                                          | Path indicates a URL path that must exist in the requested URL in order to send the Cookie header.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| idToken.cookieOptions.domain       | string                                       | ""      | \*.greymatter.io                                           | Domain specifies allowed hosts to receive the cookie. If unspecified, it defaults to the host of the current document location, excluding subdomains. If Domain is specified, then subdomains are always included.                                                                                                                                                                                                                                                                                                                                                                |
| serviceUrl                         | string                                       | ""      | localhost                                                  | The host name of the application. When a user signs in through the OAuth provider, they will need to be redirected back to your application; this host name will be used during the redirect.                                                                                                                                                                                                                                                                                                                                                                                     |
| callbackPath                       | string                                       | ""      | /ping                                                      | The path of the callback API. The callback URL gets constructed with the combination of `serviceUrl` and  `callbackPath`.                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| provider                           | string                                       | ""      | [https://accounts.google.com](https://accounts.google.com) | The url for the OpenID connect provider to use. This is used to determine the particular OAuth endpoints.                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| clientId                           | string                                       | ""      | 12h                                                        | The public identifier registered with the OAuth authorization server.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| clientSecret                       | string                                       | ""      | secret                                                     | The secret known only to the application and the authorization server.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| additionalScopes                   | \[]string                                    | \[]     | email, profile                                             | Any additional scopes to `openid`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |

## Design Decisions

### Access token and ID token locations

All three location types work just as well for the filter to read from. For storing the newly acquired bearer token and ID token, however, it is important to keep in mind there will be redirects involved in the equation.

If you choose `header` for storing an access token, the service that sits behind this proxy may or may not see this header. Let's break this down to two scenarios:

* If a user is already authenticated and have an access code in the request header, the service will see this token because this filter will just let the request pass through.
* If a user is in the middle of authentication process and the filter just exchanged an access code with a bearer token, the filter will attach the newly acquired token to the response header and send back a `302 Found` response to the user. The user's browser will then see that this response has [`Location` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location) set, and make a new request to the location specified. So the only audience of the token headers (if you so choose) is the user while the service behind this proxy will not see the token. In most cases, this is not what you want to configure to.

If you choose `queryString`, the filter will append the token(s) to the URL that the user was originally trying to get to (before being redirected to authenticate). So the service behind this proxy will be able to read them.

`cookie` is the most straight forward of the three. When the 302 response goes back to the user, it will set the cookie on their browser (which will be visible from the service when a new request gets created).

### [State Parameter](https://auth0.com/docs/protocols/oauth2/oauth-state)

Although the main purpose of using the state parameter is to mitigate CSRF attacks, we are currently using this parameter to store the original URL that a user was trying reach before he/she was redirected to Identity Provider for authentication. This was taken from the existing implementation of the OpenID Connect authentication filter (`gm.oauth`), and something to be aware of moving forward.
