OAuth using OIDC Authentication with PKCE for a .NET Core Console Native Application

This article shows how to use a .NET Core console application securely with an API using the RFC 7636 specification. The app logs into IdentityServer4 using the OIDC authorization code flow with a PKCE (Proof Key for Code Exchange). The app can then use the access token to consume data from a secure API. This would be useful for power shell script clients, or .NET Core console apps. Identity.Model.Samples provide a whole range of native client examples, and this code was built using the .NET Core native code example.

Code: https://github.com/damienbod/AspNetCoreWindowsAuth


2020-08-23 Updated to .NET Core 3.1, IdentityServer4 V4
2019-09-12 Updated to .NET Core 3.0
2018-05-15 Updated title because it is confusing, OAuth Authentication replaced with OAuth using OIDC Authentication

Native App PKCE Authorization Code Flow

The RFC 7636 specification provides a safe way in which native applications can get access tokens to use with secure applications. Native applications have similar problems to web applications, single sign on is required sometimes, the native apps may not handle passwords, the server requires a way of validating the identity, and the client app requires a way of validating the token and so on.

The RFC 7636 provides one of the best ways of doing this and by using a RFC standard, tested libraries which implement this, can be used. There is no need to re-invent the wheel.

Flow overview src: 1.1. Protocol Flow

The Proof Key for Code Exchange by OAuth Public Clients was designed so that the code cannot be intercepted in the Authorization Code Flow and used to get an access token. This can help for example, when the code is leaked to shared logs on a mobile device and a malicious application uses this to get an access token.

The extra protection is added on this flow by using a code_verifier, code_challenge and a code_challenge_method. The code_challenge and the code_challenge_method are sent to the server with the authorization request. The code_challenge is the derived version of the code_verifier. When requesting the access token, the code_verifier is sent to the server, and this is then validated on the OIDC server using the values sent in the orignal authorization request.

STS Server Configuration

On IdentityServer4 ,the Proof Key for Code Exchange by OAuth can be configured as follows:

new Client
	ClientId = "native.code",
	ClientName = "Native Client (Code with PKCE)",

	RedirectUris = { "" },
	PostLogoutRedirectUris = { "" },

	RequireClientSecret = false,

	AllowedGrantTypes = GrantTypes.Code,
	RequirePkce = true,
	AllowedScopes = { "openid", "profile", "email", "native_api" },

	AllowOfflineAccess = true,
	RefreshTokenUsage = TokenUsage.ReUse

The RequirePkce is set to true, and no secrets are used, unlike the Authorization Code flow for web applications, as it makes no sense on public mobile native devices. Depending on the native device, the RedirectUris can be configured as required.

Native client using .NET Core

Implementing the client for a .NET Core application is really easy thanks to the IdentityModel.OidcClient nuget package and the examples provided on github. This repo provides reference examples for lots of different native client types, really impressive.

This example was built used the following project: .NET Core Native Code

IdentityModel.OidcClient takes care of the PKCE handling and the flow.

The login can be implemented as follows:

private static async Task Login()
	var browser = new SystemBrowser(45656);
	string redirectUri = "";

	var options = new OidcClientOptions
		Authority = _authority,
		ClientId = "native.code",
		RedirectUri = redirectUri,
		Scope = "openid profile native_api",
		FilterClaims = false,
		Browser = browser,
		Flow = OidcClientOptions.AuthenticationFlow.AuthorizationCode,
		ResponseMode = OidcClientOptions.AuthorizeResponseMode.Redirect,
		LoadProfile = true

	_oidcClient = new OidcClient(options); 
	 var result = await _oidcClient.LoginAsync(new LoginRequest());

The SystemBrowser class uses this implementation from the IdentityModel.OidcClient samples. The results can be displayed as follows:

private static void ShowResult(LoginResult result)
	if (result.IsError)
		Console.WriteLine("\n\nError:\n{0}", result.Error);

	foreach (var claim in result.User.Claims)
		Console.WriteLine("{0}: {1}", claim.Type, claim.Value);

	Console.WriteLine($"\nidentity token: {result.IdentityToken}");
	Console.WriteLine($"access token:   {result.AccessToken}");
	Console.WriteLine($"refresh token:  {result?.RefreshToken ?? "none"}");

And the API can be called then using the access token.

private static async Task CallApi(string currentAccessToken)
	var response = await _apiClient.GetAsync("");

	if (response.IsSuccessStatusCode)
		var json = JArray.Parse(await response.Content.ReadAsStringAsync());
		Console.WriteLine($"Error: {response.ReasonPhrase}");

The IdentityModel.OidcClient can be used to implement almost any native device which needs to or should implement the Proof Key for Code Exchange by OAuth for authorization. There is no need to do the password handling in your native application.


Enhancing OAuth Security for Mobile Applications with PKCE






OAuth 2.0 and PKCE





  1. […] OAuth Authentication with PKCE for a .NET Core Console Native Application – Damien Bowden […]

  2. […] L’authentification OAuth avec PKCE pour une application .NET Core console. […]

  3. Vinay · · Reply

    Hello Sir,

    Really nice article but I am facing one issue. Please help me out

    Sorry, there was an error : invalid_request
    code challenge required

    I am using Authorization code flow and getting above mentioned error.

    Detailed Steps

    1. I created a asp.net core web api and having swagger UI page.

    2. At Swagger Page, there is a authorize button and when click on it then I redirected to IdentityServer

    3. Identity server raised above mentioned error.

    My Identity server is hosted on port 5000 and client (asp.net core web api) is hosted on 5001 port


    Following the Git Url where I posted my code. https://github.com/vinaylunawat/IdentityServer4.git

  4. In OidcClientOptions, you’ve set LoadProfile=true. What does that do? It was not in the console app example IdentityModel.OidcClient.Samples repo.

  5. Jorge Santos · · Reply

    This articles was very helpful, thanks!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: