This is an example of using BankID with ASP.NET Core to achieve Connect (login), and Identify (userinfo and profile) using a code grant.
This example stores user session in a cookie to allow easy interop with standard ASP.NET authentication mechanisms.
- When you first requests
/
route, Correlation cookie forstate
is set and you are be redirected to BankID/auth
EndPoint - After successful authentication, BankID redirects to the
/callback
URL- This verifies Correlation cookie against
state
forwarded from BankID - And sets ASP.NET session cookie
- This verifies Correlation cookie against
- Whenever you visit
/
route again,GetClaims
action from AuthController is called- This extracts
sub
claim from ASP.NET identity as well as theaccess_token
- GetClaims action requests UserInfo and Profile EndPoints from BankID and returns them
- This extracts
- When you wish to logout, visit the
/logout
route- Session is configured to last one hour, after this time access token from BankID would have expired. Using refresh tokens is an exercise left to the reader.
- Install .NET Core SDK of version 5.0 or later
- Navigate into the aspnet folder
- Run
dotnet restore
to fetch dependencies - Run
dotnet run
to start a development server on port 3000 - Navigate to http://localhost:3000
Do note that the application is configured in appsettings.json file.
If you wish to use your own client, make sure to update the BankID
Configuration accordingly and configure http://localhost:3000/callback
callback URL for your application in BankID developer portal.
ASP.NET applications are traditionally configured in Startup.cs file. We are adding cookie and OIDC authentication and an HTTP Client.
Do note the scope configuration during OIDC setup:
config.Scope.Clear();
config.Scope.Add("openid");
config.Scope.Add("profile.email");
config.Scope.Add("profile.addresses");
Bulk of the work happens in our controller AuthController.cs file. In here we define both our application routes (/
and /logout
).
Note the [Authorize]
attribute which says that the action requires authorization
[Authorize]
[HttpGet("/")]
public async Task<IActionResult> GetClaims(CancellationToken ct)
Profile EndPoint address is a non standard value for OpenID Connect discovery and so we need to refetch the discovery and extract this URL manually:
In Startup.cs we register an OIDC configuration manager:
// We need this to access OIDC configuration later to extract Profile endpoint address
var discoveryUri = new Uri(new Uri(_configuration["BankID:Issuer"]), "/.well-known/openid-configuration");
services.AddSingleton<IConfigurationManager<OpenIdConnectConfiguration>>(svc =>
new ConfigurationManager<OpenIdConnectConfiguration>(
discoveryUri.AbsoluteUri,
new OpenIdConnectConfigurationRetriever(),
new HttpDocumentRetriever()));
We then inject and use it in AuthController.cs:
private readonly IConfigurationManager<OpenIdConnectConfiguration> _configurationManager
...
// Refresh OIDC configuration from BankID
var config = await _configurationManager.GetConfigurationAsync(ct);
...
var profile = await FetchJSONWithAccessToken<dynamic>(accessToken, config.AdditionalData["profile_endpoint"] as string, ct);
This may seem complicated, but it ensures that the BankID OIDC configuration is properly cached