Skip to content

OIDC Notes

Adam Fraser edited this page May 18, 2017 · 24 revisions

TSA: OpenID Connect for Sync Gateway

Author: Adam Fraser
Contributors: -
Reviewers: —

1. Introduction

We want to be able to support Sync Gateway authentication using the OpenID Connect authentication protocol.

1.1 Scope

What Is In Scope

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)

What Is Out Of Scope

The following functionality will not be delivered:

  • Sync Gateway as an OpenID Connect Provider/IdP
  • Authentication using the Implicit or Hybrid flows

1.2 Milestone Objectives and Priorities

  • 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

1.3 Design Goals

  • 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.

1.4 Technology

The following libraries are recommended to be used:

1.5 Terminology

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.

2. Technical Solution Overview

2.1 Architecture

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.

2.1.1 Authorization Code Flow

Auth Code Flow

2.2 Database Config Properties

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
            }
          }
        }
      }
   }
}

2.3 Public API Changes

The following new API endpoints will be added to Sync Gateway to support the OIDC Authorization Code flow.

2.3.1 GET /{db}/_oidc

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

2.3.2 GET {db}/_oidc_callback

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

2.3.3 GET {db}/_oidc_refresh

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

2.4 Bearer token handling

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.

2.5 Refresh handling

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

3. Issues

Open Issues

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)

Closed Issues

Bug# Description

4. References

5. Testing Notes

Testing using Google as OP

  1. 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.
  2. 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
        },

Testing using Sync Gateway test OP

  1. 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
    }
},
  1. 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

Clone this wiki locally