-
Notifications
You must be signed in to change notification settings - Fork 138
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 and stateless session management using a validated ID token.
- Token refresh when using ID token in conjunction with Authorization Code 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 Implicit or Hybrid flows
- 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 the OIDC Authorization Code Flow. This is the preferred flow for mobile applications, as it supports retrieval and 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.
An oidc
property has been added to the database configuration options in the Sync Gateway config, with the following properties
Name | Value |
---|---|
providers |
A map of OIDC provider definitions (see below) |
default_provider |
(optional) Provider to use for OIDC requests that don't specify a provider. If only one provider is specified in the providers map, it is used as the default provider. If multiple providers are defined and default_provider is not specified, requests to /db/_oidc must specify the provider parameter. |
The providers
map is a named collection of providers, with the following properties for each provider:
Name | Value |
---|---|
issuer |
The OpenID Connect Provider issuer. Sync Gateway expects to be able to retrieve the provider configuration at issuer/.well-known/openid-configuration |
client_id |
The client ID defined in the provider for Sync Gateway. |
validation_key |
Key used to validation ID tokens. |
signing_method |
(Optional) Signing method used for validation key (provides additional security) |
callback_url |
The callback URL to be invoked after the end-user obtains a client token. When using the default provider, will be of the form https://host:port/db/_oidc_callback . For a named provider, should be of the form https://host:port/db/_oidc_callback?provider=PROVIDER_NAME`
|
register |
(optional) Whether Sync Gateway should automatically create users for successfully authenticated users that don't have an already existing user in Sync Gateway. |
disable_session |
(optional) By default, Sync Gateway will create a new session for the user upon successful OIDC authentication, and set that session in the usual way on the _oidc_callback and _oidc_refresh responses. If disable_session is set to true, the session is not created (clients must use the ID token for subsequent authentications). |
scope |
(optional) By default, Sync Gateway uses the scope "openid email" when calling the OP authorize endpoint. If the scope property is defined in the config (as a map of string values), it will be used. |
include_access |
(optional) When true, the _oidc_callback response will include the access_token, expires_at and token_type properties returned by the OP. |
Sample Sync Gateway config with OIDC enabled:
{
"interface":":4984",
"log":["*"],
"databases": {
"default": {
"server": "http://localhost:8091",
"bucket": "default",
"oidc": {
"default_provider":"google",
"providers": {
"google": {
"issuer":"https://accounts.google.com",
"client_id":"279085463427-b4tluo601dovlf1ks4kk4p8tgkps9uso.apps.googleusercontent.com",
"validation_key":"FfjeQU2nwUauWA2zhwQuRcw8",
"callback_url":"http://localhost:4984/default/_oidc_callback",
"register":true,
"disable_session":true
}
}
}
}
}
}
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.
####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. |
provider |
(optional) OpenId Connect to be used for authentication, from the list of providers defined in the Sync Gateway Config. If not specified, will attempt to authenticate using the default provider.` |
####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) |
state |
Generated value for CSRF mitigation |
provider |
(optional) OpenId Connect to be used for authentication, from the list of providers defined in the Sync Gateway Config. If not specified, will attempt to authenticate using the default provider.` |
###Response Values
Name | Value |
---|---|
id_token |
JWT Token that can be used for authentication in subsequent API requests |
refresh_token |
(Optional) Refresh token to be used to obtain a new ID token/session via the _oidc_refresh endpoint |
name |
Name of the Sync Gateway user associated with the returned tokens. |
session_id |
(Optional) Sync Gateway session ID created by this authentication |
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 |
name |
Name of the Sync Gateway user associated with the returned tokens. |
session_id |
(Optional) Sync Gateway session ID created by this authentication |
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
},
- Sync Gateway provides a minimal OP to support out of the box OpenID connect testing. The test OP should not be used for production, it does provide a complete OIDC OP implementation and is an experimental feature. 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