Identity Server
IdentityServer is a .Net/Katana-based framework and hostable component that allows implementing single sign-on and access control for modern web applications and APIs using protocols like OpenID Connect and OAuth2. It supports a wide range of clients like mobile, web, SPAs and desktop applications and is extensible to allow integration in new and existing architectures.1
Features
- Authentication as a Service Centralized login logic and workflow at a single & well-secured place.
- Single Sign-on / Sign-out Single sign-on (and out) over multiple application types like web or mobile.
- Access Control for APIs Issue access tokens for APIs for various types of clients, e.g. server to server, web applications, SPAs and native/mobile apps.
- Federation Support for external social identity providers like Google, Facebook etc, as well as integration for enterprise identity management systems via SAML and WS-Federation.
- Customization The most important part – every aspect of IdentityServer can be customized to fit your needs. Since IdentityServer is a framework, you can write code to adapt the system in a way it makes sense for your scenarios.
Terminology
OpenID Connect Provider (OP)555
OpenID Connect Provider is a piece of software that implements OpenID Connect Protocol, (which is built on top of OAuth2) and issues Security Tokens to Clients. Please refer to the link https://openid.net/connect for details about OpenID Connect. There are other terms which refers to OP like Security Token Service (STS), Identity Provider, Authorization Server. Identity Server is an OpenID Connect Provider.
Client
Scope
Identity scopes
Resource scopes
Identity Token
Access Token
Applications Interactions

As seen in the diagram:
- 1. Browser communicates with Web Application.
- 2. Web application and Mobile APP communicate with APIs
- 3. APIs interacts with other APIs
- 4. Server Apps (e.g. Windows Service) communicate with APIs.
All of this communication needs to be authenticated to prevent attacks and secure data. We can use OAuth and OpenID connect for this as shown in the following diagram.
As seen in the following diagram, we need to use combination of OpenID connect an OAuth2. Identity Server 3 is an implementation of these two protocols and is highly optimized to solve the typical security problems of modern applications.

Identity Server Flows
1. Authorization Code flow
- The Authorization Code flow returns an authorization code after user authentication that can be used to retrieve Access Token and Refresh Token.This flow requires client authentication using ClientId and Client Secret which can be used to get Access Token from back end. The access token is not exposed to user agent. It also supports long lived refresh tokens which can be used to renew expired access token.
- This flow obtains the authorization code from the authorization endpoint and all tokens are returned from the token endpoint.
- This flow is suitable only for clients who are capable of maintaining a client secret between itself and the STS securely, for example Server side MVC applications.
2. Implicit flow
- This flow requests tokens without explicit client authentication, instead using the redirect URI to verify the client identity
- Since this flow does not require explicit client authentication; Refresh Tokens are not supported. So to renew token, the client needs to send request to authorization endpoint.
- This flow obtains all tokens from authorization endpoint only.
- It is suitable for browser applications like Single Page Applications.
3. Client Credentials Flow
- This is pure OAuth2 flow, OpenID connect is not involved in this flow.
- This flow is used when applications request an access token to access their own resources, not on behalf of a user. For example, server to server communication like API to API call.
- The client is authenticated by ClientId and Client Secret.
Sample Application
- Authentication Server using Identity Server – MVC Application
- Client Application – MVC Application
- Resource Server – Web API
Authentication Server Create a new Empty MVC application with ”No Authentication”. Enable SSL for the application from the properties window as shown in the following image.

