Skip to content

Commit

Permalink
v1.6.0 (#9)
Browse files Browse the repository at this point in the history
* Better support custom domain scenarios

* Update README.md

* Update main.yml

* Adjust settings

* Add xml comments

* Don't register management token settings globally

* Further remove dependencies within implementation
  • Loading branch information
Hawxy authored Feb 22, 2022
1 parent fef20e3 commit e178392
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 33 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: Setup .NET 6
uses: actions/setup-dotnet@v1
with:
dotnet-version: '6.0.x'

- name: Setup .NET 5
uses: actions/setup-dotnet@v1
with:
Expand Down
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ This library hopes to solve that problem, featuring:

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

This library supports .NET Core 3.1 & .NET 5, and is suitable for use in ASP.NET Core and standalone .NET Generic Host applications.
This library supports .NET Core 3.1, .NET 5 & .NET 6, and is suitable for use in ASP.NET Core and standalone .NET Generic Host applications.

## Install

Expand Down Expand Up @@ -91,6 +91,19 @@ public class MyAuth0Service : IAuth0Service
_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 following:

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

### With HttpClient and/or Grpc Services

Expand Down Expand Up @@ -127,6 +140,8 @@ services.AddHttpClient<MyHttpService>(x=> x.BaseAddress = new Uri("https://MySer
.AddAccessToken(config => config.AudienceResolver = request => request.RequestUri.GetLeftPart(UriPartial.Authority));
```



### Samples

Both a .NET Generic Host and ASP.NET Core example are available in the [samples](https://github.com/Hawxy/Auth0Net.DependencyInjection/tree/main/samples) directory.
Expand Down
3 changes: 0 additions & 3 deletions samples/Sample.AspNetCore/Program.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
using System.Net;
using System.Security.Authentication;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace Sample.AspNetCore
{
Expand Down
8 changes: 4 additions & 4 deletions samples/Sample.AspNetCore/Sample.AspNetCore.csproj
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<UserSecretsId>ed89c14f-ea75-4b37-83e7-078870067ffc</UserSecretsId>
<nullable>enable</nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.39.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.9" />
<PackageReference Include="System.Text.Encodings.Web" Version="5.0.1" />
<PackageReference Include="Grpc.AspNetCore" Version="2.42.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.2" />
<PackageReference Include="System.Text.Encodings.Web" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion samples/Sample.ConsoleApp/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Threading.Tasks;
using Auth0Net.DependencyInjection.HttpClient;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
Expand Down
12 changes: 6 additions & 6 deletions samples/Sample.ConsoleApp/Sample.ConsoleApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<nullable>enable</nullable>
<UserSecretsId>096fd757-814d-4d2a-a02e-ef4f19cdc656</UserSecretsId>
</PropertyGroup>
Expand All @@ -20,14 +20,14 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.17.3" />
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.39.0" />
<PackageReference Include="Grpc.Tools" Version="2.39.1">
<PackageReference Include="Google.Protobuf" Version="3.19.4" />
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.42.0" />
<PackageReference Include="Grpc.Tools" Version="2.44.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down
14 changes: 11 additions & 3 deletions src/Auth0Net.DependencyInjection/Auth0Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Auth0Net.DependencyInjection.HttpClient;
using Auth0Net.DependencyInjection.Injectables;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;

// ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection
Expand Down Expand Up @@ -65,6 +66,7 @@ public static IHttpClientBuilder AddAuth0AuthenticationClient(this IServiceColle
services.AddScoped<IAuthenticationApiClient, InjectableAuthenticationApiClient>();
return services.AddHttpClient<IAuthenticationConnection, HttpClientAuthenticationConnection>();
}

/// <summary>
/// Adds a <see cref="ManagementApiClient" /> integrated with <see cref="IHttpClientBuilder" /> to the <see cref="IServiceCollection" />.
/// </summary>
Expand Down Expand Up @@ -106,11 +108,17 @@ public static IHttpClientBuilder AddAccessToken(this IHttpClientBuilder builder,
/// The domain used to resolve the token is the same as set in <see cref="AddAuth0AuthenticationClient"/>.
/// </remarks>
/// <param name="builder">The <see cref="IHttpClientBuilder"/> you wish to configure.</param>
/// <param name="config">Additional configuration for the management client.</param>
/// <returns>An <see cref="IHttpClientBuilder" /> that can be used to configure the <see cref="HttpClient"/>.</returns>
public static IHttpClientBuilder AddManagementAccessToken(this IHttpClientBuilder builder)
public static IHttpClientBuilder AddManagementAccessToken(this IHttpClientBuilder builder, Action<Auth0ManagementTokenConfiguration>? config = null)
{
builder.Services.TryAddTransient<Auth0ManagementTokenHandler>();
return builder.AddHttpMessageHandler<Auth0ManagementTokenHandler>();
var c = new Auth0ManagementTokenConfiguration();
config?.Invoke(c);

return builder.AddHttpMessageHandler(p =>
new Auth0ManagementTokenHandler(
p.GetRequiredService<IAuth0TokenCache>(),
p.GetRequiredService<IOptionsSnapshot<Auth0Configuration>>(), c));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.1;net5.0</TargetFrameworks>
<TargetFrameworks>netstandard2.1;net5.0;net6.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Nullable>enable</Nullable>
<Version>1.5.0</Version>
<Version>1.6.0</Version>
<Authors>Hawxy</Authors>
<Description>Dependency Injection, HttpClientFactory &amp; ASP.NET Core extensions for Auth0.NET</Description>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
Expand All @@ -18,10 +18,10 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Auth0.AuthenticationApi" Version="7.9.0" />
<PackageReference Include="Auth0.ManagementApi" Version="7.9.0" />
<PackageReference Include="LazyCache.AspNetCore" Version="2.1.3" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="Auth0.AuthenticationApi" Version="7.14.0" />
<PackageReference Include="Auth0.ManagementApi" Version="7.14.0" />
<PackageReference Include="LazyCache.AspNetCore" Version="2.4.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' ">
Expand All @@ -36,6 +36,13 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net6.0' ">
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
</ItemGroup>


<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>$(MSBuildProjectName).Tests</_Parameter1>
Expand Down
15 changes: 14 additions & 1 deletion src/Auth0Net.DependencyInjection/Cache/Auth0Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Auth0Net.DependencyInjection.Cache
public class Auth0Configuration
{
/// <summary>
/// The root domain for your Auth0 tenant.
/// The default or custom root domain for your Auth0 tenant.
/// </summary>
public string Domain { get; set; } = null!;
/// <summary>
Expand All @@ -23,5 +23,18 @@ public class Auth0Configuration
/// The time before access token expiry that the token should be renewed. The default is 30 minutes.
/// </summary>
public TimeSpan TokenExpiryBuffer { get; set; } = TimeSpan.FromMinutes(30);

}

/// <summary>
/// Configuration for the Auth0 Management API.
/// </summary>
public class Auth0ManagementTokenConfiguration
{
/// <summary>
/// This option will replace the use of <see cref="Auth0Configuration.Domain"/> to compute the audience for the Management API token.
/// Useful when using custom domains.
/// </summary>
public string? AudienceDomainOverride { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage

internal class Auth0ManagementTokenHandler : Auth0TokenHandler
{
public Auth0ManagementTokenHandler(IAuth0TokenCache cache, IOptionsSnapshot<Auth0Configuration> options)
: base(cache, new Auth0TokenHandlerConfig(UriHelpers.GetValidManagementUri(options.Value.Domain).ToString()))
public Auth0ManagementTokenHandler(IAuth0TokenCache cache, IOptionsSnapshot<Auth0Configuration> options, Auth0ManagementTokenConfiguration clientConfig)
: base(cache, new Auth0TokenHandlerConfig(UriHelpers.GetValidManagementUri(clientConfig.AudienceDomainOverride ?? options.Value.Domain).ToString()))
{
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net5.0;netcoreapp3.1</TargetFrameworks>
<TargetFrameworks>netcoreapp3.1;net5.0;net6.0</TargetFrameworks>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FakeItEasy" Version="7.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.0">
<PackageReference Include="coverlet.collector" Version="3.1.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
44 changes: 41 additions & 3 deletions tests/Auth0Net.DependencyInjection.Tests/ExtensionTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System;
using System.Linq;
using System.Reflection;
using Auth0.AuthenticationApi;
using Auth0.ManagementApi;
using Auth0Net.DependencyInjection.Cache;
using Auth0Net.DependencyInjection.HttpClient;
using Auth0Net.DependencyInjection.Injectables;
using LazyCache;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -40,12 +43,12 @@ public void AddAuth0AuthenticationClientCore_Resolves_AuthenticationClient()

var services = new ServiceCollection().AddAuth0AuthenticationClientCore(domain).Services;

var serviceDescriptor = services.FirstOrDefault(x => x.ServiceType == typeof(IAuthenticationApiClient)
var serviceDescriptor = services.FirstOrDefault(x => x.ServiceType == typeof(IAuthenticationApiClient)
&& x.ImplementationType == typeof(InjectableAuthenticationApiClient));

Assert.NotNull(serviceDescriptor);
Assert.Equal(ServiceLifetime.Scoped, ServiceLifetime.Scoped);

var provider = services.BuildServiceProvider();

var authenticationClient = provider.GetService<IAuthenticationApiClient>();
Expand Down Expand Up @@ -83,7 +86,7 @@ public void AddAuth0AuthenticationClient_Throws_InvalidConfiguration()
x.ClientSecret = "";
}).Services.BuildServiceProvider();

Assert.Throws<OptionsValidationException>(() => services.GetRequiredService<IAuthenticationApiClient>());
Assert.Throws<OptionsValidationException>(() => services.GetRequiredService<IAuthenticationApiClient>());
}

[Fact]
Expand Down Expand Up @@ -137,6 +140,41 @@ public void AddAccessToken_Rejects_InvalidConfig()
new ServiceCollection().AddHttpClient<DummyClass>(x => { }).AddAccessToken(x => { }));
}

[Fact]
public void AddManagementClient_Can_BeResolved()
{
var customDomain = "custom-domain.com";
var clientId = "fake-id";
var clientSecret = "fake-secret";
var renewal = TimeSpan.FromMinutes(60);

var collection = new ServiceCollection();

collection.AddAuth0AuthenticationClient(x =>
{
x.Domain = customDomain;
x.ClientId = clientId;
x.ClientSecret = clientSecret;
x.TokenExpiryBuffer = renewal;
});

var defaultDomain = "tenant.au.auth0.com";

collection.AddAuth0ManagementClient()
.AddManagementAccessToken(c =>
{
c.AudienceDomainOverride = defaultDomain;
});

collection.AddHttpClient<DummyClass>().AddManagementAccessToken();

var services = collection.BuildServiceProvider();

var client = services.GetService<ManagementApiClient>();

Assert.NotNull(client);
}

}

public class DummyClass
Expand Down

0 comments on commit e178392

Please sign in to comment.