OpenID Connect (OIDC) / OAuth 2.0 Plugin

EnRoute Technical Reference

OpenID Connect (OIDC) Plugin

The Enroute OpenID Connect filter/plugin can be used to execute the OIDC compliant OAuth2 flow. The plugin is a global plugin and is attached to a GatewayHost. It is supported for both Enroute Standalone API Gateway and Enroute Kubernetes Ingress API Gateway

OIDC Discovery and Enroute

OIDC Discovery provides a way to discover endpoints needed to run the OIDC compliant OAuth flow. An OIDC Discovery endpoint typically provides configuration values that can be used to configure OIDC compliant OAuth flow. See below for an example of discovery endpoints for provideers like Auth0 and Okta.

OAuth / OIDC Authentication steps

We break up the OIDC OAuth 2 flow into the following high level steps to clearly map the steps involved in working with authentication for the user.

Get authorization code to interface the Identity Provider

OIDC OAuth 2 Authorization Code
  • User makes a request [1]
  • User is redirected to Identity Provider where the user logs in [2,3]
  • Identity provider returns an authorization code and initiates redirect [4]

Get access token and user info from Identity Provider

OIDC OAuth 2 Authorization Code
  • User makes a request with authorization code [5]
  • Enroute gets the access token and id token from Identity provider using authorization code [6,7]
  • Enroute signs the tokens and sets cookie on the client with tokens and initiates redirect [8]

Invoke service authentication credentials and user info to access the service

OIDC OAuth 2 Authorization Code
  • User makes request with tokens [9]
  • Enroute verifies the token and passes valid request to the service [10]
  • Service responds to the user [11,12]

OAuth / OIDC Authentication call flow

Here is the complete call flow with all entities involved. Identity provider could be a service like Key Cloak, Google, Facebook, Okta, Auth0, Ping Identity etc.

OIDC OAuth 2 Authorization Code

OIDC Filter Configuration

OAuth OIDC filter configuration needs the following config

  • An external Identity provider
    • configured as an Upstream for Standalone Gateway
    • configured as a Service for Kubernetes Gateway
OIDC Service for KubernetesOIDC Upstream for Standalone

apiVersion: enroute.saaras.io/v1beta1
kind: GatewayHost
metadata:
  labels:
    app: httpbin
  name: httpbin
  namespace: enroute-gw-k8s
spec:
  virtualhost:
    fqdn: '*'
    filters:
      - name: oauth_filter
        type: http_filter_oauth2
        service:
          name: identity_provider
          protocol: tls
          port: 443 
  routes:
    - match: /
      services:
        - name: httpbin
          port: 80
---
apiVersion: v1
kind: Service
metadata:
  name: identity_provider
  namespace: enroute-gw-k8s
spec:
  type: ExternalName
  externalName: saaras.auth0.com
---


UPSTREAM_NAME="identity_provider"
UPSTREAM_TLS_IP="saaras.auth0.com"
UPSTREAM_TLS_PORT="443"
UPSTREAM_TLS_WEIGHT="100"
UPSTREAM_TLS_PROTO="tls"

curl -s -X POST localhost:1323/upstream \
    -d "upstream_name"="${UPSTREAM_NAME}" \
    -d "upstream_ip"="${UPSTREAM_IP}" \
    -d "upstream_port"="${UPSTREAM_PORT}" \
    -d "upstream_hc_path"="${UPSTREAM_HC_PATH}" \
    -d "upstream_protocol"="${UPSTREAM_PROTO}" \
    -d "upstream_weight"="${UPSTREAM_WEIGHT}"

  • OIDC Filter config
FieldDescription
nameName of Filter.
client_idUnique identity of the client. When a client is registered with Identity Provider, it provides a unique code to identify the client
client_secretSecret provided by the Identity Provider to the client
authorization_endpointURI Location of endpoint at Identity Provider used to get an authorization code
token_endpointURI Location token endpoint at Identity Provider used to get an access and id token
redirect_uriAfter getting the authorization code, the Identity Provider will redirect to this uri
cookie_secretSecret that will be used to create HMAC when the tokens are received from Identity Provider. Subsequently, the secret will be used to validate the HMAC of the cookie sent from the client. Note that this secret to refer to an existing secret.
logout_uriRelative match uri used to logout a user
OIDC Filter Config Example
{
  "name" : "oauth2-okta",
  "client_id" : "5FJHleU20CHfQ1NMqWFbEMrHMp7maau3",
  "client_secret" : "v7D8-biy1JjL7BGx7JP_MtZ7JTAx5OR1sDk-YqnzkYRmcKsgopGmrUOdULRNCegI",
  "authorization_endpoint" : https://dev-367091.okta.com/oauth2/v1/authorize",
  "token_endpoint": "https://dev-367091.okta.com/oauth2/v1/token",
  "redirect_uri" : "https://saaras.io/customerportal/callback",
  "cookie_secret" : "secret-hmac",
  "logout_uri" : "/logout"
}

