Token-Based Security, OAuth 2.0, OIDC and IdentityServer4

Introduction

We all know the username/password mechanism of login to a web application. We also might have heard, used, or implemented authentication/authorization systems, with or without frameworks.

Token-based security is one of the common mechanisms to secure backend APIs.

A common architecture for web applications typically consists of a web client app (e.g. an Angular or React frontend), a backend API (written in .NET Core, Java, or NodeJS), and a database for persistent.

In token-based security, generally, web client applications send tokens, representing consent, to an API. So, Instead of sending over Username, Password on each call to the API, the client app sends a token. These tokens represent consent, for example, consent, granted by the user to the client application to access an API on behalf of that user. A token can then be used on the client or can be passed to the API.

Home-grown token services e.g. self-created login endpoints that accept username, password and return a JSON Web Token are one of the options. This is already an improvement because we are no longer sending username/password on each request. We are sending it once to get a token and afterward, we can send this token to APIs.

Central Identity Provider

Let’s think about identity and access management related tasks:

These are tedious tasks and prone to change. It's better to handle at a central location, at the IDP level, so, it can be reused across applications.

So, instead of building our own authentication/authorization for different kinds of applications. If we can use an IDP (Identity Provider) to simplify these tasks for us and follow a standard, a way to ensure these tokens are safe enough to use for both authentication and authorization purposes for different types of applications, i.e., a proven protocol that’s safe for authentication and authorization and handles these common concerns.

And that’s what we will cover in this and upcoming posts.

Scenario 1: Web Application

In our basic scenario, a Web app client needs to communicate with the API tier. So, how do we create trust in this environment? How can we make sure that when we have an app client that’s not running on any machine that we control, but it's going to be entirely on our user’s machine (e.g., an Angular app). How can we trust the information that it sends to us? We will see that this can be done by using Open ID Connect (OIDC).

App Client and API Diagram

OAuth 2.0

OAuth 2.0 is an open protocol to allow secure authorization in a simple and standard method from web, mobile, and desktop apps.

OAuth 2.0 is about authorization, i.e., a client application can request an access-token and pass this access-token to an API to gain access to an API.

But, we also know there are different types of applications. A server-side ASP .NET MVC App has different means of storing things like secrets than, e.g., an Angular application, which completely runs in the client and it’s just not to be trusted by default.

So, OAuth 2.0 also defines how an application can securely get such token from STS (security token service), or in other words, how a client application securely achieves authorization.

We can already feel that homegrown endpoints are replaced by endpoints from the OAuth standard. The standard also defines how to use these endpoints for different types of client applications.

One thing to note: These access-token should only be used to access resources, an API. They shouldn’t be used to sign into client applications. That’s authentication, not authorization.

Authorization gives you access, Authentication is what identifies you, who you are.

So if OAuth is only authorization, then how about the identity, where it comes from?

OpenID Connect (OIDC)

This is the other half of the puzzle. OpenID connect complements OAuth 2.0 with authentication (identity).

As mentioned before, OIDC is a simple identity layer on top of the OAuth 2.0 protocol, so it extends OAuth2.

With OIDC, an application can receive an identity token (next to the access token) if it needs one. This identity token can then be used to sign in to an application, while the same application uses the access token to access an API.

It also defines an additional endpoint that can be used by an application to get additional user information. That’s the UserInfo endpoint.

Like before, the same principles apply. It defines how different types of client applications can safely get those tokens from STS.

OIDC is not just for new apps or API-based apps. You can use it even with apps that don’t talk to an API.

Luckily, we do not have to implement most of this. There are some great frameworks available that do most of the heavy lifting. IdentityServer4 is one of them, which we will be using later for the demo.

JSON Web Tokens (JWTs)

OIDC uses JWTs, which you can obtain using flows conforming to the OAuth 2.0 Specs. STS will actually issue JWTs and sign them. JWTs payload contains user-specific information:

Let’s see 3 different JSON web tokens:

1. ID Token

Contains user identity information.

2. ACCESS Token

Contains scopes and groups for users and this is what you will send along with the request to API. When we are talking to API, the API knows where to look for the access token. If a valid access token is present means we are authorized to use resources.

3. Refresh Token

Used to get new ID-Token and ACESS-Token.

Identity Solution (How to Choose)

We will be using IdentityServer4 for the demos.

OAuth Endpoints

These endpoints are required by the standard (when we use IdentityServer4, those are automatically setup for us):

/authorize

/token

Can be used in the following cases:

/revocation

The following end-points are part of OpenId Specifications:

Getting Started With IdentityServer4

Ok, after covering some of the basic theory, we will now start with the implementation of STS using IdentityServer4.

IdentityServer4 is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. There is a good amount of information available on its official website on this link. Setting it up in a .ASP .NET Core Web Application is very simple. There are multiple options to get started:

I created a net .NET Core Web Application using AWS Serverless Template. You can use the typical .NET Core Web API Template as well if you like:

.NET Core Web Application Example

Next, let's add the NuGet package for IdentityServer4:

Adding NuGet Package for IdentityServer4

Before configuring ASP.NET Core with IdentityServer4 middleware, let’s talk about few basic concepts:

Defining an API Scope

An API is a resource in your system that you want to protect.

Defining an API Scope

Defining the Client

The next step is to define a client application that we will use to access our new API.

For this initial scenario, the client will not have an interactive user and will authenticate using the so-called client secret with IdentityServer.

Defining the Client

You can think of the ClientId and the ClientSecret as the login and password for your application itself. It identifies your application to the identity server so that it knows which application is trying to connect to it.

Configuring IdentityServer4

Loading the resource and client definitions happens in Startup.cs. Let’s update the file:

Configuring IdentityServer4

Let’s put it to a test, run the application and visit the /.well-known/openid-configuration endpoint (notice a few of the endpoints we mentioned earlier in this post):

Endpoint Test Example

Don’t worry if this information is overwhelming for you. We will learn about these more later. For now, think that by adding identityserver4 middleware we get all this functionality, which follows security best practices standard, ready for use.

This discovery document is a standard endpoint in identity servers and this will be used by your client apps and APIs to download the necessary configuration data.

Now, we’ve reached the end of this post. We still have to cover a lot of implementation details. We will continue our learning in the next post. You can clone the source code repo from this GitHub link.

Summary

OIDC extends OAuth 2.0 protocol which deals with Authentication and Authorization. IdentityServer4 is a middleware we can use to build an IDP (STS) that is OAuth 2.0 specs compliant.

In this post, we learn the OIDC basics and set up an ASP .NET Core Web Application with the IdentityServer4 package. Let me know if you have any comments or questions. Till next time, Happy Coding!

 

 

 

 

Top