- 1. Client Initialization
- 2. Login With Client Credentials
- 3. Authenticate using Resource Owner Password Grant Flow with MFA
public async Task Initialize(string returnUrl = "/")
{
var authClient = new AuthenticationApiClient("my.custom.domain");
}Or you could pass your own implementation of the IAuthenticationConnection to override the default behaviour of interacting with the Auth0 server as below.
public class ExampleApp
{
public class YourCustomImplementation : IAuthenticationConnection
{
public Task<T> GetAsync<T>(
Uri uri,
IDictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
// Custom Implementation
return (Task<T>)Task.CompletedTask;
}
public Task<T> SendAsync<T>(
HttpMethod method,
Uri uri,
object body,
IDictionary<string, string> headers = null,
CancellationToken cancellationToken = default)
{
// Custom Implementation
return (Task<T>)Task.CompletedTask;
}
}
public async Task Initialize(string returnUrl = "/")
{
var authConnection = new YourCustomImplementation();
var authClient = new AuthenticationApiClient("my.custom.domain", authConnection);
}
}Use the client's credentials to fetch the access token for further use.
To learn more about Client Credentials Flow head to the Docs.
public async Task LoginWithClientCredentials()
{
var authClient = new AuthenticationApiClient("my.custom.domain");
// Fetch the access token using the Client Credentials.
var accessTokenResponse = await authClient.GetTokenAsync(new ClientCredentialsTokenRequest()
{
Audience = "audience",
ClientId = "clientId",
ClientSecret = "clientSecret",
});
Console.WriteLine($"Access Token : {accessTokenResponse.AccessToken}");
Console.WriteLine($"Refresh Token : {accessTokenResponse.RefreshToken}");
Console.WriteLine($"Id Token : {accessTokenResponse.IdToken}");
Console.WriteLine($"Token Type : {accessTokenResponse.TokenType}");
Console.WriteLine($"Expires In : {accessTokenResponse.ExpiresIn}");
}Head here to undertstand more about this flow and to get a glimpse of the pre-requisites required for this flow.
- When the user tries to login for the first time since enabling MFA, we would encounter an
ErrorApiExceptionexception indicating that MFA is required. - We then extract the
mfa_tokenfrom the exception and use that to enroll / challenge the user.
public async Task LoginWithRopgWithMfa()
{
var authClient = new AuthenticationApiClient("my.custom.domain");
string mfaToken = "";
try
{
var accessTokenResponse = await authClient.GetTokenAsync(new ResourceOwnerTokenRequest()
{
ClientId = "_clientId",
ClientSecret = "_clientSecret",
Username = "userName",
Password = "password",
Scope = "openid profile email", // Depends on the scopes you want to request.
Realm = "realm"
});
} catch (ErrorApiException ex)
{
// Indicates that MFA is required.
mfaToken = ex.ApiError.ExtraData["mfa_token"];
}
}- Using the
mfa_tokenwe trigger a flow that will send out a code to the user.
// Example of Enrolling the user
var resp = await authClient.AssociateMfaAuthenticatorAsync(
new AssociateMfaAuthenticatorRequest
{
ClientId = "_clientId",
ClientSecret = "_clientSecret",
OobChannels = new List<string> { "sms" },
AuthenticatorTypes = new[] { "oob" },
Token = mfaToken,
PhoneNumber = "+911234567890" // Users phone-number which will receive the code.
});var token = await authClient.GetTokenAsync(new MfaOobTokenRequest()
{
ClientId = _clientId,
ClientSecret = _clientSecret,
MfaToken = mfaToken,
OobCode = resp.OobCode,
BindingCode = "sms" // the Code received by the user from the previous call.
}
);var response = await authClient.MfaChallenge(
new MfaChallengeRequest()
{
ClientId = _clientId,
ClientSecret = _clientSecret,
MfaToken = mfaToken,
ChallengeType = "oob",
AuthenticatorId = "authenticatorId"
});var response = await authClient.ListMfaAuthenticatorsAsync("mfaToken");await authClient.DeleteMfaAuthenticatorAsync(
new DeleteMfaAuthenticatorRequest()
{
AccessToken = "AccessToken",
AuthenticatorId = "id-random"
});- 1. Management Client Initialization
- 2. Update M2M Token Quota at different levels
- 3. Get Job Error Details
- 4. Manage Network Access Control Lists (ACLs)
- 5. Using a Custom Domain with the Management API
The recommended way to initialize the Management API client is using the ManagementClient wrapper, which abstracts token management via an ITokenProvider.
Client credentials (recommended — tokens are acquired and refreshed automatically):
using Auth0.ManagementApi;
public async Task Initialize()
{
var client = new ManagementClient(new ManagementClientOptions
{
Domain = "my.custom.domain",
TokenProvider = new ClientCredentialsTokenProvider(
domain: "my.custom.domain",
clientId: "clientId",
clientSecret: "clientSecret"
)
});
// Tokens are acquired and refreshed automatically
var users = await client.Users.ListAsync(new ListUsersRequestParameters());
}Async delegate (retrieve tokens from an external source such as a vault):
var client = new ManagementClient(new ManagementClientOptions
{
Domain = "my.custom.domain",
TokenProvider = new DelegateTokenProvider(ct => GetTokenFromVaultAsync(ct))
});If you prefer to manage tokens yourself, you can use the ManagementApiClient directly:
using Auth0.ManagementApi;
public async Task InitializeWithManualToken()
{
var authClient = new AuthenticationApiClient("my.custom.domain");
// Fetch the access token using the Client Credentials.
var accessTokenResponse = await authClient.GetTokenAsync(new ClientCredentialsTokenRequest()
{
Audience = "https://my.custom.domain/api/v2/",
ClientId = "clientId",
ClientSecret = "clientSecret",
});
var apiClient = new ManagementApiClient(
token: accessTokenResponse.AccessToken,
clientOptions: new ClientOptions { BaseUrl = "https://my.custom.domain/api/v2" });
}Assuming you have a ManagementClient or ManagementApiClient initialized as shown above.
using Auth0.ManagementApi;
var tenantUpdateSettings = new UpdateTenantSettingsRequestContent
{
DefaultTokenQuota = new DefaultTokenQuota
{
Clients = new TokenQuotaConfiguration
{
ClientCredentials = new TokenQuotaClientCredentials
{
Enforce = true,
PerDay = 200,
PerHour = 100
}
},
Organizations = new TokenQuotaConfiguration
{
ClientCredentials = new TokenQuotaClientCredentials
{
Enforce = true,
PerDay = 200,
PerHour = 100
}
}
}
};
var updatedSettings = await client.Tenants.Settings.UpdateAsync(tenantUpdateSettings);Assuming you have a ManagementClient or ManagementApiClient initialized as shown above.
using Auth0.ManagementApi;
using Auth0.ManagementApi.Core;
var clientUpdateRequest = new UpdateClientRequestContent
{
TokenQuota = Optional<UpdateTokenQuota?>.Of(new UpdateTokenQuota
{
ClientCredentials = new TokenQuotaClientCredentials
{
Enforce = true,
PerDay = 200,
PerHour = 100
}
})
};
var clientUpdateResponse = await client.Clients.UpdateAsync("client_id", clientUpdateRequest);Assuming you have a ManagementClient or ManagementApiClient initialized as shown above.
using Auth0.ManagementApi;
using Auth0.ManagementApi.Core;
var orgUpdateRequest = new UpdateOrganizationRequestContent
{
TokenQuota = Optional<UpdateTokenQuota?>.Of(new UpdateTokenQuota
{
ClientCredentials = new TokenQuotaClientCredentials
{
Enforce = true,
PerDay = 200,
PerHour = 100
}
})
};
var orgUpdateResponse = await client.Organizations.UpdateAsync("org_id", orgUpdateRequest);When a job fails, you can get the error details using the Jobs.Errors.GetAsync method.
The response is an undiscriminated union type that will contain either IEnumerable<GetJobErrorResponseContent> (for import job errors) or GetJobGenericErrorResponseContent (for other job errors).
Assuming you have a ManagementClient or ManagementApiClient initialized as shown above.
using Auth0.ManagementApi;
public async Task GetJobErrorDetails(string jobId)
{
var jobError = await client.Jobs.Errors.GetAsync(jobId);
// Handle the response based on its type using Visit() for side effects
jobError.Visit(
importErrors =>
{
// Handle import job errors (IEnumerable<GetJobErrorResponseContent>)
foreach (var error in importErrors)
{
Console.WriteLine($"User object: {error.User}");
if (error.Errors != null)
{
foreach (var err in error.Errors)
{
Console.WriteLine($"Error Code: {err.Code}");
Console.WriteLine($"Error Message: {err.Message}");
Console.WriteLine($"Error Path: {err.Path}");
}
}
}
},
genericError =>
{
// Handle generic job errors (GetJobGenericErrorResponseContent)
Console.WriteLine($"Job Type: {genericError.Type}");
Console.WriteLine($"Job Status: {genericError.Status}");
Console.WriteLine($"Job Id: {genericError.Id}");
Console.WriteLine($"Job Connection Id: {genericError.ConnectionId}");
Console.WriteLine($"Job Created At: {genericError.CreatedAt}");
Console.WriteLine($"Job Status Details: {genericError.StatusDetails}");
}
);
// Alternative: Use Match() to return a value
var summary = jobError.Match(
importErrors => $"Import job with {importErrors.Count()} errors",
genericError => $"Job {genericError.Id} failed with status: {genericError.Status}"
);
Console.WriteLine(summary);
// Alternative: Use TryGet methods for conditional access
if (jobError.TryGetListOfGetJobErrorResponseContent(out var errors))
{
Console.WriteLine($"Found {errors!.Count()} import errors");
}
else if (jobError.TryGetGetJobGenericErrorResponseContent(out var generic))
{
Console.WriteLine($"Generic error: {generic!.StatusDetails}");
}
}You can read more about ACLs on the Docs
Assuming a scenario where you want to create a Network ACL that blocks traffic from a specific country,
you can use the following code snippet. This example uses the NetworkAcls client to create a new Network ACL
with a rule that blocks traffic from an Imaginary country (IMG).
using Auth0.ManagementApi;
public async Task CreateNetworkAcl()
{
var networkAcl = new CreateNetworkAclRequestContent
{
Active = true,
Priority = 1,
Description = "Reject all traffic from imaginary Country",
Rule = new NetworkAclRule
{
Action = new NetworkAclAction { Block = true },
Match = new NetworkAclMatch
{
GeoCountryCodes = new List<string> { "IMG" }
},
Scope = NetworkAclRuleScopeEnum.Management
}
};
await client.NetworkAcls.CreateAsync(networkAcl);
}using Auth0.ManagementApi;
public async Task GetAllNetworkAcls()
{
var pager = await client.NetworkAcls.ListAsync(new ListNetworkAclsRequestParameters());
await foreach (var acl in pager)
{
Console.WriteLine($"Network ACL ID: {acl.Id}");
Console.WriteLine($"Description: {acl.Description}");
Console.WriteLine($"Priority: {acl.Priority}");
Console.WriteLine($"Active: {acl.Active}");
Console.WriteLine($"Created At: {acl.CreatedAt}");
Console.WriteLine($"Updated At: {acl.UpdatedAt}");
}
}using Auth0.ManagementApi;
public async Task GetNetworkAcl(string aclId)
{
var networkAcl = await client.NetworkAcls.GetAsync(aclId);
Console.WriteLine($"Network ACL ID: {networkAcl.Id}");
Console.WriteLine($"Description: {networkAcl.Description}");
Console.WriteLine($"Priority: {networkAcl.Priority}");
Console.WriteLine($"Active: {networkAcl.Active}");
Console.WriteLine($"Created At: {networkAcl.CreatedAt}");
Console.WriteLine($"Updated At: {networkAcl.UpdatedAt}");
}Assuming you have the id of the ACL to update, you can use the following code snippet.
using Auth0.ManagementApi;
public async Task UpdateNetworkAcl(string aclId)
{
var updateRequest = new UpdateNetworkAclRequestContent
{
Active = false,
Priority = 2,
Description = "Updated description for examples",
Rule = new NetworkAclRule
{
Action = new NetworkAclAction { Block = true },
Match = new NetworkAclMatch
{
GeoCountryCodes = new List<string> { "US" }
},
NotMatch = new NetworkAclMatch
{
GeoCountryCodes = new List<string> { "CA" }
},
Scope = NetworkAclRuleScopeEnum.Management
}
};
await client.NetworkAcls.UpdateAsync(aclId, updateRequest);
}Assuming you have the id of the ACL to update, you can use the following code snippet.
using Auth0.ManagementApi;
public async Task SetNetworkAcl(string aclId)
{
var setRequest = new SetNetworkAclRequestContent
{
Active = false,
Priority = 2,
Description = "Updated description for examples",
Rule = new NetworkAclRule
{
Action = new NetworkAclAction { Block = true },
Match = new NetworkAclMatch
{
GeoCountryCodes = new List<string> { "US" }
},
NotMatch = new NetworkAclMatch
{
GeoCountryCodes = new List<string> { "CA" }
},
Scope = NetworkAclRuleScopeEnum.Management
}
};
await client.NetworkAcls.SetAsync(aclId, setRequest);
}