The endpoints can be directly populted from the OIDC discover endpoint. An example of output of OIDC discovery endpoints is shown below.

Notes

Filter example for OIDC Identity Provider Okta
OIDC OAuth Filter for KubernetesOIDC OAuth Filter for Standalone

---
apiVersion: enroute.saaras.io/v1beta1
kind: HttpFilter
metadata:
  name: oidc_filter_okta_k8s
  namespace: enroute-gw-k8s
spec:
  name: oidc_filter_okta
  type: http_filter_oauth2
  httpFilterConfig: |
   {
     "name" : "oauth2-okta",
     "client_id" : "5FJHleU20CHfQ1NMqWFbEMrHMp7maau3",
     "client_secret" : "v7D8-YqnzkYRmcKsgopGmrUOdULRNCegI",
     "authorization_endpoint" : https://dev-367091.okta.com/oauth2/v1/authorize",
     "token_endpoint": "https://dev-367091.okta.com/oauth2/v1/token",
     "redirect_uri" : "https://saaras.io/customerportal/callback",
     "cookie_secret" : "secret-hmac",
     "logout_uri" : "/logout"
   }
---


OIDC_FILTER_NAME="oidc_filter_okta"
OIDC_FILITER_TYPE="http_filter_oauth2"
OIDC_CONFIG='
{
     "name" : "oauth2-okta",
     "client_id" : "5FJHleU20CHfQ1NMqWFbEMrHMp7maau3",
     "client_secret" : "v7D8-YqnzkYRmcKsgopGmrUOdULRNCegI",
     "authorization_endpoint" : https://dev-367091.okta.com/oauth2/v1/authorize",
     "token_endpoint": "https://dev-367091.okta.com/oauth2/v1/token",
     "redirect_uri" : "https://saaras.io/customerportal/callback",
     "cookie_secret" : "secret-hmac",
     "logout_uri" : "/logout"
}
'
curl -s -X POST localhost:1323/filter   \
    -d "filter_name=${OIDC_FILTER_NAME}" \
    -d "filter_type=${OIDC_FILTER_TYPE}" \
    -d "filter_config"="${OIDC_CONFIG}"

OIDC Discovery Endpoint examples
OktaGoogle
{
  "issuer": "https://dev-367091.okta.com",
  "authorization_endpoint": "https://dev-367091.okta.com/oauth2/v1/authorize",
  "token_endpoint": "https://dev-367091.okta.com/oauth2/v1/token",
  "userinfo_endpoint": "https://dev-367091.okta.com/oauth2/v1/userinfo",
  "registration_endpoint": "https://dev-367091.okta.com/oauth2/v1/clients",
  "jwks_uri": "https://dev-367091.okta.com/oauth2/v1/keys",
  "response_types_supported": [
    "code",
    "id_token",
...
  ],
  "grant_types_supported": [
    "authorization_code",
...
  ],
...
  "scopes_supported": [
    "openid",
    "email",
    "profile",
    "address",
    "phone",
    "offline_access",
    "groups"
...
  ],
  "token_endpoint_auth_methods_supported": [
...
  ],
  "claims_supported": [
    "iss",
    "ver",
    "sub",
    "aud",
    "iat",
    "exp",
    "jti",
...
  ],
...
  "introspection_endpoint": "https://dev-367091.okta.com/oauth2/v1/introspect",
  "introspection_endpoint_auth_methods_supported": [
    "client_secret_basic",
    "client_secret_post",
    "client_secret_jwt",
    "private_key_jwt",
    "none"
  ],
  "revocation_endpoint": "https://dev-367091.okta.com/oauth2/v1/revoke",
  "end_session_endpoint": "https://dev-367091.okta.com/oauth2/v1/logout",
  "request_parameter_supported": true,
...
}

