Introduction
In previous post, we learned that OAuth is an authorization framework specially built for HTTP APIs. It allows a user to securely delegate scoped API Access to an application.
By scoped access means, that user define exactly what parts of an API, they want application to be allowed to use. This application can then talk to API freely on user behalf. In simple words, OAuth is a delegation protocol.
We also learned that OpenID Connect is a standard adding authentication (verifying the user’s identity) on top of OAuth2, which is only for authorization (access control). OpenID connect adds authentication by introducing the notion of an ID token, which is a JWT, providing a signed proof of authentication of the user.
In this post, we will go in little bit of details of OAuth and OIDC.
OAuth Players
In OAuth, we have following players:
- Protected Resource: an http API.
- Client (requesting) Application: Application that want to access to protected resource on someone’s behalf.
- Resource Owner: The user who owns the protected resource.
- Authorization Server: Responsible for handling authorization requests.
Note that, the protected resource may be an API that your company owns. However, in OAuth, the data on that API belongs to the user and it should be user consent if they want to share their data (Good foundation for GDPR etc.)
OAuth Scope
We mentioned scoped access earlier. Lets understand it a bit more. An OAuth scope is simply “A permission to do something within the protected resource on behalf of resource owner”.
What those permissions are and how fine-grained those are, entirely up to you. some examples:
- api1: we can have a scope which represents an API in its entirety.
- api1.read: or may be a particular type of access within the API.
- api1.notify: or it can be a particular piece of functionality within the API.
When a client application ask for authorization, it will be these permissions, these scopes that they will be requesting.
I went ahead and added few ApiScope in Config.cs file as shown below:
We will defined ApiResources later, for now , note that API-Resources map to scopes which gives access to API. Next wire this up in IdentityServer middleware in Startup.cs file:
Save and run the application. Here is how the discovery document shows this information.
OAuth GrantTypes
If we visit the discover document of our STS, you can see a section name as shown below:
Let’s learn a little bit about these different grant types:
- Authorization Code (Redirect Flow)
- Designed for Confidential Clients (i.e. client applications which can keep a secret).
- The flow is initiated with the response_type parameter set to code and a client secret shared between the client and the Auth server in the login request.
- Best suited for web sites with backend server( e.g. ASP .NET MVC).
- Best of both worlds: Explicit User & Client Authentication
- Implicit Flow
- Was Designed for public clients (e.g. Angular SPA).
- Best for clients accessing resource directly from browser.
- Due to lack of keeping a secret, No explicit Client authentication in this grant type.
- Not recommended for new apps.
- Client Credentials (No user involved)
- Designed for applications who are the resource owner.
- Best for machine to machine communication.
- This flow requires Client authentication.
- Resource Owner Password Credentials (ROPC)
- Instead of Redirect, we talk to authorization server.
- If you want to use in-app login screen e.g. on in angular application, then this flow can be used. But it is advised not to use this flow if possible.
- Designed as temporary solution for legacy applications (transition period).
- Should no longer be used.
Refresh Tokens
In previous post we talked briefly about Access-Tokens and that they contains claims or access information about user. We will talk about Id Token later as well.
Regardless of the mechanism, we get the access-token, but what about when those tokens expire? Here a different type of token come into play, a Refresh Token.
A refresh token is a long lived token that can be used by the client applications to swapped for new access-token or even refresh-token. This allowed us to perform long running background tasks without the user being present.
Refresh tokens are highly confidential. User should be informed that refresh token is being requested (consent screen). This is because we will be acting on user behalf, when they are no longer present.
For refresh token, we usually use a scope called “offline access“.
OAuth 2.1 Changes
Based on security changes and simplify best practices following are the changes:
- No more ROPC.
- No more Implicit Flow.
- Refresh tokens must be single use only.
- PKCE is now mandated across all application types.
Recommended Flows from OAuth 2.0 to OAuth 2.1
OAuth 2.0 Flows
App Type | Recommended Flow |
Server-Side | Authorization Code |
Single Page Apps | Implicit Flow |
Native app (mobile, desktop) | Authorization Code + PKCE |
Machine to Machine | Client Credentials |
OAuth 2.1 Flows
App Type | Recommended Flow |
Server-Side | Authorization Code + PKCE |
Single Page Apps | Authorization Code + PKCE |
Native app (mobile, desktop) | Authorization Code + PKCE |
Machine to Machine | Client Credentials |
OAuth + Identity With OIDC
As we already know that in OAuth, there is not authentication. It does not give any indication to client application about who the user is and how they authenticated. OIDC is an identity layer on top of OAuth and it formalize some of the OAuth ambiguity.
By using OIDC, you authorization server also act as an identity provider.
OIDC also gives us a discovery document. A well known document, which describes the identity provider including the URLs of its various end points. What scopes and claim types it supports and the public keys for verifying tokens. The very same document which we are referring to in this post is coming from OIDC part of IdentityServer. This document allow client applications to automatically configure themselves to use the identity provider.
Identity Access
When using OIDC, we bring a new protected resource into our system, which is an API typically hosted in our identity provider called the UserInfo endpoint.
When we call the UserInfo endpoints with an access-token attained using OIDC, we are returned claims about the delegating user. Access to this API is again scoped, however this time by identity specific scopes which gives the client application access to subset of claims about the user.
example:
- profile: give access to claims about user e.g. name, website, gender, username etc.
Configuring IdentityServer with IdentityResources
I have updated the Config.cs file with the identity resources as shown below:
Next, Update the Startup.cs file with this information:
Now, if we run the application and check the discover document, we will see that it is now populated with more information:
Identity Resources map to scopes that gives access to identity related information.
Identity Token
The other major feature of OIDC is identity token. This is a new type of token, however, instead of allowing us access to a protected resource, this token describes the authentication event itself. This token is intended for client applications (contrast to protected resource).
When client receive this token, it is going to verify both the data in it and whether or not the token has been tempered with. This is done using public-key cryptography (digitally verifiable). Identity provider sign the token with private-key and client application verify the token with public-key.
An identity-token is always a JSON WEB TOKEN (JWT). The payload contains information, which client information further act upon as needed.
The ID token is never sent to the resource API and only used by the client to validate if the user is properly authenticated before requesting authorized resources.
Hybrid Flow
OIDC also adds a new authorization flow called the Hybrid flow. It offers us an interesting alternative for authorizing confidential clients.
Hybrid flow allows every combination of code, token and id token.
So, by requesting a code and id-token together, we can not only verify that the response was intended for us but also verify that authorization code was also intended for us.
Summary
In this post, we learned about some of the details of OAuth2 and OIDC. Learned about different OAuth players. We also discussed what are different type of OAuth flows for different kind of applications and OAuth2.1 recommendations.
We also talked about OIDC extension to OAuth and also configured our identity server with some of identity related scopes. We learned that and id token is a type of JWT and it is digitally verifiable and intended for client applications. We will resume our journey on Token Based security using IdentityServer in the next post. Let me know if you have some comments or questions. You can clone the source code repo from this github link. Till Next time, happy coding.
My Recent Books
Discover more from Hex Quote
Subscribe to get the latest posts sent to your email.
1 thought on “Token Based Security, OAuth 2.0, OIDC and IdentityServer4 – Part 2”
Comments are closed.