/* * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) * See https://github.com/openiddict/openiddict-core for more information concerning * the license and the contributors participating to this project. */ using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Security.Claims; using Microsoft.Extensions.Logging; namespace OpenIddict.Client; public static partial class OpenIddictClientEvents { /// /// Represents an abstract base class used for certain event contexts. /// [EditorBrowsable(EditorBrowsableState.Never)] public abstract class BaseContext { /// /// Creates a new instance of the class. /// protected BaseContext(OpenIddictClientTransaction transaction) => Transaction = transaction ?? throw new ArgumentNullException(nameof(transaction)); /// /// Gets the environment associated with the current request being processed. /// public OpenIddictClientTransaction Transaction { get; } /// /// Gets or sets the endpoint type that handled the request, if applicable. /// public OpenIddictClientEndpointType EndpointType { get => Transaction.EndpointType; set => Transaction.EndpointType = value; } /// /// Gets the logger responsible for logging processed operations. /// public ILogger Logger => Transaction.Logger; /// /// Gets the OpenIddict client options. /// public OpenIddictClientOptions Options => Transaction.Options; /// /// Gets or sets the issuer used for the current request. /// public Uri? Issuer { get => Transaction.Issuer; set => Transaction.Issuer = value; } /// /// Gets or sets the server configuration used for the current request. /// public OpenIddictConfiguration Configuration { get => Transaction.Configuration; set => Transaction.Configuration = value; } /// /// Gets or sets the client registration used for the current request. /// public OpenIddictClientRegistration Registration { get => Transaction.Registration; set => Transaction.Registration = value; } } /// /// Represents an abstract base class used for certain event contexts. /// [EditorBrowsable(EditorBrowsableState.Never)] public abstract class BaseRequestContext : BaseContext { /// /// Creates a new instance of the class. /// protected BaseRequestContext(OpenIddictClientTransaction transaction) : base(transaction) { } /// /// Gets a boolean indicating whether the request was fully handled. /// public bool IsRequestHandled { get; private set; } /// /// Gets a boolean indicating whether the request processing was skipped. /// public bool IsRequestSkipped { get; private set; } /// /// Marks the request as fully handled. Once declared handled, /// a request shouldn't be processed further by the underlying host. /// public void HandleRequest() => IsRequestHandled = true; /// /// Marks the request as skipped. Once declared skipped, a request /// shouldn't be processed further by OpenIddict but should be allowed /// to go through the next components in the processing pipeline /// (if this pattern is supported by the underlying host). /// public void SkipRequest() => IsRequestSkipped = true; } /// /// Represents an abstract base class used for certain event contexts. /// [EditorBrowsable(EditorBrowsableState.Never)] public abstract class BaseExternalContext : BaseValidatingContext { /// /// Creates a new instance of the class. /// protected BaseExternalContext(OpenIddictClientTransaction transaction) : base(transaction) { } /// /// Gets or sets the address of the external endpoint to communicate with. /// public Uri? Address { get; set; } } /// /// Represents an abstract base class used for certain event contexts. /// [EditorBrowsable(EditorBrowsableState.Never)] public abstract class BaseValidatingContext : BaseRequestContext { /// /// Creates a new instance of the class. /// protected BaseValidatingContext(OpenIddictClientTransaction transaction) : base(transaction) { } /// /// Gets a boolean indicating whether the request will be rejected. /// public bool IsRejected { get; protected set; } /// /// Gets or sets the "error" parameter returned to the client application. /// public string? Error { get; private set; } /// /// Gets or sets the "error_description" parameter returned to the client application. /// public string? ErrorDescription { get; private set; } /// /// Gets or sets the "error_uri" parameter returned to the client application. /// public string? ErrorUri { get; private set; } /// /// Rejects the request. /// /// The "error" parameter returned to the client application. /// The "error_description" parameter returned to the client application. /// The "error_uri" parameter returned to the client application. public virtual void Reject(string? error = null, string? description = null, string? uri = null) { Error = error; ErrorDescription = description; ErrorUri = uri; IsRejected = true; } } /// /// Represents an abstract base class used for certain event contexts. /// [EditorBrowsable(EditorBrowsableState.Never)] public abstract class BaseValidatingTicketContext : BaseValidatingContext { /// /// Creates a new instance of the class. /// protected BaseValidatingTicketContext(OpenIddictClientTransaction transaction) : base(transaction) { } /// /// Gets or sets the security principal. /// public ClaimsPrincipal? Principal { get; set; } } /// /// Represents an event called when processing an incoming request. /// public sealed class ProcessRequestContext : BaseValidatingContext { /// /// Creates a new instance of the class. /// public ProcessRequestContext(OpenIddictClientTransaction transaction) : base(transaction) { } } /// /// Represents an event called when processing an errored response. /// public sealed class ProcessErrorContext : BaseRequestContext { /// /// Creates a new instance of the class. /// public ProcessErrorContext(OpenIddictClientTransaction transaction) : base(transaction) { } /// /// Gets or sets the request, or if it couldn't be extracted. /// public OpenIddictRequest? Request { get => Transaction.Request; set => Transaction.Request = value; } /// /// Gets or sets the response. /// public OpenIddictResponse Response { get => Transaction.Response!; set => Transaction.Response = value; } /// /// Gets or sets the error returned to the caller. /// public string? Error { get; set; } /// /// Gets or sets the error description returned to the caller. /// public string? ErrorDescription { get; set; } /// /// Gets or sets the error URL returned to the caller. /// public string? ErrorUri { get; set; } /// /// Gets the additional parameters returned to the caller. /// public Dictionary Parameters { get; } = new(StringComparer.Ordinal); } /// /// Represents an event called when processing an authentication operation. /// public sealed class ProcessAuthenticationContext : BaseValidatingContext { /// /// Creates a new instance of the class. /// public ProcessAuthenticationContext(OpenIddictClientTransaction transaction) : base(transaction) { } /// /// Gets or sets the request. /// public OpenIddictRequest Request { get => Transaction.Request!; set => Transaction.Request = value; } /// /// Gets or sets the grant type used for the authentication demand, if applicable. /// public string? GrantType { get; set; } /// /// Gets or sets the response type used for the authentication demand, if applicable. /// public string? ResponseType { get; set; } /// /// Gets or sets the request forgery protection resolved from the user session, if applicable. /// public string? RequestForgeryProtection { get; set; } /// /// Gets or sets the address of the token endpoint, if applicable. /// public Uri? TokenEndpoint { get; set; } /// /// Gets or sets the address of the userinfo endpoint, if applicable. /// public Uri? UserinfoEndpoint { get; set; } /// /// Gets or sets a boolean indicating whether a token request should be sent. /// public bool SendTokenRequest { get; set; } /// /// Gets or sets a boolean indicating whether a token request should be sent. /// public bool SendUserinfoRequest { get; set; } /// /// Gets or sets a boolean indicating whether an authorization /// code should be extracted from the current context. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ExtractAuthorizationCode { get; set; } /// /// Gets or sets a boolean indicating whether a backchannel /// access token should be extracted from the current context. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ExtractBackchannelAccessToken { get; set; } /// /// Gets or sets a boolean indicating whether a backchannel /// identity token should be extracted from the current context. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ExtractBackchannelIdentityToken { get; set; } /// /// Gets or sets a boolean indicating whether a frontchannel /// access token should be extracted from the current context. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ExtractFrontchannelAccessToken { get; set; } /// /// Gets or sets a boolean indicating whether a frontchannel /// identity token should be extracted from the current context. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ExtractFrontchannelIdentityToken { get; set; } /// /// Gets or sets a boolean indicating whether a refresh /// token should be extracted from the current context. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ExtractRefreshToken { get; set; } /// /// Gets or sets a boolean indicating whether a state /// token should be extracted from the current context. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ExtractStateToken { get; set; } /// /// Gets or sets a boolean indicating whether a userinfo /// token should be extracted from the current context. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ExtractUserinfoToken { get; set; } /// /// Gets or sets a boolean indicating whether an authorization /// code must be resolved for the authentication to be considered valid. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool RequireAuthorizationCode { get; set; } /// /// Gets or sets a boolean indicating whether a backchannel access /// token must be resolved for the authentication to be considered valid. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool RequireBackchannelAccessToken { get; set; } /// /// Gets or sets a boolean indicating whether a backchannel identity /// token must be resolved for the authentication to be considered valid. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool RequireBackchannelIdentityToken { get; set; } /// /// Gets or sets a boolean indicating whether a frontchannel identity /// token must be resolved for the authentication to be considered valid. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool RequireFrontchannelAccessToken { get; set; } /// /// Gets or sets a boolean indicating whether a frontchannel identity /// token must be resolved for the authentication to be considered valid. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool RequireFrontchannelIdentityToken { get; set; } /// /// Gets or sets a boolean indicating whether a refresh token /// must be resolved for the authentication to be considered valid. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool RequireRefreshToken { get; set; } /// /// Gets or sets a boolean indicating whether a state token /// must be resolved for the authentication to be considered valid. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool RequireStateToken { get; set; } /// /// Gets or sets a boolean indicating whether a userinfo token /// must be resolved for the authentication to be considered valid. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool RequireUserinfoToken { get; set; } /// /// Gets or sets a boolean indicating whether the authorization /// code extracted from the current context should be validated. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ValidateAuthorizationCode { get; set; } /// /// Gets or sets a boolean indicating whether the backchannel access /// token extracted from the current context should be validated. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ValidateBackchannelAccessToken { get; set; } /// /// Gets or sets a boolean indicating whether the backchannel identity /// token extracted from the current context should be validated. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ValidateBackchannelIdentityToken { get; set; } /// /// Gets or sets a boolean indicating whether the frontchannel access /// token extracted from the current context should be validated. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ValidateFrontchannelAccessToken { get; set; } /// /// Gets or sets a boolean indicating whether the frontchannel identity /// token extracted from the current context should be validated. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ValidateFrontchannelIdentityToken { get; set; } /// /// Gets or sets a boolean indicating whether the refresh token /// extracted from the current context should be validated. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ValidateRefreshToken { get; set; } /// /// Gets or sets a boolean indicating whether the state token /// extracted from the current context should be validated. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ValidateStateToken { get; set; } /// /// Gets or sets a boolean indicating whether the userinfo token /// extracted from the current context should be validated. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool ValidateUserinfoToken { get; set; } /// /// Gets or sets the authorization code to validate, if applicable. /// public string? AuthorizationCode { get; set; } /// /// Gets or sets the backchannel access token to validate, if applicable. /// public string? BackchannelAccessToken { get; set; } /// /// Gets or sets the backchannel identity token to validate, if applicable. /// public string? BackchannelIdentityToken { get; set; } /// /// Gets or sets the frontchannel access token to validate, if applicable. /// public string? FrontchannelAccessToken { get; set; } /// /// Gets or sets the frontchannel identity token to validate, if applicable. /// public string? FrontchannelIdentityToken { get; set; } /// /// Gets or sets the refresh token to validate, if applicable. /// public string? RefreshToken { get; set; } /// /// Gets or sets the username to send to the server, if applicable. /// public string? Username { get; set; } /// /// Gets or sets the password to send to the server, if applicable. /// public string? Password { get; set; } /// /// Gets or sets the frontchannel state token to validate, if applicable. /// public string? StateToken { get; set; } /// /// Gets or sets the userinfo token to validate, if applicable. /// public string? UserinfoToken { get; set; } /// /// Gets or sets the principal extracted from the authorization code, if applicable. /// public ClaimsPrincipal? AuthorizationCodePrincipal { get; set; } /// /// Gets or sets the principal extracted from the backchannel access token, if applicable. /// public ClaimsPrincipal? BackchannelAccessTokenPrincipal { get; set; } /// /// Gets or sets the principal extracted from the backchannel identity token, if applicable. /// public ClaimsPrincipal? BackchannelIdentityTokenPrincipal { get; set; } /// /// Gets or sets the principal extracted from the frontchannel access token, if applicable. /// public ClaimsPrincipal? FrontchannelAccessTokenPrincipal { get; set; } /// /// Gets or sets the principal extracted from the frontchannel identity token, if applicable. /// public ClaimsPrincipal? FrontchannelIdentityTokenPrincipal { get; set; } /// /// Gets or sets the principal extracted from the refresh token, if applicable. /// public ClaimsPrincipal? RefreshTokenPrincipal { get; set; } /// /// Gets or sets the principal extracted from the state token, if applicable. /// public ClaimsPrincipal? StateTokenPrincipal { get; set; } /// /// Gets or sets the principal extracted from the userinfo token, if applicable. /// public ClaimsPrincipal? UserinfoTokenPrincipal { get; set; } /// /// Gets or sets the request sent to the token endpoint, if applicable. /// public OpenIddictRequest? TokenRequest { get; set; } /// /// Gets or sets the response returned by the token endpoint, if applicable. /// public OpenIddictResponse? TokenResponse { get; set; } /// /// Gets or sets the request sent to the userinfo endpoint, if applicable. /// public OpenIddictRequest? UserinfoRequest { get; set; } /// /// Gets or sets the response returned by the userinfo endpoint, if applicable. /// public OpenIddictResponse? UserinfoResponse { get; set; } /// /// Gets or sets a boolean indicating whether a client assertion /// token should be generated (and optionally included in the request). /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool GenerateClientAssertionToken { get; set; } /// /// Gets or sets a boolean indicating whether the generated client /// assertion token should be included as part of the request. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool IncludeClientAssertionToken { get; set; } /// /// Gets or sets the generated client assertion token, if applicable. /// The client assertion token will only be returned if /// is set to . /// public string? ClientAssertionToken { get; set; } /// /// Gets or sets type of the generated client assertion token, if applicable. /// The client assertion token type will only be returned if /// is set to . /// public string? ClientAssertionTokenType { get; set; } /// /// Gets or sets the principal containing the claims that will be /// used to create the client assertion token, if applicable. /// public ClaimsPrincipal? ClientAssertionTokenPrincipal { get; set; } } /// /// Represents an event called when processing a challenge response. /// public sealed class ProcessChallengeContext : BaseValidatingTicketContext { /// /// Creates a new instance of the class. /// public ProcessChallengeContext(OpenIddictClientTransaction transaction) : base(transaction) { } /// /// Gets or sets the request. /// public OpenIddictRequest Request { get => Transaction.Request!; set => Transaction.Request = value; } /// /// Gets or sets the response. /// public OpenIddictResponse Response { get => Transaction.Response!; set => Transaction.Response = value; } /// /// Gets the user-defined authentication properties, if available. /// public Dictionary Properties { get; } = new(StringComparer.Ordinal); /// /// Gets or sets the name of the provider that will be /// used to resolve the issuer identity, if applicable. /// public string? ProviderName { get; set; } /// /// Gets the additional parameters returned to the caller. /// public Dictionary Parameters { get; } = new(StringComparer.Ordinal); /// /// Gets or sets the client identifier that will be used for the challenge demand. /// public string? ClientId { get; set; } /// /// Gets or sets the grant type that will be used for the challenge demand. /// public string? GrantType { get; set; } /// /// Gets or sets the response mode that will be /// used for the challenge demand, if applicable. /// public string? ResponseMode { get; set; } /// /// Gets or sets the response type that will be /// used for the challenge demand, if applicable. /// public string? ResponseType { get; set; } /// /// Gets or sets the redirection endpoint that will /// be used for the challenge demand, if applicable. /// [StringSyntax(StringSyntaxAttribute.Uri)] public string? RedirectUri { get; set; } /// /// Gets or sets the code challenge that will /// be used for the challenge demand, if applicable. /// public string? CodeChallenge { get; set; } /// /// Gets or sets the code challenge method that will /// be used for the challenge demand, if applicable. /// public string? CodeChallengeMethod { get; set; } /// /// Gets or sets the code verifier that will be stored in the state token, if applicable. /// public string? CodeVerifier { get; set; } /// /// Gets or sets the nonce that will be used for the challenge demand, if applicable. /// public string? Nonce { get; set; } /// /// Gets or sets the request forgery protection that will be stored in the state token, if applicable. /// Note: this value MUST NOT be user-defined or extracted from any request and MUST be random /// (generated by a random number generator suitable for cryptographic operations). /// public string? RequestForgeryProtection { get; set; } /// /// Gets or sets the optional return URL that will be stored in the state token, if applicable. /// [StringSyntax(StringSyntaxAttribute.Uri)] public string? TargetLinkUri { get; set; } /// /// Gets or sets the optional identity token hint that will /// be sent to the authorization server, if applicable. /// public string? IdentityTokenHint { get; set; } /// /// Gets or sets the optional login hint that will be sent to the authorization server, if applicable. /// public string? LoginHint { get; set; } /// /// Gets the set of scopes that will be requested to the authorization server. /// public HashSet Scopes { get; } = new(StringComparer.Ordinal); /// /// Gets or sets a boolean indicating whether a state token /// should be generated (and optionally included in the request). /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool GenerateStateToken { get; set; } /// /// Gets or sets a boolean indicating whether the generated /// state token should be included as part of the request. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool IncludeStateToken { get; set; } /// /// Gets or sets the generated state token, if applicable. /// The state token will only be returned if /// is set to . /// public string? StateToken { get; set; } /// /// Gets or sets the principal containing the claims that /// will be used to create the state token, if applicable. /// public ClaimsPrincipal? StateTokenPrincipal { get; set; } } /// /// Represents an event called when processing a sign-out response. /// public sealed class ProcessSignOutContext : BaseValidatingTicketContext { /// /// Creates a new instance of the class. /// public ProcessSignOutContext(OpenIddictClientTransaction transaction) : base(transaction) { } /// /// Gets or sets the request. /// public OpenIddictRequest Request { get => Transaction.Request!; set => Transaction.Request = value; } /// /// Gets or sets the response. /// public OpenIddictResponse Response { get => Transaction.Response!; set => Transaction.Response = value; } /// /// Gets the user-defined authentication properties, if available. /// public Dictionary Properties { get; } = new(StringComparer.Ordinal); /// /// Gets or sets the name of the provider that will be /// used to resolve the issuer identity, if applicable. /// public string? ProviderName { get; set; } /// /// Gets or sets the client identifier that will be used for the sign-out demand. /// public string? ClientId { get; set; } /// /// Gets or sets the post-logout redirection endpoint that /// will be used for the sign-out demand, if applicable. /// [StringSyntax(StringSyntaxAttribute.Uri)] public string? PostLogoutRedirectUri { get; set; } /// /// Gets or sets the optional identity token hint that will /// be sent to the authorization server, if applicable. /// public string? IdentityTokenHint { get; set; } /// /// Gets or sets the optional login hint that will be sent to the authorization server, if applicable. /// public string? LoginHint { get; set; } /// /// Gets or sets the optional return URL that will be stored in the state token, if applicable. /// public string? TargetLinkUri { get; set; } /// /// Gets or sets the nonce that will be used for the sign-out demand, if applicable. /// public string? Nonce { get; set; } /// /// Gets or sets the request forgery protection that will be stored in the state token, if applicable. /// Note: this value MUST NOT be user-defined or extracted from any request and MUST be random /// (generated by a random number generator suitable for cryptographic operations). /// public string? RequestForgeryProtection { get; set; } /// /// Gets the additional parameters returned to the caller. /// public Dictionary Parameters { get; } = new(StringComparer.Ordinal); /// /// Gets or sets a boolean indicating whether a state token /// should be generated (and optionally included in the request). /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool GenerateStateToken { get; set; } /// /// Gets or sets a boolean indicating whether the generated /// state token should be included as part of the request. /// Note: overriding the value of this property is generally not /// recommended, except when dealing with non-standard clients. /// public bool IncludeStateToken { get; set; } /// /// Gets or sets the generated state token, if applicable. /// The state token will only be returned if /// is set to . /// public string? StateToken { get; set; } /// /// Gets or sets the principal containing the claims that /// will be used to create the state token, if applicable. /// public ClaimsPrincipal? StateTokenPrincipal { get; set; } } }