Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .fernignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ src/Directory.Build.props
src/Auth0.ManagementApi/Auth0.ManagementApi.Custom.props
src/Auth0.ManagementApi/.shiprc
src/Auth0.ManagementApi/.version
src/Auth0.ManagementApi/ManagementApiClient.Internal.cs

tests/Auth0.AuthenticationApi.IntegrationTests
tests/Auth0.Core.UnitTests
Expand Down
15 changes: 15 additions & 0 deletions src/Auth0.ManagementApi/ManagementApiClient.Internal.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Auth0.ManagementApi.Core;

namespace Auth0.ManagementApi;

public partial class ManagementApiClient
{
/// <summary>
/// Replaces the Authorization header with a dynamic supplier that is evaluated per-request.
/// Used by <see cref="ManagementClient"/> to wire in <see cref="ITokenProvider"/> support.
/// </summary>
internal void SetAuthorizationHeader(Func<Task<string>> supplier)
{
_client.Options.Headers["Authorization"] = supplier;
}
}
233 changes: 26 additions & 207 deletions src/Auth0.ManagementApi/Wrapper/ManagementClient.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
using Auth0.ManagementApi.Anomaly;
using Auth0.ManagementApi.AttackProtection;
using Auth0.ManagementApi.Core;
using Auth0.ManagementApi.Emails;
using Auth0.ManagementApi.Guardian;
using Auth0.ManagementApi.Tenants;
using Auth0.ManagementApi.VerifiableCredentials;

namespace Auth0.ManagementApi;

