GSoft.Extensions.Http.Authentication.ClientCredentialsGrant
1.0.0
Prefix Reserved
Workleap.Extensions.Http.Authentication.ClientCredentialsGrant
See the version list below for details.
dotnet add package GSoft.Extensions.Http.Authentication.ClientCredentialsGrant --version 1.0.0
NuGet\Install-Package GSoft.Extensions.Http.Authentication.ClientCredentialsGrant -Version 1.0.0
<PackageReference Include="GSoft.Extensions.Http.Authentication.ClientCredentialsGrant" Version="1.0.0" />
paket add GSoft.Extensions.Http.Authentication.ClientCredentialsGrant --version 1.0.0
#r "nuget: GSoft.Extensions.Http.Authentication.ClientCredentialsGrant, 1.0.0"
// Install GSoft.Extensions.Http.Authentication.ClientCredentialsGrant as a Cake Addin #addin nuget:?package=GSoft.Extensions.Http.Authentication.ClientCredentialsGrant&version=1.0.0 // Install GSoft.Extensions.Http.Authentication.ClientCredentialsGrant as a Cake Tool #tool nuget:?package=GSoft.Extensions.Http.Authentication.ClientCredentialsGrant&version=1.0.0
GSoft.Authentication.ClientCredentialsGrant
Description | Download link | Build status |
---|---|---|
Client-side library for any .NET application | ||
Server-side library for ASP.NET Core web applications |
This set of two libraries enables authenticated machine-to-machine HTTP communication between a .NET application and an ASP.NET Core web application. HTTP requests are authenticated with JSON web tokens (JWT) issued by an OAuth 2.0 authorization server using the client credentials grant flow.
┌────────────────────────────────┐
┌─────────►│ OAuth 2.0 authorization server │◄──────────┐
│ └────────────────────────────────┘ │
│ │
│ get token with get signing keys │
│ client credentials grant flow │ validate
│ │ token
┌─┴───────────┐ ┌───────────────┴────────┐
│ Client .NET ├──────────────────────────►│ Protected ASP.NET Core │
│ application │ authenticated HTTP call │ service │
└─────────────┘ └────────────────────────┘
The client-side library includes:
- Automatic acquisition and lifetime management of client credentials-based access tokens.
- Optimized access token caching with two layers of cache using IMemoryCache, IDistributedCache, and data protection for encryption.
- Built-in customizable retry policy for production-grade resilient HTTP requests made to the OAuth 2.0 authorization server.
- Built as an extension for the Microsoft.Extensions.Http library.
- Support for .NET Standard 2.0.
The server-side library includes:
- JWT authentication using the Microsoft.AspNetCore.Authentication.JwtBearer library.
- Default authorization policies, but you can still create your own policies.
- Non-intrusive: default policies must be explicitly used, and the default authentication scheme can be modified.
- Support for ASP.NET Core 6.0 and later.
Requirements and Considerations:
- Your OAuth 2.0 authorization server must expose its metadata at the URL
<AUTHORITY>/.well-known/openid-configuration
, as described in RFC 8414. - The client-side application uses data protection. It is important to note that your data protection configuration should support distributed workloads if you have multiple instances of a client application. Microsoft recommends using a combination of Azure Key Vault and Azure Storage to ensure that data encrypted by an instance of a client application can be read by another instance.
Getting started
Client-side library
Install the package GSoft.Extensions.Http.Authentication.ClientCredentialsGrant in your client-side application
that needs to communicate with the protected ASP.NET Core server. Then, use one of the following methods to configure an authenticated HttpClient
:
// Method 1: directly set the options values with C# code
services.AddHttpClient("MyClient").AddClientCredentialsHandler(options =>
{
options.Authority = "<oauth2_authorization_server_base_url>";
options.ClientId = "<oauth2_client_id>";
options.ClientSecret = "<oauth2_client_secret>"; // use a secret store instead of hardcoding the value
options.Scope = "<optional_requested_scope>"; // use "Scopes" for multiple values
});
// Method 2: bind the options to a configuration section
services.AddHttpClient("MyClient").AddClientCredentialsHandler(configuration.GetRequiredSection("MyConfigSection").Bind);
// Method 3: Lazily bind the options to a configuration section
services.AddHttpClient("MyClient").AddClientCredentialsHandler();
services.AddOptions<ClientCredentialsOptions>("MyClient").BindConfiguration(configSectionPath: "MyConfigSection");
// appsettings.json:
{
"MyConfigSection": {
"Authority": "<oauth2_authorization_server_base_url>",
"ClientId": "<oauth2_client_id>",
"ClientSecret": "<oauth2_client_secret>", // use a secret configuration provider instead of hardcoding the value
"Scope": "<optional_requested_scope>", // use "Scopes" for multiple values
}
}
// You can also use the generic HttpClient registration with any of these methods:
services.AddHttpClient<MyClient>().AddClientCredentialsHandler( /* [...] */);
Then, instantiate the HttpClient
later on using IHttpClientFactory
or directly inject it in the constructor if you used the generic registration:
public class MyClient
{
private readonly HttpClient _httpClient;
public MyClient(IHttpClientFactory httpClientFactory)
{
this._httpClient = httpClientFactory.CreateClient("MyClient");
}
public async Task DoSomeAuthenticatedHttpCallAsync()
{
await this._httpClient.GetStringAsync("https://myservice");
}
}
This client-side library is based on Duende.AccessTokenManagement, Copyright (c) Brock Allen & Dominick Baier, licensed under the Apache License, Version 2.0.
Server-side library
Install the package GSoft.AspNetCore.Authentication.ClientCredentialsGrant in your server-side ASP.NET Core application and register the authentication services:
// Registers Microsoft's JwtBearer handler with a default "ClientCredentials" authentication scheme.
// This authentication scheme can be changed using other methods overloads.
builder.Services.AddAuthentication().AddClientCredentials();
This will automatically bind the configuration section Authentication:Schemes:ClientCredentials
(unless you've changed the authentication scheme).
For instance, the example above works well with this appsettings.json
:
{
"Authentication": {
"Schemes": {
"ClientCredentials": {
"Authority": "<oauth2_authorization_server_base_url>",
"Audience": "<audience>"
}
}
}
}
Next, register the authorization services:
builder.Services.AddAuthorization(options =>
{
// Change the scheme here if you registered a custom scheme in the authentication services.
// You can also add requirements to your policy, such as '.RequireClaim("name", "value", ["values"])'.
options.AddPolicy("my-policy", x => x.AddAuthenticationSchemes(ClientCredentialsDefaults.AuthenticationScheme).RequireAuthenticatedUser());
});
Finally, register the authentication and authorization middlewares in your ASP.NET Core app and decorate your endpoints with the AuthorizeAttribute
:
var app = builder.Build();
// [...]
app.UseAuthentication();
app.UseAuthorization();
// Minimal APIs
app.MapGet("/hello-world", () => "Hello World!").RequireAuthorization("my-policy");
// Controller-style
[Authorize("my-policy")]
[HttpGet("hello-world")]
public IActionResult HelloWorld() => this.Ok("Hello world");
Building, releasing and versioning
The project can be built by running Build.ps1
. It uses Microsoft.CodeAnalysis.PublicApiAnalyzers to help detect public API breaking changes. Use the built-in roslyn analyzer to ensure that public APIs are declared in PublicAPI.Shipped.txt
, and obsolete public APIs in PublicAPI.Unshipped.txt
.
A new preview NuGet package is automatically published on any new commit on the main branch. This means that by completing a pull request, you automatically get a new NuGet package.
When you are ready to officially release a stable NuGet package by following the SemVer guidelines, simply manually create a tag with the format x.y.z
. This will automatically create and publish a NuGet package for this version.
License
Copyright © 2023, GSoft Group Inc. This code is licensed under the Apache License, Version 2.0. You may obtain a copy of this license at https://github.com/gsoft-inc/gsoft-license/blob/master/LICENSE.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- IdentityModel (>= 6.1.0)
- Microsoft.AspNetCore.DataProtection.Abstractions (>= 6.0.0)
- Microsoft.Extensions.Caching.Memory (>= 6.0.0)
- Microsoft.Extensions.Http (>= 6.0.0)
- Microsoft.Extensions.Http.Polly (>= 6.0.0)
- Microsoft.Extensions.Options (>= 6.0.0)
- Polly.Contrib.WaitAndRetry (>= 1.1.1)
- System.Text.Json (>= 6.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.