Obtaining a Token in a .NET Console App using the Client-Credentials Grant
This guide provides a step-by-step explanation of how to implement token-based authentication and authorization in a .NET Console Application using Entrypage.io as your identity provider.
Prerequisites:
- Entrypage-account
- .NET SDK
Obtaining a token in a console application depends on its ability to securely store a secret. Console apps can serve different purposes; for example, one might run as a background job, while another could be a widely distributed tool. Depending on the scenario, a console application is considered either a public or a confidential client.
- When a console application is distributed to a number of people on untrusted devices, it should be considered a public client. In this case, it should use the Authorization Code Grant with
Proof Key for Code Exchange (PKCE)
. - When a console application runs in the background, it is considered a confidential client and should use the
Client-Credentials Grant
.
Implementing the Client-Credentials Grant
To authenticate as a confidential client, you obtain a token using the Client-Credentials Grant
. This involves posting the client_id and client_secret to the /token
endpoint.
To obtain a token, the request must contain:
- A Basic Auth header, which is a Base64-encoded client_id:client_secret pair.
- A request body that includes the requested scope, with a minimum of ‘openid’.
It’s important to understand that when a token is obtained through the Client-Credentials Flow
, the token does not represent a user but a client (typically a machine). As such, the subject identifier is the client ID, never a user ID.
1. Configure the Authorization Server
To set up your authorization server with Entrypage.io, follow these steps:
- Go to portal.entrypage.io and sign in to your account.
- Navigate to the
Clients
tab and create a new client. - Configure the client with
Client-Credentials
enabled. - Configure the client with a Client Secret.
- Set the
client_id
toconsole-app
.
Once this is complete, you are ready to configure your application.
2. Create a New Console Application
While it is possible to obtain a token through executing a web-request, is is best practice to use a library to obtain the token for you and create the request correctly, hence, creating the console application project consists of the foollowing steps:
dotnet new console
dotnet add package Duende.IdentityModel.OidcClient
3. Obtain The Discovery Document (Optional)
A token is obtained from the token endpoint. The location of this endpoint is documented in the server’s /well-known/openid-configuration
file, also known as the discovery document.
The URL for the token endpoint rarely changes. The best practice, or “royal way,” to get the token endpoint’s address is by first obtaining the discovery document. However, it’s not uncommon for developers to use the token endpoint’s address directly if they already know it.
You can obtain the discovery document by executing the following C# code:
var discoveryDocument = await httpClient.GetDiscoveryDocumentAsync(authority);
4. Request the Token
While you could execute the request using the HttpClient
class, this is considered a bad practice. Instead, you should use a common, trusted library such as Duende.IdentityModel.OidcClient
to handle the request for you.
The library’s HttpClient
extension provides a simplified method for making the request:
var token = await httpClient.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest()
{
Address = discoveryDocument.TokenEndpoint,
ClientId = clientId,
ClientSecret = clientSecret,
Scope = "openid"
});
Validating the signature
To validate a JSON Web Token’s (JWT) authenticity, an application must verify its signature. This ensures the token hasn’t been tampered with and was issued by a trusted party.
However, in this specific scenario, the console application acts as a client that receives a token and then forwards it to a resource server to access a resource. In this standard OAuth 2.0/OpenID Connect flow, the resource server is the entity responsible for validating the token’s authenticity. The console app, acting as a client, simply presents the token; it doesn’t need to validate its signature.
Demo
Find a complete example of how to implement the client-credentials grant in a .NET Console application on GitHub.