-
Notifications
You must be signed in to change notification settings - Fork 140
OIDC Notes
Author: Adam Fraser
Contributors: -
Reviewers: —
We want to be able to support Sync Gateway authentication using the OpenID Connect authentication protocol.
The following functionality will be delivered:
- Authentication using the OpenID Connect Authorization Code Flow
- Authentication using the Implicit Flow
- Authentication and stateless session management using a validated ID token.
- Token refresh when using ID token in conjunction with Authorization Code Flow or Implicit Flow
- Option for user creation on first sign-in (similar to what's done for Facebook auth today)
The following functionality will not be delivered:
- Sync Gateway as an OpenID Connect Provider/IdP
- Authentication using the Hybrid flow
- Create stateful session (existing SG session model) after authentication via Implicit Flow
- Create stateful session (existing SG session model) after authentication via Auth Code Flow
- ID token validation based on validation key
- Use ID token for stateless sessions, instead of session tokens
- Refreshing expired ID tokens using cached refresh, access tokens
- Leverage existing libraries that are proven, stable and actively maintained for the standard OpenID Connect flows, where possible.
- Adhere to security standards for caching and management of tokens.
- Implementation should be straightforward for client apps to interact with.
- Implementation should be straightforward for users to configure on the Sync Gateway side.
The following libraries are recommended to be used:
- https://github.com/coreos/go-oidc for Auth Code and Implicit flows
- https://github.com/auth0/go-jwt-middleware for ID token validation
The OpenID Connect spec can be a bit inconsistent in their use of terms for the three participants in the authentication flows. Here we'll try to adhere to the following terms:
- OpenId Connect Provider (OP) An OAuth 2.0 Authorization Server that authenticates the end-user.
- Relying Party Sync Gateway in our case; the application that the end-user is trying to access. The RP is sometimes referred to as 'client' in the OpenID Connect docs, because the RP is the client of the OP API. Will try to only refer to it as 'Relying Party' here to avoid confusion with clients of the SG REST API.
- End-user The end user trying to authenticate against the relying party. For our case it's any consumer of the SG public API - either Couchbase Lite, or a web application targeting the REST API directly.
We want Sync Gateway support two of the standard OIDC authentication flows.
- The Implicit Flow is the preferred flow for mobile applications, as it supports secure client storage of a refresh token. This allows clients to avoid forcing users to re-enter username/password information every time their current session expires.
- The Authorization Code Flow is the preferred flow for browser-based applications, or any other client that doesn't have secure storage for a refresh token.
The Auth Code flow supports authentication without revealing access/refresh tokens to the end-user, and so is the recommended approach for non-mobile clients (browser/REST API).
The Implicit flow allows clients to securely store refresh tokens locally, to avoid repeated end-user authentication against the OP.
The following database-level config properties will be added to Sync Gateway to support OIDC, in an oidc
map.
Name | Value |
---|---|
oidc_discovery |
URL of OP discovery endpoint |
client_id |
Client ID defined for Sync Gateway in OP |
register |
Whether SG should auto-create users |
validation_key |
Key used to validation ID tokens |
signing_method |
Signing method used for validation key (optional, provides additional security) |
The following new API endpoints will be added to Sync Gateway to support the OIDC Authorization Code flow.
Called by clients to initiate the OIDC Authorization Code flow. The incoming scope allows clients to specify whether they are using the authorization code (openid
) or implicit (openid offline_access
) flow.
####Request
Name | Value |
---|---|
offline |
When true, requests a refresh token from the OP. Sets access_type=offline and prompt=consent on the redirect to the OP. Secure clients should set offline=true and persist the returned refresh token to secure storage. |
####Response If OIDC is configured for the DB, Sync Gateway will return a redirect to the OP, in the format described here.
Notes on redirect parameters as used by Sync Gateway:
Name | Value |
---|---|
response_type |
code |
client_id |
OP Client identifier, as defined in SG database config |
scope |
openid |
redirect_uri |
https://{sg public interface}/{db}/oidc_callback |
state |
Generated value for CSRF mitigation |
The callback clients are redirected to after successful authentication against the OP.
###Request Parameters
Name | Value |
---|---|
code |
OIDC authentication code (auth code flow) |
id_token |
ID token (implicit flow) |
state |
Generated value for CSRF mitigation |
###Response Values
Name | Value |
---|---|
id_token |
JWT Token to be used for authentication in subsequent API requests |
Used to obtain an new ID token, based on authentication with a valid ID token. Intended for use with the authorization code flow, for web clients that are managing their own ID token lifecycle without exposing the refresh token to the end-user. Uses a refresh_token stored internally by Sync Gateway to obtain the new ID token without requiring end-user re-authentication against the OP.
###Request Parameters
Name | Value |
---|---|
refresh_token |
Refresh token (optional, used by implicit flow) |
###Response Values
Name | Value |
---|---|
id_token |
JWT Token to be used for authentication in subsequent API requests |
The ID token should be set by end users as a bearer token in the Authenticate header. Incoming bearer tokens will be validated using the go-jwt-middleware library, based on the validation key and (optional) signing method.
In the auth code flow, clients must refresh their ID token before it expires, using the {db}/oidc_refresh endpoint.
For the implicit flow, clients can refresh their ID token
Bug# | Description |
---|---|
- | Are there client enhancements required to properly handle the redirect responses coming from Sync Gateway? |
- | Should the GET /{db}/oidc/ request take a flow_type parameter (values implicit/authcode) instead of the actual scope that gets passed to the OP? Current proposal is scope, as it reduces the risk of API signature changes if we want to support other flows in future. If we leave it as scope, however, should we enforce only the tested/supported values? (openid , openid offline_access ) |
- | Should we support clients using cookies to provide the ID token? |
- | If oidc is configured for a database, should we still fall back to a basic auth check if a bearer token isn't present? |
- | Do we support dynamic registration of Sync Gateway as an OIDC RP in 1.3? (http://openid.net/specs/openid-connect-registration-1_0.html) |
- | Need ability to handle non-standard auth endpoint parameters. For example, [Google's OpenID Connect endpoint requires setting the access_type to get a refresh token] (https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters). This differs from the offline_access scope defined in the OIDC spec. A possible implementation would be to allow users to include these optional parameters in the URL specified in the config (this is the approach used by Salesforce for RP config) |
Bug# | Description |
---|---|
- OpenID Connect core spec
- OpenID Connect Auth Code Flow Implementer's Guide
- OpenID Connect Implicit Flow Implementer's Guide
- Auth0 notes on refresh tokens
- Auth0 jwt go library
- coreos oidc go libraries
- Set up your app definition in Google. This is steps 1-5 in this documentation. At step 5, you can use localhost:4984 as YOUR_NAMESPACE for testing purposes.
- Set the OIDC properties in your Sync Gateway database config, similar to the following:
"oidc": {
"issuer":"https://accounts.google.com",
"client_id":"[AS_DEFINED_IN_STEP_1]",
"validation_key":"[AS_DEFINED_IN_STEP_1]",
"callback_url":"http://localhost:4984/default/_oidc_callback",
"register":true
},
- The test OP is enabled per database, add the following to Sync Gateway database config:
"unsupported": {
"oidc_test_provider": {
"enabled":true
}
},
- Set the OIDC properties in your Sync Gateway database config, similar to the following:
"oidc": {
"providers": {
"test": {
"issuer":"http://localhost:4984/db/_oidc_testing",
"client_id":"sync_gateway",
"validation_key":"R75hfd9lasdwertwerutecw8",
"callback_url":"http://localhost:4984/db/_oidc_callback"
}
}
}
The issuer
URL must point to the database containing the config suffixed with /_oidc_testing
.
The client_id
value must be "sync_gateway"
The validation_key
can be set to any value, the OIDC client and the testing OP will use for token requests.
The callback
URL must point to the database containing the config suffixed with /_oidc_callback