stasnocap.OpenIddict.AccessTokenManagement.ClientAccess 1.0.0

dotnet add package stasnocap.OpenIddict.AccessTokenManagement.ClientAccess --version 1.0.0
NuGet\Install-Package stasnocap.OpenIddict.AccessTokenManagement.ClientAccess -Version 1.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="stasnocap.OpenIddict.AccessTokenManagement.ClientAccess" Version="1.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add stasnocap.OpenIddict.AccessTokenManagement.ClientAccess --version 1.0.0
#r "nuget: stasnocap.OpenIddict.AccessTokenManagement.ClientAccess, 1.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install stasnocap.OpenIddict.AccessTokenManagement.ClientAccess as a Cake Addin
#addin nuget:?package=stasnocap.OpenIddict.AccessTokenManagement.ClientAccess&version=1.0.0

// Install stasnocap.OpenIddict.AccessTokenManagement.ClientAccess as a Cake Tool
#tool nuget:?package=stasnocap.OpenIddict.AccessTokenManagement.ClientAccess&version=1.0.0

openiddict-access-token-management

Automatic token management for machine to machine and user-centric web app OAuth and OIDC flows

The project is highly inspired by Duende.AccessTokenManagement (refactored to work with OpenIddictClientService)

Client credentials

Setup

services.AddOpenIddict()

    // Register the OpenIddict client components.
    .AddClient(options =>
    {
        // Allow grant_type=client_credentials to be negotiated.
        options.AllowClientCredentialsFlow();

        // Disable token storage, which is not necessary for non-interactive flows like
        // grant_type=password, grant_type=client_credentials or grant_type=refresh_token.
        options.DisableTokenStorage();

        // Register the System.Net.Http integration and use the identity of the current
        // assembly as a more specific user agent, which can be useful when dealing with
        // providers that use the user agent as a way to throttle requests (e.g Reddit).
        options.UseSystemNetHttp()
               .SetProductInformation(typeof(Program).Assembly);

        // Add a client registration matching the client application definition in the server project.
        options.AddRegistration(new OpenIddictClientRegistration
        {
            Issuer = new Uri("https://localhost:44385/", UriKind.Absolute),

            ClientId = "console",
            ClientSecret = "388D45FA-B36B-4988-BA59-B187D329C207"
        });
    });

// default cache
services.AddDistributedMemoryCache();

services.AddClientAccessTokenManagement(options => {
    // or leave it empty and set options.DisableAccessTokenEncryption() on server
    options.EncryptionKey = "DRjd/GnduI3Efzen9V9BvbNUfc/VKgXltV7Kbk9sMkY=";
});

HTTP Client Factory

services.AddClientAccessHttpClient("invoices", "invoice.client", client =>
{
    client.BaseAddress = new Uri("https://apis.company.com/invoice/");
});
services.AddHttpClient<CatalogClient>(client =>
    {
        client.BaseAddress = new Uri("https://apis.company.com/catalog/");
    })
    .AddClientAccessTokenHandler("catalog.client");

Usage

Manual
public class WorkerManual : BackgroundService
{
    private readonly IHttpClientFactory _clientFactory;
    private readonly IClientTokenManagementService _tokenManagementService;

    public WorkerManualIHttpClientFactory factory, IClientTokenManagementService tokenManagementService)
    {
        _clientFactory = factory;
        _tokenManagementService = tokenManagementService;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {          
        while (!stoppingToken.IsCancellationRequested)
        {
            var client = _clientFactory.CreateClient();
            client.BaseAddress = new Uri("https://apis.company.com/catalog/");
            
            // get access token for client and set on HttpClient
            var token = await _tokenManagementService.GetAccessTokenAsync("catalog.client");
            client.SetBearerToken(token.Value);
            
            var response = await client.GetAsync("list", stoppingToken);
                
            // rest omitted
        }
    }
}

HTTP factory

public class WorkerHttpClient : BackgroundService
{
    private readonly ILogger<WorkerHttpClient> _logger;
    private readonly IHttpClientFactory _clientFactory;

    public WorkerHttpClient(ILogger<WorkerHttpClient> logger, IHttpClientFactory factory)
    {
        _logger = logger;
        _clientFactory = factory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var client = _clientFactory.CreateClient("invoices");
            var response = await client.GetAsync("test", stoppingToken);

            // rest omitted
        }
    }
}

User

Setup

services.AddOpenIddict()

    // Register the OpenIddict client components.
    .AddClient(options =>
    {
        // Allow grant_type=refresh_token to be negotiated.
        options.AllowRefreshTokenFlow();

        // Disable token storage, which is not necessary for non-interactive flows like
        // grant_type=password, grant_type=client_credentials or grant_type=refresh_token.
        options.DisableTokenStorage();

        // Register the System.Net.Http integration and use the identity of the current
        // assembly as a more specific user agent, which can be useful when dealing with
        // providers that use the user agent as a way to throttle requests (e.g Reddit).
        options.UseSystemNetHttp()
               .SetProductInformation(typeof(Program).Assembly);

        // Add a client registration without a client identifier/secret attached.
        options.AddRegistration(new OpenIddictClientRegistration
        {
            Issuer = new Uri("https://localhost:44382/", UriKind.Absolute)
        });
    });

// adds services for token management
builder.Services.AddUserAccessTokenManagement(options => {
    // or leave it empty and set options.DisableAccessTokenEncryption() on server
    options.EncryptionKey = "DRjd/GnduI3Efzen9V9BvbNUfc/VKgXltV7Kbk9sMkY=";
});

HTTP client factory

// registers HTTP client that uses the managed user access token
builder.Services.AddUserAccessTokenHttpClient("invoices",
    configureClient: client => { client.BaseAddress = new Uri("https://api.company.com/invoices/"); });
// registers a typed HTTP client with token management support
builder.Services.AddHttpClient<InvoiceClient>(client =>
    {
        client.BaseAddress = new Uri("https://api.company.com/invoices/");
    })
    .AddUserAccessTokenHandler();

Usage

Manually

public class HomeController : Controller
{
    private readonly IHttpClientFactory _httpClientFactory;
    private readonly IUserTokenManagementService _tokenManagementService;

    public HomeController(IHttpClientFactory httpClientFactory, IUserTokenManagementService tokenManagementService)
    {
        _httpClientFactory = httpClientFactory;
        _tokenManagementService = tokenManagementService;
    }

    public async Task<IActionResult> CallApi()
    {
        var token = await _tokenManagementService.GetAccessTokenAsync(User);
        var client = _httpClientFactory.CreateClient();
        client.SetBearerToken(token.Value);
            
        var response = await client.GetAsync("https://api.company.com/invoices");
        
        // rest omitted
    }
}

HttpContext extension method

public async Task<IActionResult> CallApi()
{
    var token = await HttpContext.GetUserAccessTokenAsync();
    var client = _httpClientFactory.CreateClient();
    client.SetBearerToken(token.Value);
        
    var response = await client.GetAsync("https://api.company.com/invoices");
    
    // rest omitted
}

HTTP client factory

public async Task<IActionResult> CallApi()
{
    var client = _httpClientFactory.CreateClient("invoices");

    var response = await client.GetAsync("list");
    
    // rest omitted
}
public async Task<IActionResult> CallApi([FromServices] InvoiceClient client)
{
    var response = await client.GetList();
    
    // rest omitted
}
services.AddUserAccessTokenManagement(options => {
    // or leave it empty and set options.DisableAccessTokenEncryption() on server
    options.UseUnauthorizedMiddleware = true;
    // redirect to login
    options.UnauthorizedRedirectOptions.RelativeUri = "/login";
    // append returnUrl to redirecti uri
    options.UnauthorizedRedirectOptions.AppendReturnUrlToQuery = true;
    // change returnUrl query name, default is 'returnUrl'
    options.UnauthorizedRedirectOptions.ReturnUrlQueryName = "myReturnUrlQueryName";
});

or same

services.AddClientAccessTokenManagement(options => ...);

Middleware

app.UseMiddleware<UnauthorizedMiddleware>();
Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on stasnocap.OpenIddict.AccessTokenManagement.ClientAccess:

Package Downloads
stasnocap.OpenIddict.AccessTokenManagement.UserAccess

Automatic token management for user-centric web app OAuth and OIDC flows

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.0 177 8/20/2023