/// <summary>
Expand All @@ -26,9 +18,8 @@ namespace Auth0.ManagementApi;
/// });
/// </code>
/// </summary>
public sealed class ManagementClient : IManagementApiClient, IDisposable
public sealed class ManagementClient : ManagementApiClient, IDisposable
{
private readonly RawClient _client;
private readonly HttpClient _httpClient;
private readonly bool _ownsHttpClient;
private readonly ITokenProvider _tokenProvider;
Expand All @@ -40,6 +31,23 @@ public sealed class ManagementClient : IManagementApiClient, IDisposable
/// <exception cref="ArgumentNullException">Thrown when <paramref name="options"/> is null.</exception>
/// <exception cref="ArgumentException">Thrown when <see cref="ManagementClientOptions.Domain"/> is empty, whitespace, or contains a scheme prefix.</exception>
public ManagementClient(ManagementClientOptions options)
: this(Validate(options), BuildClientOptions(options))
{
}

private ManagementClient(ManagementClientOptions options, ClientOptions clientOptions)
: base(null, clientOptions)
{
_tokenProvider = options.TokenProvider;
_ownsHttpClient = options.HttpClient == null;
_httpClient = clientOptions.HttpClient;

// Replace the static "Bearer " auth header with a dynamic per-request supplier.
SetAuthorizationHeader(async () =>
$"Bearer {await _tokenProvider.GetTokenAsync(default).ConfigureAwait(false)}");
}

private static ManagementClientOptions Validate(ManagementClientOptions options)
{
if (options == null) throw new ArgumentNullException(nameof(options));

Expand All @@ -54,219 +62,30 @@ public ManagementClient(ManagementClientOptions options)
if (options.TokenProvider == null)
throw new ArgumentNullException(nameof(options), "TokenProvider must not be null.");

_tokenProvider = options.TokenProvider;

var baseUrl = $"https://{options.Domain}/api/v2";

_ownsHttpClient = options.HttpClient == null;
_httpClient = options.HttpClient ?? new HttpClient();
return options;
}

private static ClientOptions BuildClientOptions(ManagementClientOptions options)
{
var clientOptions = new ClientOptions
{
BaseUrl = baseUrl,
HttpClient = _httpClient,
BaseUrl = $"https://{options.Domain}/api/v2",
HttpClient = options.HttpClient ?? new HttpClient(),
Timeout = options.Timeout ?? TimeSpan.FromSeconds(30),
MaxRetries = options.MaxRetries ?? 2,
};

// Set up headers with dynamic token supplier
var headers = new Headers(new Dictionary<string, string>());

if (options.AdditionalHeaders != null)
{
foreach (var header in options.AdditionalHeaders)
{
headers[header.Key] = new HeaderValue(header.Value);
clientOptions.Headers[header.Key] = header.Value;
}
}

// Wire the async token supplier into the Authorization header.
// HeaderValue supports Func<Task<string>> which is evaluated per-request.
Func<Task<string>> authHeaderSupplier = async () =>
$"Bearer {await _tokenProvider.GetTokenAsync(default).ConfigureAwait(false)}";
headers["Authorization"] = authHeaderSupplier;

foreach (var header in headers)
{
clientOptions.Headers[header.Key] = header.Value;
}

_client = new RawClient(clientOptions);

Actions = new ActionsClient(_client);
Branding = new BrandingClient(_client);
ClientGrants = new ClientGrantsClient(_client);
Clients = new ClientsClient(_client);
ConnectionProfiles = new ConnectionProfilesClient(_client);
Connections = new ConnectionsClient(_client);
CustomDomains = new CustomDomainsClient(_client);
DeviceCredentials = new DeviceCredentialsClient(_client);
EmailTemplates = new EmailTemplatesClient(_client);
EventStreams = new EventStreamsClient(_client);
Flows = new FlowsClient(_client);
Forms = new FormsClient(_client);
UserGrants = new UserGrantsClient(_client);
Groups = new GroupsClient(_client);
Hooks = new HooksClient(_client);
Jobs = new JobsClient(_client);
LogStreams = new LogStreamsClient(_client);
Logs = new LogsClient(_client);
NetworkAcls = new NetworkAclsClient(_client);
Organizations = new OrganizationsClient(_client);
Prompts = new PromptsClient(_client);
RefreshTokens = new RefreshTokensClient(_client);
ResourceServers = new ResourceServersClient(_client);
Roles = new RolesClient(_client);
Rules = new RulesClient(_client);
RulesConfigs = new RulesConfigsClient(_client);
SelfServiceProfiles = new SelfServiceProfilesClient(_client);
Sessions = new SessionsClient(_client);
Stats = new StatsClient(_client);
SupplementalSignals = new SupplementalSignalsClient(_client);
Tickets = new TicketsClient(_client);
TokenExchangeProfiles = new TokenExchangeProfilesClient(_client);
UserAttributeProfiles = new UserAttributeProfilesClient(_client);
UserBlocks = new UserBlocksClient(_client);
Users = new UsersClient(_client);
Anomaly = new AnomalyClient(_client);
AttackProtection = new AttackProtectionClient(_client);
Emails = new EmailsClient(_client);
Guardian = new GuardianClient(_client);
Keys = new Auth0.ManagementApi.Keys.KeysClient(_client);
RiskAssessments = new Auth0.ManagementApi.RiskAssessments.RiskAssessmentsClient(_client);
Tenants = new TenantsClient(_client);
VerifiableCredentials = new VerifiableCredentialsClient(_client);
return clientOptions;
}

/// <inheritdoc />
public IActionsClient Actions { get; }

/// <inheritdoc />
public IBrandingClient Branding { get; }

/// <inheritdoc />
public IClientGrantsClient ClientGrants { get; }

/// <inheritdoc />
public IClientsClient Clients { get; }

/// <inheritdoc />
public IConnectionProfilesClient ConnectionProfiles { get; }

/// <inheritdoc />
public IConnectionsClient Connections { get; }

/// <inheritdoc />
public ICustomDomainsClient CustomDomains { get; }

/// <inheritdoc />
public IDeviceCredentialsClient DeviceCredentials { get; }

/// <inheritdoc />
public IEmailTemplatesClient EmailTemplates { get; }

/// <inheritdoc />
public IEventStreamsClient EventStreams { get; }

/// <inheritdoc />
public IFlowsClient Flows { get; }

/// <inheritdoc />
public IFormsClient Forms { get; }

/// <inheritdoc />
public IUserGrantsClient UserGrants { get; }

/// <inheritdoc />
public IGroupsClient Groups { get; }

/// <inheritdoc />
public IHooksClient Hooks { get; }

/// <inheritdoc />
public IJobsClient Jobs { get; }

/// <inheritdoc />
public ILogStreamsClient LogStreams { get; }

/// <inheritdoc />
public ILogsClient Logs { get; }

/// <inheritdoc />
public INetworkAclsClient NetworkAcls { get; }

/// <inheritdoc />
public IOrganizationsClient Organizations { get; }

/// <inheritdoc />
public IPromptsClient Prompts { get; }

/// <inheritdoc />
public IRefreshTokensClient RefreshTokens { get; }

/// <inheritdoc />
public IResourceServersClient ResourceServers { get; }

/// <inheritdoc />
public IRolesClient Roles { get; }

/// <inheritdoc />
public IRulesClient Rules { get; }

/// <inheritdoc />
public IRulesConfigsClient RulesConfigs { get; }

/// <inheritdoc />
public ISelfServiceProfilesClient SelfServiceProfiles { get; }

/// <inheritdoc />
public ISessionsClient Sessions { get; }

/// <inheritdoc />
public IStatsClient Stats { get; }

/// <inheritdoc />
public ISupplementalSignalsClient SupplementalSignals { get; }

/// <inheritdoc />
public ITicketsClient Tickets { get; }

/// <inheritdoc />
public ITokenExchangeProfilesClient TokenExchangeProfiles { get; }

/// <inheritdoc />
public IUserAttributeProfilesClient UserAttributeProfiles { get; }

/// <inheritdoc />
public IUserBlocksClient UserBlocks { get; }

/// <inheritdoc />
public IUsersClient Users { get; }

/// <inheritdoc />
public IAnomalyClient Anomaly { get; }

/// <inheritdoc />
public IAttackProtectionClient AttackProtection { get; }

/// <inheritdoc />
public IEmailsClient Emails { get; }

/// <inheritdoc />
public IGuardianClient Guardian { get; }

/// <inheritdoc />
public Auth0.ManagementApi.Keys.IKeysClient Keys { get; }

/// <inheritdoc />
public Auth0.ManagementApi.RiskAssessments.IRiskAssessmentsClient RiskAssessments { get; }

/// <inheritdoc />
public ITenantsClient Tenants { get; }

/// <inheritdoc />
public IVerifiableCredentialsClient VerifiableCredentials { get; }

/// <summary>
/// Disposes the <see cref="ManagementClient"/> and releases managed resources.
/// Only disposes the internal <see cref="HttpClient"/> if it was created by this instance.
Expand Down
Loading