GithubHelp home page GithubHelp logo

stasnocap / openiddict-access-token-management Goto Github PK

View Code? Open in Web Editor NEW
0.0 1.0 0.0 49 KB

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

License: Apache License 2.0

C# 100.00%

openiddict-access-token-management's Introduction

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

<ItemGroup>
    <PackageReference Include="stasnocap.OpenIddict.AccessTokenManagement.ClientAccess" Version="1.0.0" />
</ItemGroup>

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

<ItemGroup>
    <PackageReference Include="stasnocap.OpenIddict.AccessTokenManagement.UserAccess" Version="1.0.0" />
</ItemGroup>

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
}

Refresh token and cookie on the server have expired

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>();

openiddict-access-token-management's People

Contributors

stasnocap avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.