Securing Microservices with IdentityServer4, OAuth2 and OpenID Connect fronted by Ocelot API Gateway

Mehmet Ozkaya
aspnetrun
Published in
25 min readOct 13, 2020

--

Target Architecture of Identity Server with Microservices Reference Application

In this article, we’re going to learn how to secure microservices with using standalone Identity Server 4 and backing with Ocelot API Gateway. We’re going to protect our ASP.NET Web MVC and API applications with using OAuth 2 and OpenID Connect in IdentityServer4. Securing your web application and API with tokens, working with claims, authentication and authorization middlewares and applying policies, and so on.

Step by Step Development w/ Course

I have just published a new course — Securing .NET 5 Microservices with IdentityServer4 with OAuth2, OpenID Connect and Ocelot Api Gateway.
In the course, we are securing .Net 5 microservices with using standalone Identity Server 4 and backing with Ocelot API Gateway. We’re going to protect our ASP.NET Web MVC and API applications with using OAuth 2 and OpenID Connect in IdentityServer4.

Source Code

Get the Source Code from AspnetRun Microservices Github — Clone or fork this repository, if you like don’t forget the star. If you find or ask anything you can directly open issue on repository.

Overall Picture

See the overall picture. You can see that we will have 4 microservices which we are going to develop.

Movies.API

First of all, we are going to develop Movies.API project and protect this API resources with IdentityServer4 OAuth 2.0 implementation. Generate JWT Token with client_credentials from IdentityServer4 and will use this token for securing Movies.API protected resources.

Movies.MVC

After that, we are going to develop Movies.MVC Asp.Net project for Interactive Client of our application. This Interactive Movies.MVC Client application will be secured with OpenID Connect in IdentityServer4. Our client application pass credentials with logging to an Identity Server and receive back a JSON Web Token (JWT).

Identity Server

Also, we are going to develop centralized standalone Authentication Server and Identity Provider with implementing IdentityServer4 package and the name of microservice is Identity Server.
Identity Server4 is an open source framework which implements OpenId Connect and OAuth2 protocols for .Net Core.
With Identity Server, we can provide authentication and access control for our web applications or Web APIs from a single point between applications or on a user basis.

Ocelot API Gateway

Lastly, we are going to develop Ocelot API Gateway and make secure protected API resources over the Ocelot API Gateway with transferring JWT web tokens.
Once the client has a bearer token it will call the API endpoint which is fronted by Ocelot. Ocelot is working as a reverse proxy.

After Ocelot reroutes the request to the internal API, it will present the token to Identity Server in the authorization pipeline. If the client is authorized the request will be processed and a list of movies will be sent back to the client.

Also over these picture, we have also apply the claim based authentications.

Background

You can follow the previous article which explains overall microservice architecture of this example.

Check for the previous article which explained overall microservice architecture of this repository.

Prerequisites

  • Install the .NET 5 or above SDK
  • Install Visual Studio 2019 v16.x or above
  • Install Postman

Introduction

We will develop security operations with Identity Server integration for an existing microservices reference application.
We had developed run-aspnetcore-microservices reference application before this article. You can see the overall picture of the reference microservices application.

Target Architecture of Identity Server with Microservices Reference Application

Now with the newly added red box in picture, we will extend this application with IdentityServer OAuth 2.0 and OpenId Connect features.

By the end of this article, you’ll learn all about how to secure your ASP.NET based microservices applications with IdentityServer4 using OAuth 2 and OpenID Connect. And Also you’ll learn how to secure protected APIs backing with Ocelot API Gateway in a microservices architecture.

Code Structure

Let’s check our project code structure on the visual studio solution explorer window. You can see the 4 asp.net core microservices project which we had see on the overall picture.

If we expand the projects, you will see that;
Movies.API is an asp.net core web api project which includes crud api operations.
Movies.MVC is an asp.net core MVC web application project which consumes Movies.API project and represent the data.
IdentityServer is a standalone Identity Provider for our architecture.
APIGateway is an api gateway between Movies.MVC and Movies.API.

Before we start we should learn the basics of terminology.

What is JWT (Token) ?

User authentication and authorization is very important while developing our web projects. We use various methods to protect our application from unauthorized persons and we provide access to it only for authorized users. One of these solutions is to use tokens.

At this point, there are some industry standards. We are going to talk about JSON Web Token (JWT).

JWT (JSON Web Tokens) is an RFC7519 industry standard. It is used for user authentication and authorization on systems that communicate with each other. JWT can be used for many issues such as user authentication, web service security, and information security. JWT is a very popular and preferred method when protecting our resources. If we want to access a protected resource, the first thing we have to do is to retrieve a token.

JWT Example Scenario

The general scenario is:

The user sends a login request to the server with username and password.
The Authentication Server takes this information and queries it from the database, combines the user name with its secret key and generate the token.
When user authenticated, Authentication server returns token and the server writes this information to the related user’s Token column in the database.
The user passes JWT token when making API calls into header part of the request and the server side checks each time whether the token is valid or not from the database.
Application verifies and processes API call.

JWT(JSON Web Tokens) Structure

The token produced with JWT consists of 3 main parts encoded with Base64. These are Header (Header), Payload (Data), Signature parts. Let’s take a closer look at these parts. If we pay attention to the token example on the side, there are 3 fields separated by dots in the token form.

Header

This part to be used in JWT is written in JSON format and consists of 2 fields. These are the token type and the name of the algorithm to be used for signing.

Payload (Data)

This section includes claims. The data kept in this section is unique between the token client and server. This captured claim information also provides this uniqueness.

Signature

This part is the last part of the token. Header, payload and secret key are required to create this part. With the signature part, data integrity is guaranteed.

What is OAuth2 ?

OAuth2 is an open authorization protocol used in data communication between applications. Lets think that we have developed an authorized application which includes OAuth2 support. So once we authorized the user group then we can give access to the data source of another application with the OAuth2 protocol.

For example, when a user connects or logs in to the web application you are developing with facebook, google or github. OAuth2 is a protocol used for user authorization, not for authentication. Applications such as Google, Facebook, Twitter provide OAuth2 support and verified users in these applications can be authorized to other developed web applications that use and rely on the Oauth2 protocol.

OAuth2 is the industry-standard protocol for authorization. It delegates user authentication to the service that hosts the user’s account and authorizes third-party applications to access that account. In short, OAuth2 performs the authorization process between applications.

There is industry standard documentation regarding OAuth 2.0 — RFC 6749 that helps us a lot to understand OAuth related topics.

OAuth2 Authorization Types and Flows

OAuth2 Grant Types or authorization flows determine the interaction between a client application and token service. We have said that the OAuth2 protocol is a protocol that does not provide user authentication but has the necessary support for it.

OAuth2 authorization types:
Authorization Code Grant
Implicit Grant
Resource Owner Password Credential Grant
Client Credential Grant

We can see roles included in OAuth2 flows with the image here;

Client Application: A client application is an application that accesses protected data sources on behalf of the resource owner. (Web, Javascript, mobile…)
Client applications are classified as public and confidential. Public client applications; native applications (applications developed for desktop, tablet, mobile, etc.), user-agent based applications (Javascript based or SPA applications).

Resource Owner: The person (end user) or application that owns the data in the system.

Authorization Server: Gives access tokens within the resource owner authority for authenticated client applications. In short, it manages authorization and access.

Resource Server: Allows access according to the access token and authorization scope by managing the data source that needs to be protected. The protected data source can be eg profile information or personal information of the person.

What is OpenId Connect ?

OpenId 1.0 is a simple authentication layer built on the OAuth2 protocol in fact OpenID Connect is an extension on top of OAuth 2.0. In addition to the end user authentication by an Authorization Server for client applications, it enables the end user to obtain simple profile information with a structure similar to REST. OpenId Connect (OIDC) provides an API friendly structure compared to previous versions. OIDC is an extension that extends the OAuth2 Authorization Code Grant structure.

OIDC keeps transactions simple, built on OAuth2, and simplifies token (JWT) usage. It can be integrated with OIDC web applications, mobile applications, Single page applications (SPA) and server side applications.

OIDC is the industry-standard protocol for authentication.
There is great documentation regarding OIDC — Core as below link that helps us a lot to understand OIDC related topics.

https://openid.net/specs/openid-connect-core-1_0.html

OpenID Connect Endoints

Authorization Endpoint: It is an endpoint defined in OAuth2. It is responsible for the authentication and consent process of the end user.
Token Endpoint: Allows the exchange of a client application with the authorization code or client Id and client secret and access token.
UserInfo Endpoint: It is an endpoint defined with OIDC. A client or resource server is the point where additional claim requests are provided.

You can check the details of OpenId Connect Endpoints and other details in below urls. I am sharing reference document links into video.
OpenID Connect Core 1.0 (spec)
OpenID Connect Discovery 1.0 (spec)

OpenID Connect Authentication Flows

As you know that OAuth2 has defining Authorization Grant and Extension Grant (extension authorizations), so as the same way OIDC defines authentication flows.

There are three authentication flows. These flows differ according to the parameters passed to the OpenId Provider (OP), the content of the responses and how they are processed. The difference between the requests made to the Authorization Endpoint is determined by the response_type parameter.

Flows and parameter values;

Authorization Code Flow -> “code”
Implicit Flow -> “id_token” or“id_token token”
Hybrit Flow -> “ code id_token” or“code token” or “code id_token token”

When we see the code value in the response_type parameter, the authorization endpoint always returns the authorization code.

If an id_token is included in a response_type, the id_token is included in the response, or an access token will be included in the response from the auhorization endpoint if the token is included in the response_type parameter.

In short, this parameter determines the response structure and which operation steps the client application will use.

For these three flows, the Authorization Code Flow is an extension of the OAuth2 Authorization Code Grant.

OIDC Implicit Flow and Hybrid Flow are an extension of Authorization Code Flow.

What is Identity Server 4 ?

Identity Server4 is an open source framework which implements OpenId Connect and OAuth2 protocols for .Net Core.
With IdentityServer, we can provide authentication and access control for our web applications or Web APIs from a single point between applications or on a user basis.

IdentityServer determines how is your web or native client applications that want to access Web Api or Api (Resource) in corporate applications or modern web applications can be accessed using authentication and authorization. So for this operations, there is no need to write identification specific to the client application on the Web API side.

You can call this centralized security system as a security token service, identity provider, authorization server, IP-STS and more.
As a summary IdentityServer4 provides that issues security tokens to clients.

IdentityServer has a number of jobs and features — including:

  • Protect your resources
  • Authenticate users using a local account store or via an external identity provider
  • Provide session management and single sign-on
  • Manage and authenticate clients
  • Issue identity and access tokens to clients
    validate tokens

Identity Server 4 Terminologies

Basically, we can think of our structure as client applications (web, native, mobile), data source applications (web api, service) and IdentityServer application. You can see these system into image.

Client Applications
Client Applications are applications that want to access secure data sources (Web Api) that users use. A client must be first registered with IdentityServer before it can request tokens.
Examples for clients are web applications, native mobile or desktop applications, SPAs, server processes etc.

Resources
Data Resources are the data we want to be protected by IdentityServer. Data sources must have a unique name and the client that will use this resource must access the resource with this name.

IdentityServer
IdentityServer that we can say OpenId Connect provider over the OAuth2 and OpenId protocols. In short, it provides security tokens to client applications. IdentityServer protects data sources, ensures authentication of users, provides single sign-on and session management, verifies client applications, provides identity and access tokens to client applications and checks the authenticity of these tokens.

Identity Token
Identity Token represents to the result of the authentication process. It contains a sub-identifier for the user and information about how and when the user will be authenticated. It also contains identity information.

Access Token
Access Token provides access to the data source (API). The client application can access the data by sending a request to the data source with this token. Access token contains client and user information. The API uses this information to authorize and allow access to data.

Identity Server 4 in Microservices World

The security of the application we have developed that the protection and management of the data used by the application are very important. With the developing technology, the access of applications or devices in different technologies to our data may have some security and software problems or additional loads for us.

For example, let’s assume that the users of a SPA (Single Page App) Client application that will use a Web API we have developed log into the system with their username and password. Then, when another client web application to our same Web API wants to verify with windows authentication and enter, a native mobile client application wants to access or another web API wants to access the Web API that we have developed, the security supported by each client application technology, we may need to develop or configure the security part of our application.

In such a case, you can see the image, we need a central (Authentication / Authorization Server) application on the basis of client and resource (api) dynamically for the access and security of client applications and data sources for the same user groups.
In microservice architectures, authentication is handled centrally by nature.

So in this article, we are going to develop our protected api resource and client web applications which consumes the apis. In order to secure our application we will develop the Authentication Server which will be the IdentityServer4. So by this way, the client is going to get the token from Authentication Server and send this token when calling the protected api. Also we will add an API gateway in this picture and protect our apis over the ocelot api gateway.

Building API Resources — MOVIE.API ASP.NET WEB API PROJECT

In this section, we are going to learn how to build Asp.Net Web API projects as API Resources for our target architecture.

Let’s check our big picture of the architecture of what we are going to build one by one.

As you can see that We are going to start with developing the Movies.API project. This API project will have Movies data and performs CRUD operations with exposing api methods for consuming from clients.

Our API project will manage movie records stored in a relational in-memory database as described in the table above. These movies data will be our protected resource and after developing this api project, we will protect our movies resources with Identity Server.
We will use In-Memory Database when developing CRUD operations with Entity Framework.

Create Asp.Net Core Web API Project For Movies.API Microservice

I am not going to develop all details in here, this will be the Asp.Net Core Web API Project which implemented CRUD operations for Movies Entity with Entity Framework In-Memory Database.

So you can check development of this project into github link of project;

This is the Movies.API project as you can see in the below solution view of project;

Building Identity Server 4

In this section, we are going to learn how to build Identity Server 4 Authentication Microservices for our target architecture.

Let’s check our big picture of the architecture of what we are going to build one by one.

As you can see that we have developed Movies.API project in previous section. So in this section, we are going to continue with developing the Identity Server project.
This project will be Asp.Net Core Empty Web Application and will install IdentityServer4 nuget package in order to be centralized standalone Authentication Microservices.

Identity Server4 is an open source framework which implements OpenId Connect and OAuth2 protocols for .Net Core.
With IdentityServer, we can provide authentication and access control for our web applications or Web APIs from a single point between applications or on a user basis.

Create Asp.Net Core Empty Project :
Right Click — Add new Empty Web App — HTTPS — n : IdentityServer

Right Click Manage Nuget Packages :
Browse IdentityServer
Install IdentityServer4

Go to Startup.cs and Configure Services
Register into DI

 public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer();
}

Add pipeline

 app.UseRouting();
app.UseIdentityServer();

Configure IdentityServer4 with Clients, Resources, Scopes and TestUsers

We are going to configure IdentityServer4 with Clients, Resources, Scopes and TestUsers.
Identity Server required additional configurations to successfully run the application.

Open Startup.cs
Extend Register AddIdentityServer method;

services.AddIdentityServer()
.AddInMemoryClients(new List<Client>())
.AddInMemoryIdentityResources(new List<IdentityResource>())
.AddInMemoryApiResources(new List<ApiResource>())
.AddInMemoryApiScopes(new List<ApiScope>())
.AddTestUsers(new List<TestUser>())
.AddDeveloperSigningCredential();

IdentityServer4 Clients, Resources, Scopes and TestUsers

We are using IdentityServer4 In-Memory Configuration. And for now, we are giving the configurations as an empty list.
Let me briefly explain these configurations on Identity Server. First of all, we don’t need to fill all the configurations, I put here in order to check all configs.

ApiResources
ApiScopes

An API is a resource in your system that you want to protect. Resources or Apis is the part where the data source or web service we want to protect is defined.
So for that reason we have defined ApiResources and ApiScopes. Scopes represent what a client application is allowed to do.

Clients
IdentityServer needs to know what client applications are allowed to use it. Clients that need to access the Api resource are defined in the clients section. Each client application is defined in the Client object on the IdentityServer side. A list of applications that are allowed to use your system.

IdentityResources
IdentityResource is information that includes user information such as userId, email, name, has a unique name and we can assign claim types linked to them. Identity Resource information defined for a user is included in the identity token. We can use Identity Resource that we defined with scope parameter in client settings.

TestUsers
Test users that will use the client applications need to access the Apis. So for client application we should also defined test users.

DeveloperSigningCredential
Creates temporary key material at startup time. This is for dev only scenarios when you don’t have a certificate to use. The generated key will be persisted to the file system so it stays stable between server restarts.

Adding Config Class for Clients, Resources, Scopes and TestUsers

We are going to add Config Class for Clients, Resources, Scopes and TestUsers definitions on IdentityServer4.

First of all, we are going to do is create a new Config class. This class will consist of different configurations related to Users, Clients, IdentityResources, etc. So, let’s add them one by one.

Add Config.cs into IdentityServer project;

 public class Config
{
public static IEnumerable<Client> Clients =>
new Client[]
{
};
public static IEnumerable<ApiScope> ApiScopes =>
new ApiScope[]
{
};
public static IEnumerable<ApiResource> ApiResources =>
new ApiResource[]
{
};
public static IEnumerable<IdentityResource> IdentityResources =>
new IdentityResource[]
{
};
public static List<TestUser> TestUsers =>
new List<TestUser>
{
};
}

Change Startup.cs DI Register;

services.AddIdentityServer()
.AddInMemoryClients(Config.Clients)
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiResources(Config.ApiResources)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddTestUsers(Config.TestUsers)
.AddDeveloperSigningCredential();

Verify that discovery link is working
OpenID Connect Discovery Document
https://localhost:5005/.well-known/openid-configuration

Protecting Movie.API With Using Identity Server 4 JWT Token

In this section we are going to protect Movie.API resources with using IdentityServer 4 and JWT Token.

Let’s check our big picture of the architecture of what we are going to build one by one.

As you can see that, in the previous sections, we have developed Movies.API and Identity Server project in previous section.

So in this section, we are going to protect this API resources with IdentityServer4 OAuth 2.0 implementation. Generate JWT Token with client_credentials from IdentityServer4 and will use this token for securing Movies.API protected resources.

After generate a JWT Token, We can use this access token to access API, protected by your implementation of IdentityServer.

We are going to configure our identity server project in order to protect our movie api project.
We will define our ApiScopes and Clients into Config class and configure our services.

First of all, we are going to add a new ApiScope which is Movie API in the Authorization Server. So, let’s add that one.

Defining an API Scope in Config.cs;

public static IEnumerable<ApiScope> ApiScopes =>
new ApiScope[]
{
new ApiScope(“movieAPI”, “Movie API”)
};

Additionally, we should create a new client which will request to reach protected movie.api resources.

Defining the client in Config.cs

public static IEnumerable<Client> Clients =>
new Client[]
{
new Client
{
ClientId = “movieClient”,
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets =
{
new Secret(“secret”.Sha256())
},
AllowedScopes = { “movieAPI” }
}
};

And finally, we should configure IdentityServer as per our protected resource. That means we should summarize the identity server configuration.

Configuring IdentityServer

public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddInMemoryClients(Config.Clients)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddDeveloperSigningCredential();
}

Run application
Get Success

Verify that discovery link is working
OpenID Connect Discovery Document
https://localhost:5005/.well-known/openid-configuration

Check with https://jsonformatter.org/

As you can see that, we can inspect the moviesAPI into supported scopes as well.

See below scopes “movieAPI

“scopes_supported”: [
“movieAPI”,
“offline_access”
],

Get Token from Identity Server with client_credentials grant_type

We are going to Get the Token from Identity Server with client_credentials grant_type.

First of all, we are going to run IdentityServer Application
Once we start our application, we are going to get information that our server is up and running and using in-memory grant store in the console window.

Run IdentityServer Application
See its working well with discovery link

Check Discovery document and see token_endpoint

“authorization_endpoint”: “https://localhost:5005/connect/authorize",
“token_endpoint”: “https://localhost:5005/connect/token",

Let’s try now to retrieve a token from our authorization server with a Postman request:

Get token from Postman

Create New Request into Postman “IdentityServer” Folder into Collection
Add “GET Token” request

Set POST
POST https://localhost:5005/connect/token

Click “Body” Section
Pick “x-www-form-urlencoded”

Set below parameters:

grant_type = client_credentials
scope = movieAPI
client_id = movieClient
client_secret = secret

As you can see, we are using /connect/token endpoint to retrieve the token from the server. For parameters, we provide client_id, client_secret, client_credentials as a grant_type and scope. Once we press the Send button, we are going to receive our token.

Get token response

{
“access_token”: “eyJhbGciOiJSUzI1NiIsImtpZCI6IkIzQ0ZCMkE5Qjg2QzBDQjJDMDRDQjc2N0U0RUUyMUQ2IiwidHlwIjoiYXQrand0In0.eyJuYmYiOjE1OTg2MTIzMDYsImV4cCI6MTU5ODYxNTkwNiwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NTAwNSIsImNsaWVudF9pZCI6Im1vdmllQ2xpZW50IiwianRpIjoiREI1OTk5OERBODYyRjU0MjgzNURBRDc4NDg3MTJCMEYiLCJpYXQiOjE1OTg2MTIzMDYsInNjb3BlIjpbIm1vdmllQVBJIl19.YL20fNhfy9hIXI0v1cc9SIpNLH5ht7BNiLihLueZKtKibzYqFta9cmJw1z3nB1NMGl1IzhGH4PItn_KNWD8fHcU51S35IUcHOKnNKJ_upL8vpesTXWB4WAxdFJhF5c4nOvcGrStaWx6B1dymnNrPFJwWqW_Td4xNCpmNswrSRwSKb0ObKFjJNlz2NnqbaCb-AvjwbDzFCLy2-soc7GiilqdUVxevi5vfb1WuYCdzPB9y5OMflMP5Dyny1uA9d9m5LIw4gYlYx5KjQJOPBJqY3I95aMHXJYRv5N08q2sMlaI9aP_XQ5MMlwuWyKejJprLNFl4KMuw62M6d9Ug2TshkA”,
“expires_in”: 3600,
“token_type”: “Bearer”,
“scope”: “movieAPI”
}

If you take this access token over to jwt.io, you can see that it contains the following claims:

Go to https://jwt.io/
Paste token
See payload details

{
“nbf”: 1598612306,
“exp”: 1598615906,
“iss”: “https://localhost:5005",
“client_id”: “movieClient”,
“jti”: “DB59998DA862F542835DAD7848712B0F”,
“iat”: 1598612306,
“scope”: [
“movieAPI”
]
}

As you can see that we can successfully generate to token for protecting our movie api with movieClient definition.

Securing Movies.API with JWT Bearer Token Authentication

First of all, we are going to add Nuget Dependency into Movies.API project. Because we will protect this api project with jwt bearer token authentication.

Adding a Nuget Dependency into Movies.API
package Microsoft.AspNetCore.Authentication.JwtBearer

After that, in order to activate jwt bearer token athentication, we should register JWT Authentication into asp.net core dependency injection method. In the Startup.cs — ConfigureServices method, we should register and configure jwt authentication with adding service collection.

Add the Authentication services to DI (dependency injection)

public void ConfigureServices(IServiceCollection services)

services.AddAuthentication(“Bearer”)
.AddJwtBearer(“Bearer”, options =>
{
options.Authority = “https://localhost:5005”;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
});

We use the AddAuthentication method to add authentication services to the dependency-injection of our web api project. Moreover, we use the AddJwtBearer method to configure support for our Authorization Server.

After that we should also add the authentication middleware into the aspnet pipeline. Go to Startup.cs — Configure method and adding authentication middleware;

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)app.UseRouting();app.UseAuthentication();
app.UseAuthorization();

And finally, we should Authorize the API Controller which is MoviesController in Movies.API project. By this way we can protect our api resources.

[Route(“api/[controller]”)]
[ApiController]
[Authorize]
public class MoviesController : ControllerBase

OpenID Connect with IS4 For Interactive MVC Movie Client Microservice

In this section we are going to integrate IS project with the mvc client application for performing interactive client operations. This section we are going to focus on Movies.Client project in order to integrate with IS4 with OpenID Connect.

Let’s check our big picture of the architecture of what we are going to build one by one.

As you can see that, we have developed Identity Server and the Movies.Client MVC Interactive Client Application. In order to make interactive client operations we should integrate our MVC application with the centralized Identity Server application. We are going to authorize our Movie page and redirect for login operation to the IdentityServer UI Login page and after success login it will get the token and redirect back to MVC application to continue to its operations inside of the MVC application.

Add new Client into IS4 Config.cs

Our Client application Movie.Client MVC app was in https urls = https://localhost:5002

Let’s add a client;

Adding new interactive client ; Config.cs

public static IEnumerable<Client> Clients =>
new Client[]
{
new Client
{
ClientId = “shopping_web”,
ClientName = “Shopping Web App”,
AllowedGrantTypes = GrantTypes.Code,
AllowRememberConsent = false,
RedirectUris = new List<string>()
{
https://localhost:5003/signin-oidc” — this is client app port
},
PostLogoutRedirectUris = new List<string>()
{
https://localhost:5003/signout-callback-oidc"
},
ClientSecrets = new List<Secret>
{
new Secret(“secret”.Sha256())
},
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
}
};

So, we provide the properties of client like ClientId, ClientName and the ClientSecret for this client. So let me explain this client properties.

After that, we should Adding IdentityResources which information will be shared when login;

public static IEnumerable<IdentityResource> IdentityResources =>
new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile()
};

Finally, let’s add the users into the configuration Adding Test users which is login;

public static List<TestUser> TestUsers =>
new List<TestUser>
{
new TestUser
{
SubjectId = “5BE86359–073C-434B-AD2D-A3932222DABE”,
Username = “mehmet”,
Password = “mehmet”,
Claims = new List<Claim>
{
new Claim(JwtClaimTypes.GivenName, “mehmet”),
new Claim(JwtClaimTypes.FamilyName, “ozkaya”)
}
}
};

Also we need to modify registering DI — InMemory Configuration

public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddIdentityServer()
.AddInMemoryClients(Config.Clients)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddTestUsers(Config.TestUsers)
.AddDeveloperSigningCredential();
}

Build OpenId Connect Interactive Client for Movies.Client MVC Application

We are going to configure OpenID Connect Authentication layer for our Movies.Client MVC Application. So the idea is create authentication layer for our MVC Client application. We are going to protect Movies page into MVC application and users will login the system when try to reach Movies page. In order to navigate users to IdentityServer Login page, we should configure our mvc client application in order to be an interactive client for Identity Server. As you remember we were defined our “shopping_web” client into our Config class in IdentityServer project. So now we are going to configure this client for authentication layer in MVC client application.

Go To Project -> Movies.Client

First of all we will start with adding OpenIdConnect nuget package;

ADD NUGET PACKAGE

dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect

install and build the application.

Now we can configure our MVC application with OpenIdConnect authentication. So let me write first and will explain later, configuring OpenIdConnect authentication;

MVC APP CONFIGURE DI APP

public void ConfigureServices(IServiceCollection services)services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = “https://localhost:5005”;

options.ClientId = “shopping_web”;
options.ClientSecret = “secret”;
options.ResponseType = “code”;

options.Scope.Add(“openid”);
options.Scope.Add(“profile”);
options.SaveTokens = true;options.GetClaimsFromUserInfoEndpoint = true;
});

First of all we adding authentication services as usual with adding cookie also. We set default authentication scheme for this service dependecies.

We register authentication as a service and populate the DefaultScheme and DefaultChallengeScheme properties.
After that, We add the AddCookie method with the name of the AuthenticationScheme, in order to register the cookie handler and the cookie-based authentication for our Authentication Scheme.

And the most important part is adding AddOpenIdConnect method.

We call AddOpenIdConnect method in order to register and configure the OIDC handler for our OpenID Connect integration.

The Authority property has the value of our IdentityServer address.
The ClientId and ClientSecret properties must be the same as the client id and client secret from the Config class of our IdentityServer for this client.
The ResponseType property, We set it to the code value and therefore, we expect the code to be returned from the /authorization endpoint.

We added OpenID and profile scopes for our options in order to access user information.

The SaveTokens property to true to store the token after successful authorization.

Hybrid Flow of Identity Server Secure Interactive MVC Client (OpenID) and API Resources (OAuth) with Together

We are going to implement hybrid flow of OICD Authentication flows when we want to get tokens over the front and back channels.

Let’s check our big picture of the architecture of what we are going to build one by one.

As you can see that, we have developed Movies.Client MVC project for the interactive client with OpenId Connect.
And also we have developed Movies.API project for protected resources with OAuth 2.
So now we are going to combine these two operation and povide to security in one hybrid flow.

Using Hybrid Flow For Getting Token and Combine Scopes for Interactive Channel

First of all, we are going to change our flow to Hybrid flow. So we should modify our GrantTypes into Config.cs.

Go To IDENTITYSERVER Project
Config.cs
Clients
ClientId = “movies_mvc_client”,

 AllowedGrantTypes = GrantTypes.Code, — REMOVED
AllowedGrantTypes = GrantTypes.Hybrid, — ADDED
RequirePkce = false, — ADDED

After that, in the same place, we will extend our scopes with adding “moiveAPI” into our Allowed Scopes. By this way we can access the movie API with using only one token which getting with OpenId Connect Interactive Client.

Go To IDENTITYSERVER Project
Config.cs
Add AllowedScopes of OpenID Connect

AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
“movieAPI” — ADDED
}

Check Startup.cs of IS4 that API resource or scopes added or not.

Go To IDENTITYSERVER Project
Startup.cs — ConfigureServices

services.AddIdentityServer()
.AddInMemoryClients(Config.Clients)
.AddInMemoryApiScopes(Config.ApiScopes)

And after finish the config operations in IS project, we can update ResponseType of our Interactive MVC Client project in order to connect with Hybrid flow.

Go to MVC.Client — Startup.cs — ConfigureServices which defined OpenID connect and add api scope.

services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = “https://localhost:5005”;
options.ClientId = “movies_client”;
options.ClientSecret = “secret”;
— — options.ResponseType = “code”; — REMOVED
options.ResponseType = “code id_token”; — ADDED

We will use “code id_token” hybrid flow with giving the response type value.

Add Scope ;


options.Scope.Add(“openid”);
options.Scope.Add(“profile”);
options.Scope.Add(“movieAPI”); — ADDED !

In the same place, we should add “movieAPI” scope in order to access with the same authentication access. By this way we can access api and identity values with getting 1 token in a hybrid flow.

Ocelot API Gateway Implementation For Movies MVC Client to Interact with Identity Server and Carry the Token

We are going to implement Ocelot API Gateway for Movies.MVC Client Application to interact with Identity Server and carry the token.

Let’s check our big picture of the architecture of what we are going to build one by one.

As you can see that, Ocelot API gateway staying in the middle of our architecture.
We are going to develop Ocelot Api Gateway in the middle of our architecture.
We are using Ocelot in here, for acting as a reverse proxy for a secured internal ASP.NET Core Web API projects. So that’s why I am not going to give deep information about Ocelot API Gateway.
It will open apis to MVC Movies.Client application and consumes the protected movie.api resources with carrying token which retrieved from Identity Server.

Securing Ocelot API Gateway with Bearer Token

We are going to Secure Ocelot API Gateway with Bearer Token. For proving security in Ocelot, we are going to use AuthenticationOptions in to ocelot.json configuration file.

First of all we are going to modify our configuration file.

Go to -> “ApiGateway
Go to -> ocelot.json

Put below codes for authentication, carry to bearer token :

“AuthenticationOptions”: {
“AuthenticationProviderKey”: “IdentityApiKey”,
“AllowedScopes”: []
}
All parts :
{
“DownstreamPathTemplate”: “/api/movies”,
“DownstreamScheme”: “https”,
“DownstreamHostAndPorts”: [
{
“Host”: “localhost”,
“Port”: “5001”
}
],
“UpstreamPathTemplate”: “/movies”,
“UpstreamHttpMethod”: [ “GET”, “POST”, “PUT” ],
“AuthenticationOptions”: {
“AuthenticationProviderKey”: “IdentityApiKey”,
“AllowedScopes”: []

}
}

After that, we should provide JWT Bearer token configuration into Ocelot application.

Go to -> “ApiGateway
Startup.cs

Add below authentication layer:

public void ConfigureServices(IServiceCollection services)
{
var authenticationProviderKey = “IdentityApiKey”;
// NUGET — Microsoft.AspNetCore.Authentication.JwtBearer
services.AddAuthentication()
.AddJwtBearer(authenticationProviderKey, x =>
{
x.Authority = “https://localhost:5005”; // IDENTITY SERVER URL
//x.RequireHttpsMetadata = false;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
});
services.AddOcelot();
}

Secure Existing Microservices Application With adding Identity Server Integration over the Ocelot and APIs.

We are going to Secure Existing Microservices Application With adding Identity Server Integration over the Ocelot and APIs.

Let’s check our big picture of the existing microservices architecture. This is basically an implementation of e-commerce domain in a microservices architecture.

As you can see that, we have developed a reference microservices architecture before this course. But the security part is missing. So we should developing Identity microservices in this picture by applying this article.

Before that, let me share the source code of an existing microservices architecture. You can find the repository in below link, please star and fork the repository and start working on it. Once you developed you can send me pull request, I will evaluate and merge the codes if it is expected.

https://github.com/aspnetrun/run-aspnetcore-microservices

TODO List of Identity Microservices

Ok now we can talk about todo list.
In this assignment I have created this todo list which you can extend this list.

Of course start with the -> Download and Run the Final Reference Microservice Application

  • Create Identity Server Microservice into Reference Microservice Application
  • Add Configurations for Identity Server Microservice
  • Create Clients, Identity Resources and Testusers
  • Create User Interface for Identity Server
  • Set Authentication for Shopping MVC Interaction Client
  • Login the Application Securing with Identity Server
  • Add Login / Logout Button into Shopping Web Client Application

I am not going to develop all details in here,

So you can check development of this project into github link of project;

Step by Step Development w/ Course

I have just published a new course — Securing .NET 5 Microservices with IdentityServer4 with OAuth2, OpenID Connect and Ocelot Api Gateway.
In the course, we are securing .Net 5 microservices with using standalone Identity Server 4 and backing with Ocelot API Gateway. We’re going to protect our ASP.NET Web MVC and API applications with using OAuth 2 and OpenID Connect in IdentityServer4.

--

--

Mehmet Ozkaya
aspnetrun

Software Architect | Udemy Instructor | AWS Community Builder | Cloud-Native and Serverless Event-driven Microservices https://github.com/mehmetozkaya