Authorization code flow (Basic)
This guide is designed to get you started with your integration for end-user authentication. The guide is written for .NET using C# and covers the basics of setting up an authorization code flow.
Learn more about OIDC grant types in the OIDC implementation documentation.
How it works
In an authorization code flow:
- The client application redirects the user to the authorisation server, where the user logs in and provides consent.
- After successful authentication, the authorisation server redirects the user back to the client application with an authorization code.
- The client application then exchanges this code for an access token and a refresh token by making a direct request to the authorization server's token endpoint.

OpenID Connect flow diagram
The Authorization code flow is primarily designed for web applications and requires user interaction during the entire authentication process.
Prerequisites
If you do not have an account already, then you need to sign up to the Signicat Dashboard for free and complete the initial preparations. To do this:
- Sign up to the Signicat Dashboard and register your profile.
- Ensure that you have created an organisation.
- Create an account. To do this:
- Go to Signicat Dashboard > Organisation, then select + Add account.
- Enter an account name, choose the type of account that you want to create, then select Create.
- Create a domain. To do this:
- Go to Signicat Dashboard > Settings > Domain management, then select + Add domain.
- To create a standard domain, enter a domain name. Then, select Add domain.
- To create a custom domain, follow the instructions in the Custom domains documentation.
We recommend that you create a sandbox account to test our services before going live. Sandbox and production accounts must be set up separately.
This guide assumes you already have installed and properly configured the following in your local machine:
- .NET Core SDK.
- A code editor, such as Visual Studio Code, Visual Studio or Rider.
- A command-line interface, such as PowerShell. All commands in this guide were tested with PowerShell.
Additionally, we strongly recommend you use a library or framework for the implementation, such as the ones provided by JWT.
Create an OIDC client
Make sure your OIDC client has been properly created and configured. To do this in the Signicat Dashboard, navigate to Products > eID and Wallet Hub > OIDC clients. You can find the required client settings below.
Client settings on the Dashboard
- Information
- Name: filled
- URI: empty
- Logo URI: empty
- URIs
- Redirect URI: filled with 1 (one) URI
- For example: https://localhost:5001/account/callback
- Post logout redirect URI: empty
- Front channel logout URI: empty
- Front channel logout session required: false
- Redirect URI: filled with 1 (one) URI
- Security
- Primary grant type: Authorisation code
- Require secret: true
- Require PKCE: true
- Allow access token via browser: false
- User reference access tokens: false
- Allowed CORS origins: empty
- Encrypt ID tokens: false
- User info response type: empty (or default)
- Content encryption algorithm: empty (or default)
- Accesses
- Allowed scopes: filled with, at least,
openidandprofile - Identity provider restrictions: empty
- Allowed scopes: filled with, at least,
- Lifetimes
- All fields with default values
After saving your client, you must generate a new secret.
Tutorial steps
1. Initialise your project
Start your solution:
mkdir SignicatQuickStartGuide
cd .\SignicatQuickStartGuide\
dotnet new sln
Add an empty web project:
dotnet new web --name AuthorizationCodeFlowGuide
dotnet sln .\SignicatQuickStartGuide.sln add .\AuthorizationCodeFlowGuide\
2. Install dependencies
Add support to OpenID Connect authentication workflow by including the following package in your project:
dotnet add .\AuthorizationCodeFlowGuide\ package Microsoft.AspNetCore.Authentication.OpenIdConnect --version 3.1.7
3. Startup settings
Under the Startup class, do the following.
Set using statements:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
Create an asynchronous method to redeem the authorisation code for tokens at token endpoint:
protected virtual async Task RedeemAuthorizationCodeAsync(AuthorizationCodeReceivedContext context)
{
var configuration = await context.Options.ConfigurationManager.GetConfigurationAsync(CancellationToken.None);
var requestMessage = new HttpRequestMessage(HttpMethod.Post, configuration.TokenEndpoint);
var authInfo = $"{context.TokenEndpointRequest.ClientId}:{context.TokenEndpointRequest.ClientSecret}";
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic", authInfo);
var tokenEndpointRequest = context.TokenEndpointRequest.Clone();
tokenEndpointRequest.ClientSecret = null;
requestMessage.Content = new FormUrlEncodedContent(tokenEndpointRequest.Parameters);
var responseMessage = await context.Backchannel.SendAsync(requestMessage);
if (!responseMessage.IsSuccessStatusCode)
{
Console.WriteLine(await responseMessage.Content.ReadAsStringAsync());
return;
}
try
{
var responseContent = await responseMessage.Content.ReadAsStringAsync();
var message = new OpenIdConnectMessage(responseContent);
context.HandleCodeRedemption(message);
}
catch (Exception exc)
{
Console.WriteLine($"An error occurred: {exc.Message}");
}
}
Register authentication and controller with views services in the ConfigureServices method:
Your value for config.Authority will vary depending on your configuration.
- If you haven't configured a custom domain: in the code sample below, replace
chosen-namewith the name you have chosen for your account. - If you have configured your own custom domain, change the value of
config.Authoritytohttps://your.domain.com/auth/open.
public void ConfigureServices(IServiceCollection services)
{
// omitted for brevity
services.AddAuthentication(config =>
{
config.DefaultAuthenticateScheme = "AuthorizationCodeClientAppCookie";
config.DefaultSignInScheme = "AuthorizationCodeClientAppCookie";
config.DefaultChallengeScheme = "Signicat";
})
.AddCookie("AuthorizationCodeClientAppCookie")
.AddOpenIdConnect("Signicat", config =>
{
config.Events.OnAuthorizationCodeReceived = RedeemAuthorizationCodeAsync;
config.Authority = "https://chosen-name.app.signicat.dev/auth/open";
config.ClientId = "YOUR_CLIENT_ID_HERE";
config.ClientSecret = "YOUR_CLIENT_SECRET_HERE";
config.CallbackPath = "/account/callback";
config.UsePkce = true;
config.ResponseType = "code";
config.Scope.Add("openid");
config.Scope.Add("profile");
config.GetClaimsFromUserInfoEndpoint = true;
config.SaveTokens = true;
});
services.AddControllersWithViews();
// omitted for brevity
}
Add authentication and authorisation middlewares to the pipeline and change endpoint mappings to default in the Configure method:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// omitted for brevity
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
// omitted for brevity
}
4. Protected resource
To check if everything is working as expected, create a basic controller (HomeController) with an Index action and a simple View to it.
The folder and file structure could be similar to this:
.
├─ SignicatQuickStartGuide.sln
├─ AuthorizationCodeFlowGuide
│ ├─ AuthorizationCodeFlowGuide.csproj
│ ├─ Controllers
│ │ └─ HomeController.cs
│ └─ Views
│ │ └─ Home
│ │ └─ Index.cshtml
│ └─ ...
└─ ...
Other folders and files omitted for brevity.
Your Home controller could be similar to:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace AuthorizationCodeFlowGuide.Controllers
{
public class HomeController : Controller
{
[Authorize]
public IActionResult Index()
{
return View();
}
}
}
Your Index view could be similar to:
<h1>Index</h1>
<p>This is a protected resource! Only visible after authentication.</p>
5. Run
Execute your project:
dotnet run --project .\AuthorizationCodeFlowGuide\
Open https://localhost:5001/ in a browser.
We strongly recommend using HTTPS.
Change your port number, if necessary. It's the same host you set on your client's redirect URI.
6. Test end-user
Choose Norwegian BankID and sign with a test user as follows: