Table of Contents

Class AuthorizeInteractionResponseGenerator

Namespace
Fdyay.IdentityServer.ResponseHandling
Assembly
Fdyay.IdentityServer.AspNetCore.dll

Duende's default interaction generator: create account, then login, then consent.

public class AuthorizeInteractionResponseGenerator : IAuthorizeInteractionResponseGenerator
Inheritance
AuthorizeInteractionResponseGenerator
Implements
Inherited Members

Constructors

AuthorizeInteractionResponseGenerator(IOptions<IdentityServerOptions>, TimeProvider, ILogger<AuthorizeInteractionResponseGenerator>, IConsentService, IProfileService?)

Creates the generator, as the container resolves it.

public AuthorizeInteractionResponseGenerator(IOptions<IdentityServerOptions> options, TimeProvider timeProvider, ILogger<AuthorizeInteractionResponseGenerator> logger, IConsentService consent, IProfileService? profile = null)

Parameters

options IOptions<IdentityServerOptions>

The server options; ValidateTenantOnAuthorization decides whether the tenant hint is checked.

timeProvider TimeProvider

The clock a session's age is measured against for max_age.

logger ILogger<AuthorizeInteractionResponseGenerator>

Receives the generator's diagnostics.

consent IConsentService

Decides whether the request needs the user's consent.

profile IProfileService

Asked whether the user is still active; null asks nothing.

Exceptions

ArgumentNullException

options is null.

Properties

Decides whether the request needs the user's consent.

protected IConsentService Consent { get; }

Property Value

IConsentService

Logger

Receives the generator's diagnostics.

protected ILogger Logger { get; }

Property Value

ILogger

Options

The server options, as they stood when the generator was created.

protected IdentityServerOptions Options { get; }

Property Value

IdentityServerOptions

Profile

Asked whether the user is still active; none registered asks nothing.

protected IProfileService? Profile { get; }

Property Value

IProfileService

TimeProvider

The clock a session's age is measured against for max_age.

protected TimeProvider TimeProvider { get; }

Property Value

TimeProvider

Methods

ProcessConsentAsync(ValidatedAuthorizeRequest, ConsentResponse?, CancellationToken)

Asks for consent when it is needed, and reads the decision when there is one.

protected virtual Task<InteractionResponse> ProcessConsentAsync(ValidatedAuthorizeRequest request, ConsentResponse? consent, CancellationToken ct)

Parameters

request ValidatedAuthorizeRequest
consent ConsentResponse
ct CancellationToken

Returns

Task<InteractionResponse>

Remarks

Duende 8.0.1's ProcessConsentAsync, measured: a prompt value still standing that is neither none nor consent is one nothing acted on, and refused ("Invalid PromptMode"); consent the user must give under prompt=none is consent_required; and a grant that leaves out a required scope is access_denied. A grant names the request (Description) and narrows it to what was consented, walking the request rather than the decision so a decision cannot add a scope.

Ours: a decision is read whenever there is one, where Duende reads it only while consent is still required; and it is not recorded here, because the consent page's GrantConsentAsync has already recorded it through UpdateConsentAsync(string, Client, ConsentResponse, CancellationToken).

ProcessCreateAccountAsync(ValidatedAuthorizeRequest, CancellationToken)

Sends a prompt=create request to the create-account page.

protected virtual Task<InteractionResponse> ProcessCreateAccountAsync(ValidatedAuthorizeRequest request, CancellationToken ct)

Parameters

request ValidatedAuthorizeRequest
ct CancellationToken

Returns

Task<InteractionResponse>

Remarks

Duende's: create is suppressed as it is answered, so the return from the page is not sent there again.

ProcessInteractionAsync(ValidatedAuthorizeRequest, ConsentResponse?, CancellationToken)

public virtual Task<InteractionResponse> ProcessInteractionAsync(ValidatedAuthorizeRequest request, ConsentResponse? consent, CancellationToken ct)

Parameters

request ValidatedAuthorizeRequest
consent ConsentResponse
ct CancellationToken

Returns

Task<InteractionResponse>

Remarks

Duende 8.0.1's, measured: a denial from the consent page is answered first; then create account, login and consent are asked in that order and the first that wants a page wins; and under prompt=none a page becomes the error that says which one — login_required, consent_required, or interaction_required — with no description, as Duende sends none.

ProcessLoginAsync(ValidatedAuthorizeRequest, CancellationToken)

Sends the user to sign in when the request or the session calls for it.

protected virtual Task<InteractionResponse> ProcessLoginAsync(ValidatedAuthorizeRequest request, CancellationToken ct)

Parameters

request ValidatedAuthorizeRequest
ct CancellationToken

Returns

Task<InteractionResponse>

Remarks

Duende 8.0.1's ProcessLoginAsync, measured, in its order: prompt=login or select_account, and max_age=0, each suppressed as it is answered so the return cannot loop; then nobody signed in, or a user the profile service calls inactive (asked as AuthorizeEndpoint); a session from another tenant (under ValidateTenantOnAuthorization) or another provider than the request's acr_values hint names; a session older than max_age; a local session the client does not allow, or a provider outside its restrictions; and a session older than the client's UserSsoLifetime.

Ours: a session with no readable auth_time is too old for max_age and the SSO lifetime — the claim is what proves freshness, so its absence cannot be read as fresh enough. An idp: hint the client's restrictions do not allow asks for nothing, as Duende's validator removes it (RemoveIdP).