Redirect URI Validator
Duende.IdentityServer.Validation.IRedirectUriValidator
Section titled “Duende.IdentityServer.Validation.IRedirectUriValidator”Validates redirect URIs and post-logout redirect URIs submitted in authorization and end-session requests.
IdentityServer invokes this validator during the authorization request pipeline to confirm that the redirect_uri
parameter supplied by the client is permitted for that client, and during the end-session pipeline to confirm
that the post_logout_redirect_uri is permitted.
The default implementation performs an exact string match against the URIs registered on the client. Override this interface to apply custom matching logic, such as wildcard or pattern-based URI validation.
/// <summary>/// Validates redirect URIs and post-logout redirect URIs submitted in authorization and end-session requests./// </summary>public interface IRedirectUriValidator{ /// <summary> /// Determines whether a redirect URI is valid for a client. /// </summary> [Obsolete("Use the overload that takes a RedirectUriValidationContext parameter instead.")] Task<bool> IsRedirectUriValidAsync(string requestedUri, Client client);
/// <summary> /// Determines whether a redirect URI is valid for a client. /// </summary> Task<bool> IsRedirectUriValidAsync(RedirectUriValidationContext context, CancellationToken ct);
/// <summary> /// Determines whether a post-logout redirect URI is valid for a client. /// </summary> Task<bool> IsPostLogoutRedirectUriValidAsync(string requestedUri, Client client, CancellationToken ct);}IRedirectUriValidator APIs
Section titled “IRedirectUriValidator APIs”-
IsRedirectUriValidAsync(RedirectUriValidationContext, CancellationToken)Determines whether a
redirect_uriis valid for a client. This overload is preferred because it provides additional context such as the full request parameters, any validated request object values, and the type of authorize request (e.g., PAR vs. standard authorize). -
IsRedirectUriValidAsync(string, Client)(Deprecated)Legacy overload that only receives the requested URI and client. Marked as obsolete and will be removed in a future version. Use the context-based overload instead.
-
IsPostLogoutRedirectUriValidAsyncCalled during end-session request processing to verify that the
post_logout_redirect_uriparameter supplied by the client is registered and permitted.
RedirectUriValidationContext
Section titled “RedirectUriValidationContext”Models the context for validating a client’s redirect URI.
-
RequestedUri- The URI to validate for the client. -
Client- The client whose registered redirect URIs should be checked. -
RequestParameters- The raw request parameters as aNameValueCollection. -
RequestObjectValues- Validated request object values as a collection of claims. May benullif no request object was submitted. -
AuthorizeRequestType- Indicates the context of the request: PAR vs. standard authorize with or without pushed parameters.
Registration
Section titled “Registration”Register a custom implementation using AddRedirectUriValidator<T>() on the IdentityServer builder:
builder.Services.AddIdentityServer() .AddRedirectUriValidator<CustomRedirectUriValidator>();Examples
Section titled “Examples”Wildcard subdomain matching
Section titled “Wildcard subdomain matching”This example allows redirect URIs that match a registered pattern with a wildcard subdomain:
public class WildcardRedirectUriValidator : IRedirectUriValidator{ public Task<bool> IsRedirectUriValidAsync(RedirectUriValidationContext context, CancellationToken ct) { var requestedUri = new Uri(context.RequestedUri);
foreach (var registeredUri in context.Client.RedirectUris) { if (registeredUri.StartsWith("https://*.")) { // Extract the domain pattern (e.g., "*.example.com") var pattern = registeredUri.Substring("https://".Length); var domain = pattern.Substring(2); // Remove "*."
if (requestedUri.Host.EndsWith(domain) && requestedUri.Scheme == "https") { return Task.FromResult(true); } } else if (context.RequestedUri == registeredUri) { return Task.FromResult(true); } }
return Task.FromResult(false); }
public Task<bool> IsRedirectUriValidAsync(string requestedUri, Client client) { // Delegate to the context-based overload var context = new RedirectUriValidationContext { RequestedUri = requestedUri, Client = client }; return IsRedirectUriValidAsync(context, CancellationToken.None); }
public Task<bool> IsPostLogoutRedirectUriValidAsync(string requestedUri, Client client, CancellationToken ct) { // Apply similar wildcard logic or exact matching return Task.FromResult(client.PostLogoutRedirectUris.Contains(requestedUri)); }}