Giter VIP home page Giter VIP logo

auth0net.dependencyinjection's Introduction

Auth0.NET Dependency Injection Extensions

NuGet Nuget

Integrating Auth0.NET into your project whilst following idiomatic .NET conventions can be cumbersome and involve a sizable amount of boilerplate shared between projects.

This library hopes to solve that problem, featuring:

✅ Extensions for Microsoft.Extensions.DependencyInjection.

✅ Automatic access token caching & renewal for the Management API and your own REST & Grpc services

HttpClientFactory integration for centralized extensibility and management of the internal HTTP handlers.

IHttpClientBuilder extensions, providing handlers to automatically append access tokens to outgoing requests.

This library is compatible with all .NET Standard 2.0 runtimes (.NET 6+ recommended) and is suitable for use in ASP.NET Core and standalone .NET Generic Host applications.

Install

Add Auth0Net.DependencyInjection to your project:

Install-Package Auth0Net.DependencyInjection

Scenarios

Authentication Client Only

Auth0Authentication

If you're simply using the AuthenticationApiClient and nothing else, you can call AddAuth0AuthenticationClientCore and pass in your Auth0 Domain. This integration is lightweight and does not support any other features of this library.

services.AddAuth0AuthenticationClientCore("your-auth0-domain.auth0.com");

You can then request the IAuthenticationApiClient within your class:

public class AuthController : ControllerBase
{
    private readonly IAuthenticationApiClient _authenticationApiClient;

    public AuthController(IAuthenticationApiClient authenticationApiClient)
    {
        _authenticationApiClient = authenticationApiClient;
    }

Authentication Client + Management Client

Auth0AuthenticationAndManagement

Add the AuthenticationApiClient with AddAuth0AuthenticationClient, and provide a machine-to-machine application configuration that will be consumed by the Management Client, Token Cache and IHttpClientBuilder integrations. This extension must be called before using any other extensions within this library:

services.AddAuth0AuthenticationClient(config =>
{
   config.Domain = builder.Configuration["Auth0:Domain"];
   config.ClientId = builder.Configuration["Auth0:ClientId"];
   config.ClientSecret = builder.Configuration["Auth0:ClientSecret"];
});

Add the ManagementApiClient with AddAuth0ManagementClient() and add the DelegatingHandler with AddManagementAccessToken() that will attach the Access Token automatically:

services.AddAuth0ManagementClient().AddManagementAccessToken();

Ensure your Machine-to-Machine application is authorized to request tokens from the Managment API and it has the correct scopes for the features you wish to use.

You can then request the IManagementApiClient (or IAuthenticationApiClient) within your services:

public class MyAuth0Service : IAuth0Service
{
    private readonly IManagementApiClient _managementApiClient;

    public MyAuth0Service(IManagementApiClient managementApiClient)
    {
        _managementApiClient = managementApiClient;
    }

Handling Custom Domains

If you're using a custom domain with your Auth0 tenant, you may run into a problem whereby the audience of the Management API is being incorrectly set. You can override this via the Audience property:

services.AddAuth0ManagementClient()
    .AddManagementAccessToken(c =>
    {
        c.Audience = "my-tenant.au.auth0.com";
    });

With HttpClient and/or Grpc Services (Machine-To-Machine tokens)

Auth0AuthenticationAll

Note: This feature relies on services.AddAuth0AuthenticationClient(config => ...) being called and configured as outlined in the previous scenario.

This library includes a delegating handler - effectively middleware for your HttpClient - that will append an access token to all outbound requests. This is useful for calling other services that are protected by Auth0. This integration requires your service implementation to use IHttpClientFactory as part of its registration. You can read more about it here

HttpClient

Use AddAccessToken along with the required audience:

services.AddHttpClient<MyHttpService>(x => x.BaseAddress = new Uri(builder.Configuration["MyHttpService:Url"]))
        .AddAccessToken(config => config.Audience = builder.Configuration["MyHttpService:Audience"]);

Grpc

This extension is compatible with any registration that returns a IHttpClientBuilder, thus it can be used with Grpc's client factory:

services.AddGrpcClient<UserService.UserServiceClient>(x => x.Address = new Uri(builder.Configuration["MyGrpcService:Url"]))
        .AddAccessToken(config => config.Audience = builder.Configuration["MyGrpcService:Audience"]);

Advanced

AddAccessToken also has an option for passing in a func that can resolve the audience at runtime. This can be useful if your expected audiences always follow a pattern, or if you rely on service discovery, such as from Steeltoe.NET:

services.AddHttpClient<MyHttpService>(x=> x.BaseAddress = new Uri("https://MyServiceName/"))
        .AddServiceDiscovery()
        .AddAccessToken(config => config.AudienceResolver = request => request.RequestUri.GetLeftPart(UriPartial.Authority));

Client Lifetimes

Both the authentication and authorization clients are registered as singletons and are suitable for injection into any other lifetime.

Samples

Both a .NET Generic Host and ASP.NET Core example are available in the samples directory.

Internal Cache

The Auth0TokenCache will cache a token for a given audience until at least 95% of the expiry time. If a request to the cache is made between 95% and 99% of expiry, the token will be refreshed in the background before expiry is reached.

An additional 1% of lifetime is removed to protect against clock drift between distributed systems.

In some situations you might want to request an access token from Auth0 manually. You can achieve this by injecting IAuth0TokenCache into a class and calling GetTokenAsync with the audience of the API you're requesting the token for.

An in-memory-only instance of FusionCache is used as the caching implementation. This instance is named and will not impact other usages of FusionCache.

Utility

This library exposes a simple string extension, ToHttpsUrl(), that can be used to format the naked Auth0 domain sitting in your configuration into a proper URL.

This is identical to https://{Configuration["Auth0:Domain"]}/ that you usually end up writing somewhere in your Startup.cs.

For example, formatting the domain for the JWT Authority:

.AddJwtBearer(options =>
             {
                 // "my-tenant.auth0.com" -> "https://my-tenant.auth0.com/"
                 options.Authority = builder.Configuration["Auth0:Domain"].ToHttpsUrl();
                 //...
             });

Disclaimer

I am not affiliated with nor represent Auth0. All implementation issues regarding the underlying ManagementApiClient and AuthenticationApiClient should go to the official Auth0.NET Respository.

License notices

Icons used under the MIT License from the Identicons pack.

auth0net.dependencyinjection's People

Contributors

hawxy avatar stevenvolckaert avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

stevenvolckaert

auth0net.dependencyinjection's Issues

Add IServiceProvider as an input to AddAuth0AuthenticationClient

It would be nice to have IServiceProvider available to fetch other services for populating configuration.

services.AddAuth0AuthenticationClient((config, provider) => {
    var configuration = provider.GetRequiredService<IConfiguration>();

    config.Domain = configuration["AUTH0_DOMAIN"];
    // etc.
});

Question: Is there a way to register multiple authentication clients?

We have a Microservice that is having some issues where I have multiple services trying to call AddAuth0AuthenticationClient with different clientIds.

Is there a way for this to work? To register a specific authentication client for a specific httpclient that I am trying to use? Am I missing something in the documentation?

Example:
In my Nuget package I try to configure the authentication specifically for this service:

            services.AddAuth0AuthenticationClient(opts =>
            {
                opts.ClientId = notificationsClientOptions.ClientId;
                opts.ClientSecret = notificationsClientOptions.ClientSecret;
                opts.Domain = notificationsClientOptions.Domain;
            });
            // configure Auth0 M2M for Notifications
            services
                .AddHttpClient<INotificationsClient, NotificationsClient>()
                .AddAccessToken(c => c.Audience = notificationsClientOptions?.Audience);

In another nuget package I try to configure the service for something else:

           services.AddAuth0AuthenticationClient(opts =>
           {
               opts.ClientId = settingsOptions.ClientId;
               opts.ClientSecret = settingsOptions.ClientSecret;
               opts.Domain = settingsOptions.Domain;
           });

           // configure Auth0 M2M for settings
           services
               .AddHttpClient<ISettingsClient, SettingsClient>()
               .AddAccessToken(c => c.Audience = settingsOptions?.Audience);

Am I doing this completely wrong? How can I configure both of these clients with different client ids/secrets in the same app?

Question about AudienceDomainOverride

I'm using Auth0 api also as authorization audience. Allowing setting only domain part of audience requires to set the value twice. I need to set in config domain only for AudienceDomainOverride value and another one for audience to use in authorization handler.

It would be good to have additionally option to set full audience here. E.g Simple Audience in Auth0Confinfiguration instead of Domain Override. Just use separate values for both.

Auth0Net.DependencyInjection.3.2.0 has a dependency to Microsoft.Extensions.Caching.Memory.8.0.0 for all target frameworks

Thank you for the recent release of Auth0Net.DependencyInjection.3.2.0. I've noticed this version has a dependency to Microsoft.Extensions.Caching.Memory.8.0.0 for all target frameworks.

This forces us to update all our Microsoft.Extensions.* dependencies to 8.*, which I tried today, but the problem is that some of our applications are running on netcoreapp3.1 which cannot be migrated easily, and that the Microsoft.Extensions.*.8.* packages haven't been tested with this target framework.

The compiler is showing warnings like

Microsoft.Extensions.DependencyInjection.Abstractions 8.0.1 doesn't support netcoreapp3.1 and has not been tested with it. Consider upgrading your TargetFramework to net6.0 or later. You may also set true in the project file to ignore this warning and attempt to run in this unsupported configuration at your own risk.

If the Auth0Net.DependencyInjection target frameworks

  • netstandard2.0 and net6.0 would depend on Microsoft.Extensions.Caching.Memory.6.0.1;
  • net7.0 would depend on Microsoft.Extensions.Caching.Memory.7.0.0; and
  • net8.0 would depend on Microsoft.Extensions.Caching.Memory.8.0.0,

I think this would solve the issue?

Please let me know what you think. And I'd be happy to assist and make a pull request for this.

.NET 8

Will you be adding/can you add a net8.0 target framework?

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.