{
 "issuer": "https://accounts.google.com",
 "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
 "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code",
 "token_endpoint": "https://oauth2.googleapis.com/token",
 "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
 "revocation_endpoint": "https://oauth2.googleapis.com/revoke",
 "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
 "response_types_supported": [
  "code",
  "token",
  "id_token",
  "code token",
  "code id_token",
  "token id_token",
  "code token id_token",
  "none"
 ],
 "subject_types_supported": [
  "public"
 ],
 "id_token_signing_alg_values_supported": [
  "RS256"
 ],
 "scopes_supported": [
  "openid",
  "email",
  "profile"
 ],
 "token_endpoint_auth_methods_supported": [
  "client_secret_post",
  "client_secret_basic"
 ],
 "claims_supported": [
  "aud",
  "email",
  "email_verified",
  "exp",
  "family_name",
  "given_name",
  "iat",
  "iss",
  "locale",
  "name",
  "picture",
  "sub"
 ],
 "code_challenge_methods_supported": [
  "plain",
  "S256"
 ],
 "grant_types_supported": [
  "authorization_code",
  "refresh_token",
  "urn:ietf:params:oauth:grant-type:device_code",
  "urn:ietf:params:oauth:grant-type:jwt-bearer"
 ]
}

Terminology

  • OAuth2 Authorization Framework is a framework for an application to access a resource with permission from the user.
    • OAuth defined roles where a resource owner (or the user), grants permission to a client (eg: the application or Enroute Gateway) to access resources on the resource server (eg: your application). This process is facilitated by the authorization server.
    • Authorization Server Endpoints provided by authorization server to make different OAuth flows work.
    • Resource Server Endpoints provided by resource server (or Enroute or the service) as a redirect target for authorization server. For example the auth endpoint below for Google is used to get an authorization code:
		access_type: "offline"
		auth_uri: "https://accounts.google.com/o/oauth2/v2/auth"
		prompt: "consent"
		response_type: "code"
		scope: ["https://www.googleapis.com/auth/drive", …]
			0: "https://www.googleapis.com/auth/drive"
			1: "https://www.googleapis.com/auth/drive"
			2: "https://www.googleapis.com/auth/drive.metadata"
			3: "https://www.googleapis.com/auth/drive"
			4: "https://www.googleapis.com/auth/drive"
			5: "https://www.googleapis.com/auth/drive"

- <a class="text-color" href="https://tools.ietf.org/html/rfc6749#section-3.3">Scope of permissions</a> An application can request access for specific resources eg: a set of APIs on google like a user's drive by specifying the drive scope.
		POST /token HTTP/1.1
		Host: oauth2.googleapis.com
		code=4%2F0AY0e-g4tZPWVCZLB3Ggu0G6drjnN-WIRUHwcBZDUiQuj1wynOxcbKOPNsARfyHAakUk_Sw&redirect_uri=https%3A%2F%2Fdevelopers.google.com%2Foauthplayground&client_id=407408718192.apps.googleusercontent.com&client_secret=************&scope=&grant_type=authorization_code
		
		HTTP/1.1 200 OK
		Content-type: application/json; charset=utf-8
		{
		  "access_token": "ya29.a0AfH6SMAqMOFuu2veuZuNx22fW2yBsITaXhnCGg8hCieBtm9nworoERi2mj-hRaq3SyDmwhBsrB15VwBaGEgAwU36i2B0J2aMMtphpYt9foK3lM4thT3gImn3ChnT3AiEJWBn-ed1_8fHiJsnihEwDzyXh0OfrAUdXl8gRrKrnW8", 
		  "scope": "https://www.googleapis.com/auth/drive", 
		  "token_type": "Bearer", 
		  "expires_in": 3599, 
		  "refresh_token": "1//043X0Cjp29bcfCgYIARAAGAQSNwF-L9IrowDcIUBBV7wRQ9uJPOid6gkuOAnWJBb8rowziicI6fQvsP6hosywoV_HvR5H5klin5U"
		}

OpenID Connect (OIDC) is built on top of the OAuth 2.0 framework and provides the identity flow. - OIDC uses JWTs or JSON Web Tokens to relay and verify identity information. - OIDC makes it possible to use external user identity providers like Google, Facebook, Github etc. and their sign-in information to be used for an application. On a successful login from these providers, a corresponding OIDC compliant JWT token can be used to access and verify information about the user. - OIDC discovery provides a way to automatically configure endpoints, claims supported and other information to work with OIDC from a specific provider.