Developers and architects simply can’t build modern applications without running into issues of authorization and authentication.
OAuth 2.0 is an industry standard for “delegated authorization” which is the ability to provide an application or client access to data or features offered by another app or service. OAuth 2.0 focuses on authorization and is not prescriptive about authentication. OpenID Connect (OIDC) adds a standards-based authentication layer on top of OAuth 2.0.
To put this in context, Couchbase Sync Gateway supports various forms of client authentication. Clients might be Couchbase Lite clients that sync data with the Sync Gateway over the Internet using a websocket-based replication protocol, or they could be web frontend or mobile apps that are accessing the Sync Gateway through the public REST endpoint. One of the more popular Couchbase Sync Gateway client authentication mechanisms is OIDC.
In this post, we will cover the fundamentals of OAuth 2.0 and OIDC for authentication and authorization. I will discuss two common flows, namely the Implicit Flow and the Authorization Code Flow. A basic understanding of the flows should hopefully provide you with sufficient background for understanding how to use OIDC-based authentication within the context of Sync Gateway client authentication. More on that in a future blog post, so stay tuned!
In order to understand OIDC, we first need to understand OAuth 2.0. That’s because, as an authentication framework, OIDC is built on top of OAuth 2.0.
An OAuth 2.0 Primer
OAuth 2.0 is an industry standard for delegated authorization, and there are a number of OAuth providers on the market.
For example, consider the “Login with Facebook” button that powers a number of web and mobile apps. This is implemented using OAuth 2.0.
Here’s a simplified view of what goes on behind the scenes. I am describing below what is referred to as the Authorization Code Flow. There is an alternative “Implicit Flow” as well which is more prevalent when used in the context of OIDC.
Prerequisites
First, the app/client must be registered with the Authorization Server. The registration process results in the generation of a client_id
and a client_secret
which must then be configured on the app/client requesting authentication.
-
- When the user (a.k.a., “Resource Owner” in OAuth 2.0 speak) clicks on the Login with Facebook button on their favorite app, the app sends an Authorization Request to the login URL of the Authorization Server. In our example, the Authorization Server is Facebook. The Authorization Request includes a number of parameters. For brevity, I am not including the complete list of parameters which can be found in RFC6749. At a minimum, the request must include the following parameters:
client_id
which uniquely identifies the app to the Authorization Serverresponse_type
that must be specified ascode
indicating that the client expects an Authorization Coderequest_uri
that specifies the URL that the Authorization Server must redirect control to following authentication
- The Authorization Server (Facebook) prompts the user to enter their username and password and (optionally) answer a bunch of security questions that are required to authenticate the user.
- Once authenticated, the user is then (optionally) presented with a “resource consent form” listing the set of Facebook resources (such as the user’s public profile) that the app wants access to.
- The set of resources presented in the consent form is specified via a
scope
parameter in the initial Authorization Request to the Authorization Server.
- The set of resources presented in the consent form is specified via a
- Once the user authorizes access to the requested resources, the user is redirected back to the app with an Authorization Code.
- The URL which the Authorization Server redirects the user to is specified via the
redirect_uri
parameter which is also included in the initial Authorization Request.
- The URL which the Authorization Server redirects the user to is specified via the
- The app/client then exchanges the authorization code with the Authorization Server for an opaque access token (or refresh token), passing in the
client_id
andclient_secret
as part of the request. - The app can then access the requested resources on Facebook using the access token.
- When the user (a.k.a., “Resource Owner” in OAuth 2.0 speak) clicks on the Login with Facebook button on their favorite app, the app sends an Authorization Request to the login URL of the Authorization Server. In our example, the Authorization Server is Facebook. The Authorization Request includes a number of parameters. For brevity, I am not including the complete list of parameters which can be found in RFC6749. At a minimum, the request must include the following parameters:
Confused? Don’t worry, we will be revisiting this again in the context of OIDC.
What Is OpenID Connect (OIDC) ?
The main goal of OAuth 2.0 is delegated authorization. In other words, as we saw earlier, the primary purpose of OAuth 2.0 is to grant an app access to data owned by another app.
OAuth 2.0 does not focus on authentication, and as such, any authentication implementation using OAuth 2.0 is non-standard. That’s where OpenID Connect (OIDC) comes in. OIDC adds a standards-based authentication layer on top of OAuth 2.0.
The Authorization Server in the OAuth 2.0 flows now assumes the role of Identity Server (or OIDC Provider). The underlying protocol is almost identical to OAuth 2.0 except that the Identity Server delivers an Identity Token (ID Token) to the requesting app. The Identity Token is a standard way of encoding the claims about the authentication of the user. We will talk more about identity tokens later.
I will describe two popular OIDC flows here: Implicit Flow and Authorization Code Flow.
Prerequisites
For both these flows, the app/client must be registered with the Authorization Server. The registration process results in the generation of a client_id
and a client_secret
which must then be configured on the app/client requesting authentication.
OIDC Implicit Flow
The OIDC Implicit Flow is the simpler of the two and is recommended for use in Couchbase Lite client authentication with Sync Gateway which we will talk about more in my next blog post.
Once again, we will use Login with Facebook as an example to illustrate the flow.
-
- When the user clicks on the Login with Facebook button on their favorite app, the app sends an Authentication Request to the login URL of the Authorization Server or Identity Server. In our example, the Authorization Server is Facebook.
- The Authentication Request includes a number of parameters. For brevity, I am not including the complete list of all parameters which can be found in the OIDC spec. At a minimum, the request must include the following parameters:
client_id
which uniquely identifies the app to the Authorization Serverresponse_type
that must be specified asid_token
indicating that the client expects an ID Token.scope
that must contain theopenid
scope value, in addition to an optional list of resources that the app is requesting access torequest_uri
that specifies the URL that the Authorization must redirect control to following authentication
- The Authentication Request includes a number of parameters. For brevity, I am not including the complete list of all parameters which can be found in the OIDC spec. At a minimum, the request must include the following parameters:
- The Identity Server (Facebook) then prompts the user to enter their username and password and (optionally) answer a bunch of security questions that are required to authenticate the user.
- Once authenticated, the user is then (optionally) presented with a “resource consent form” listing the set of Facebook resources (such as the user’s public profile) that the app wants access to.
- The set of resources presented in the consent form is specified via the
scope
parameter which was included in the initial Authentication Request to the Authorization Server.
- The set of resources presented in the consent form is specified via the
- Once the user authorizes access to the requested resources, the user is redirected back to the app with an Identity Token and optionally an Access Token
- The URL which the Authentication Server redirects the user to is specified via the
redirect_uri
parameter which is also included in the initial Authentication Request.
- The URL which the Authentication Server redirects the user to is specified via the
- The app then validates the Identity Token per criteria specified in the OIDC spec and retrieves the identity of the authenticated user.
- When the user clicks on the Login with Facebook button on their favorite app, the app sends an Authentication Request to the login URL of the Authorization Server or Identity Server. In our example, the Authorization Server is Facebook.
OIDC Authorization Code Flow
The OIDC Authorization Code Flow is very similar to the OAuth 2.0 Authorization Code Flow described earlier.
Once again, we will use Login with Facebook as an example to illustrate the flow.
-
- When the user clicks on the Login with Facebook button on their favorite app, the app sends an Authentication Request to the login URL of Authorization Server or Identity Server. In our example, the Authorization Server is Facebook.
- The Authentication Request includes a number of parameters. For brevity, I am not including the complete list of all parameters which can be found in OIDC spec. At a minimum, the request must include the following parameters:
client_id
which uniquely identifies the app to the Authorization Serverresponse_type
that must be specified ascode
indicating that the client expects an Authorization Code.scope
that must contain theopenid
scope value, in addition to an optional list of resources that app is requesting access torequest_uri
that specifies the URL that the Authorization must redirect control to following authentication
- The Authentication Request includes a number of parameters. For brevity, I am not including the complete list of all parameters which can be found in OIDC spec. At a minimum, the request must include the following parameters:
- The Identity Server (Facebook) then prompts the user to enter their username and password and (optionally) answer a bunch of security questions that are required to authenticate the user.
- Once authenticated, the user is then (optionally) presented with a “resource consent form” listing the set of Facebook resources (such as the user’s public profile) that the app wants access to.
- The set of resources presented in the consent form is specified via the
scope
parameter which is also included in the initial Authentication Request to the Authorization Server.
- The set of resources presented in the consent form is specified via the
- Once the user authorizes access to the requested resources, the user is redirected back to the app with an Authorization Code
- The URL which the Authorization Server redirects the user to is specified via the
redirect_uri
parameter which is also included in the initial Authorization Request.
- The URL which the Authorization Server redirects the user to is specified via the
- The app/client then exchanges the authorization code with the Authorization Server for an Identity Token and an opaque Access Token, passing in the
client_id
andclient_secret
as part of the request. - The app then validates the Identity Token per criteria specified in the OIDC spec and retrieves the identity of the authenticated user.
- When the user clicks on the Login with Facebook button on their favorite app, the app sends an Authentication Request to the login URL of Authorization Server or Identity Server. In our example, the Authorization Server is Facebook.
JSON Web Token (JWT)
A key element of OIDC is the Identity Token which is a security token that encodes the authentication claims about a user in a standard format referred to as the JSON Web Token (JWT). The JWT is digitally signed.
A “claim” is an assertion about the user. Here is an example of a JWT which has a typical set of claims.
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "sub": "AItOawmwtWwcT0k51BayewNvutrJUqsvl6qs7A4", "name": "Priya Rajagopal", "email": "priya.rajagopal@example.com", "iss": "https://pk-demo.okta.com/OAuth 2.0/default", "aud": "WuRuBAgABMP7_w4K9L-40Jhh", "iat": 1622246311, "exp": 1624838311, "amr": [ "pwd" ] } |
-
sub
is the user whom the JWT refers toiss
is the issuer of the JWT who also signs the JWTaud
is who the token is intended foriat
is the issued timestampexp
is the expiration timestampamr
refers to the authentication method used to issue token
More Resources
jwt.io is very useful to decode and verify a JWT.
The OIDC and OAuth playground from Okta is a great resource for trying out the flows without actually implementing it.
What’s Next
In this post we described the fundamentals of OpenID Connect (OIDC) and OAuth 2.0 flows. In next week’s post, we will discuss OIDC-based authentication in the context of Sync Gateway client authentication. Stay tuned!
If you have questions or feedback, please leave a comment below or email me priya.rajagopal@couchbase.com. The Couchbase Forums are another good place to reach out with questions.
Catch up with the rest of the posts in this series on authentication and authorization: