Build Your Own Authentication Server for Single Sign-On (SSO) in ASP.NET Core

Discuss how to build a custom authentication server for SSO using ASP.NET Core Identity and Identity Server.

Shawn Shi
Geek Culture
5 min readJan 24, 2023

--

Background

On the software as a service (SaaS) market, there are quite some single sign-on providers, such as Microsoft Azure Active Directory (AD), Okta Identity Cloud. In the meantime, there are cases when off-the-shelf solutions just do NOT work or are NOT customizable enough. That is when a custom authentication server needs to be built for single sign-on, let’s call it SSO server in this article.

In a previous article, we discussed at the high-level, how a custom SSO server can be developed, highlighting the major components. Let’s recap!

How to build a single sign-on server — major components:

  1. User membership management, such as user name, email, roles, etc..
  2. Configuration data management, such as clients, referring to applications that should have access to the SSO server, identity resources, referring to user identity data, API scopes, referring to API services that are protected by the SSO server, etc..
  3. Operational data management. such as refresh tokens generated by the SSO server, and keys for digital signature, etc..
  4. Protocol implementation. The standard protocol is OpenID Connect and OAuth 2.0. OpenID Connect is for authentication purpose and is built above OAuth 2.0, which is for authorization.

Goal

The goal is to discuss a starter project that have included the above components so that you can get up and running quickly. By the end of this article, you should be able to run a SSO server web application with a seeded user called admin@test.ca, and see a login screen like below! Note the UI should be fully customizable. The logo in the screenshot below is from Duende, who provides the Identity Server library.

Getting Started

System Diagram

Let’s first look at the system diagram below. The SSO Server is single web application, and it communicates with a single database. Tables for user data, configuration data, and operational data can all be sitting in the same database.

The most obvious advantage of having configuration data and operational data stored in a database instead of code files or app settings files, is that changes to such data will not requires app restart. Another benefit is that we can run multiple instances of the SSO server in a load balancing environment. These instances all share the same data.

System Diagram

Dry Run

You should be able to just follow along without the source code. However, if you would like to navigate through the code or even give it a dry run, the sample code in this article is hosted in a GitHub project. You can simply clone the repo, and run the SSO Server project in Visual Studio or using command line. See more details in the README file.

Solution Overview

As you can see, there is one single project called SsoServer in the solution. The SsoServer project is a .NET Core web application. At the moment, only Razor pages are added, but we can certainly add API endpoints using MVC to the same application hosting the razor pages.

Project Entry Point

Program.cs is the project entry point, i.e., the first method to be executed when the application runs. Three major tasks are completed here:

  1. Configure logging using Serilog.
  2. Configure the Dependency Injection services by calling ConfigureServices() in line 20.
  3. Configure the HTTP request pipeline such as middlewares by calling ConfigurePipeline() in line 21.

Now let’s examine Configure Services method and Configure Pipeline method.

Key take away notes:

  • Line 24 to 39 configures the use of ASP.NET Core Identity for user membership management using a Sqlite database, which is pointed to by the connection string defined in line 22. Entity Framework is set up to interact with the database, including managing database schema using code-first approach. Initial migrations to create all ASP.NET Core Identity relevant tables are provided in path Data/Migrations/AspNetCoreIdentity.
  • Line 32 to line 55 configures the use of Identity Server to implement SSO. Line 45 indicates all the configuration data, such as clients, API resources, identity resources, are stored in a Sqlite database pointed by the same connection string for user data. Line 50 does the same thing for operational data, such as keys, refresh tokens. Line 55 integrate user lookup with ASP.NET Core Identity.
  • Line 72 to line 74 ensure the database tables requires are created and initial data is seeded, in development environment only. Database schema update is done through Entity Framework migrations. Both database update and data seeding are done at application start up.

User Management using ASP.NET Core Identity

In development environment, we automatically apply Entity Framework migrations by calling EnsureAspNetCoreIdentityDatabaseIsSeeded method, as defined below, in order to create the ASP.NET Core Identity tables. Data seeding is also done here. See AspNetCoreIdentitySeeder.cs for detailed code for seeding roles and seeding users.

In the screenshot below, every table that starts with “AspNet” are part of the ASP.NET Core Identity tables.

Sqlite database for SSO Server

Configuration Data Management using Identity Server

Similar to how ASP.NET Core Identity tables are automatically created in development environment, the following method is called for table creation and data seeding for configuration data. Tables like Clients, ClientClaims, IdentityResources, etc. are all part of this. Check out the “ConfigurationDbContext” for a full list of tables created by this method. See IdentityServerConfigurationDbSeeder.cs for detailed code for SeedIdentityResources, SeedApiScopes, SeedClients.

Operational Data Management using Identity Server

Similarly, the following method is called for table creation and data seeding for operational data. Tables like keys, persisted grants are part of this. Check out the “OperationalDbContext” for a full list of tables created by this method.

Conclusions

That’s it! We now have covered everything we need to get a SSO server up and running, so we can move on to adding new clients, new identity resources and API resources to protect, and customize UI for our own branding, etc.. Hope this will save you hours from the complexity of setting up what we have covered in this article!

If you have read to this point, give yourself a pat on the shoulder! Thanks for reading! Cheers!

Related resources:

This is part 2 of a series of articles discussing how to build a centralized authentication server using ASP.NET Core. Other articles can be found here:

  1. Single Sign-On (SSO) Simplified: Understanding How SSO Works in Plain English
  2. Build Your Own Authentication Server for Single Sign-On (SSO) in ASP.NET Core
  3. REST API for User Management in Authentication Server for Single Sign-On
  4. REST API for User Management in Authentication Server for Single Sign-On (2)
  5. Protect Web API using Your Own Authentication Server
  6. Access Web API Protected by Your Own Authentication Server

--

--

Shawn Shi
Geek Culture

Senior Software Engineer at Microsoft. Ex-Machine Learning Engineer. When I am not building applications, I am playing with my kids or outside rock climbing!