Install following packages to the application via nuget.
- Owin.Host.Systemweb
- IdentityServer3
Clients
new Client { ClientId = "TestClient", ClientName = "Demo Client Application", Enabled = true, Flow = Flows.Implicit, RequireConsent = false, RedirectUris = new List { "http://localhost:52481/" }, PostLogoutRedirectUris =new List { "http://localhost:52481/" }, AllowedScopes = new List { Constants.StandardScopes.OpenId, Constants.StandardScopes.Profile, Constants.StandardScopes.Email, "GreetingsAPI" } }
Users
public class Users { public static List Get() { return new List { new InMemoryUser { Subject = "ABCD-1234-EFGH-5678", Username = "testuser", Password = "123456", Claims = new List { new Claim(Constants.ClaimTypes.PreferredUserName, "TestUser"), new Claim(Constants.ClaimTypes.Name, "Test User"), new Claim(Constants.ClaimTypes.Email, "test@test.com") } } }; } }
Scopes
public class Scopes { public static IEnumerable Get() { return new List { StandardScopes.OpenId, StandardScopes.Profile, StandardScopes.Email, StandardScopes.Roles, new Scope { Enabled = true, DisplayName = "Greetings API", Name = "GreetingsAPI", Description = "Access to the Greetings API", Type = ScopeType.Resource } }; } }
Configuring Identity Server
We’ll configure IdentityServer in the startup class. Here we’ll provide information about the clients, users, scopes and the signing certificate. In production we should load the signing certificate from the Windows Certificate Store. But here we’ll use test signing certificate provided by Identity Server and we’ll add it in our project itself.
Please follow the instructions provided the link to configure the certificate. Open the Startup class and add the following code to it.
public class Startup { public void Configuration(IAppBuilder app) { app.Map("/identity", identity => { identity.UseIdentityServer(new IdentityServerOptions() { SiteName = "Authentication Server", SigningCertificate = LoadCertificate(), Factory = new IdentityServerServiceFactory() .UseInMemoryClients(Clients.Get()) .UseInMemoryScopes(Scopes.Get()) .UseInMemoryUsers(Users.Get()) }); }); } X509Certificate2 LoadCertificate() { return new X509Certificate2( string.Format(@"{0}binidentityServeridsrv3test.pfx", AppDomain.CurrentDomain.BaseDirectory), "idsrv3test"); } }
<system.webserver> <modules runallmanagedmodulesforallrequests="true"> </modules></system.webserver>
Client Application
Create a new MVC application with “No Authentication” and add following packages to it via nuget.
- Owin.Host.Systemweb
- IdentityServer3
- Owin.Security.Cookies
- Owin.Security.OpenIdConnect
app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = "Cookies" });
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { Authority = "https://localhost:44374/identity", ClientId = "TestClient", RedirectUri = "http://localhost:52481/", ResponseType = "id_token", Scope = "openid email profile", SignInAsAuthenticationType = "Cookies" });
Here the Authority is the url of our Authentication Server, ClientId is the ClientId we registered with the Authentication Server, ReirectUri is the url of this application, which is also registered with Authentication Server. ResponseType is “id_token” which specifies we need Identity Token in response of successful user authentication. Scope is space separate values of the user claims we require. The “opeid” scope must always be there.
The “OpenIdConnectAuthenticationOptions” has also provides various notifications raised on specific events, which we can use to our requirements. We can store the claims received from the Authentication Server in a cookie using “SecurityTokenValidated” notification as shown below.
Notifications = new OpenIdConnectAuthenticationNotifications { SecurityTokenValidated = n => { var claims = n.AuthenticationTicket.Identity; var sub = claims.FindFirst(IdentityServer3.Core.Constants.ClaimTypes.Subject); var name = claims.FindFirst(IdentityServer3.Core.Constants.ClaimTypes.Name); var email = claims.FindFirst(IdentityServer3.Core.Constants.ClaimTypes.Email); var username = claims.FindFirst(IdentityServer3.Core.Constants.ClaimTypes.PreferredUserName); var nid = new ClaimsIdentity(claims.AuthenticationType); nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken)); nid.AddClaim(sub); nid.AddClaim(name); nid.AddClaim(email); nid.AddClaim(username); n.AuthenticationTicket = new AuthenticationTicket(nid, n.AuthenticationTicket.Properties); return Task.FromResult(0); } }
MyProfile Action Method
[Authorize] public ActionResult MyProfile() { var claims = (User as ClaimsPrincipal).Claims; var idClaim = claims.FirstOrDefault(c => c.Type == IdentityServer3.Core.Constants.ClaimTypes.Subject); var nameClaim = claims.FirstOrDefault(c => c.Type == IdentityServer3.Core.Constants.ClaimTypes.Name); var emailClaim = claims.FirstOrDefault(c => c.Type == IdentityServer3.Core.Constants.ClaimTypes.Email); var usernameClaim = claims.FirstOrDefault(c => c.Type == IdentityServer3.Core.Constants.ClaimTypes.PreferredUserName); var model = new ProfileModel { Id = idClaim.Value, Name = nameClaim.Value, Email = emailClaim.Value, Username = usernameClaim.Value }; return View(model); }
MyProfile View
@model ClientApplication.Models.ProfileModel @{ ViewBag.Title = "Profile"; } <h2>Profile</h2> <div class="col-md-12"> <div class="form-group"> <label class="control-label">Id</label> <p class="form-control-static">@Model.Id</p> </div> <div class="form-group"> <label class="control-label">Name</label> <p class="form-control-static">@Model.Name</p> </div> <div class="form-group"> <label class="control-label">Email</label> <p class="form-control-static">@Model.Email</p> </div> <div class="form-group"> <label class="control-label">Username</label> <p class="form-control-static">@Model.Username</p> </div> </div>
Resource Server
Now we’ll create a web api that will be accessed by our client application. This API will be protected using our authentication server. Create a new Web API project and add following nuget packages.
- Owin.Host.SystemWeb
- Aspnet.WebApi.Owin
public class GreetingsController : ApiController { [Authorize] [HttpGet] public IHttpActionResult Get() { return Ok("Hello World"); } }
public class Startup { public void Configuration(IAppBuilder app) { app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions { Authority = "https://localhost:44374/identity", RequiredScopes = new[] { "GreetingsAPI" } }); } }
Here we have specified “RequiredScopes” as “GreetingsAPI”; which is our custom scope that we have registered with OP. So if any client application that wish to access this API must provide a Bearer Authentication Token that contains “GreetingsAPI” scope. So to be able to access this API our client needs to send request to our OP to get Access Token. We’ll use Client Credential flow and “TokenClient” class to get Access Token.
Create a new Action Method in “HomeController” of Client Application. This method will first get the access token and then using this access token it will call the API created above.
private string APIUrl = "http://localhost:58340/api"; private string AuthServerUrl = "https://localhost:44374"; public async Task CallAPIWithToken() { var tokenUrl = $"{AuthServerUrl}/identity/connect/token"; var tokenClient = new TokenClient(tokenUrl, "GreetingAPIClient", "secret"); var tokenResponse = await tokenClient.RequestClientCredentialsAsync("GreetingsAPI"); using (var client = new HttpClient()) { client.SetBearerToken(tokenResponse.AccessToken); var result = await client.GetStringAsync(APIUrl + "/Greetings"); return View((object)result); } }
Full source code for identity server demo using in memory client and users is available on github link.