/// <summary> /// Processes the consent logic. /// </summary> /// <param name="request">The request.</param> /// <param name="consent">The consent.</param> /// <returns></returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentException">Invalid PromptMode</exception> protected internal virtual async Task <InteractionResponse> ProcessConsentAsync(ValidatedAuthorizeRequest request, ConsentResponse consent = null) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (request.PromptMode != null && request.PromptMode != OidcConstants.PromptModes.None && request.PromptMode != OidcConstants.PromptModes.Consent) { _logger.LogError("Invalid prompt mode: {promptMode}", request.PromptMode); throw new ArgumentException("Invalid PromptMode"); } var consentRequired = await _consent.RequiresConsentAsync(request.Subject, request.Client, request.RequestedScopes); if (consentRequired && request.PromptMode == OidcConstants.PromptModes.None) { _logger.LogInformation("Error: prompt=none requested, but consent is required."); return(new InteractionResponse { Error = OidcConstants.AuthorizeErrors.ConsentRequired }); } if (request.PromptMode == OidcConstants.PromptModes.Consent || consentRequired) { var response = new InteractionResponse(); // did user provide consent if (consent == null) { // user was not yet shown conset screen response.IsConsent = true; _logger.LogInformation("Showing consent: User has not yet consented"); } else { request.WasConsentShown = true; _logger.LogTrace("Consent was shown to user"); // user was shown consent -- did they say yes or no if (consent.Granted == false) { // no need to show consent screen again // build access denied error to return to client response.Error = OidcConstants.AuthorizeErrors.AccessDenied; _logger.LogInformation("Error: User denied consent"); } else { // double check that required scopes are in the list of consented scopes var valid = request.ValidatedScopes.ValidateRequiredScopes(consent.ScopesConsented); if (valid == false) { response.Error = OidcConstants.AuthorizeErrors.AccessDenied; _logger.LogInformation("Error: User denied consent to required scopes"); } else { // they said yes, set scopes they chose request.ValidatedScopes.SetConsentedScopes(consent.ScopesConsented); _logger.LogInformation("User consented to scopes: {scopes}", consent.ScopesConsented); if (request.Client.AllowRememberConsent) { // remember consent var scopes = Enumerable.Empty <string>(); if (consent.RememberConsent) { // remember what user actually selected scopes = request.ValidatedScopes.GrantedResources.ToScopeNames(); _logger.LogDebug("User indicated to remember consent for scopes: {scopes}", scopes); } await _consent.UpdateConsentAsync(request.Subject, request.Client, scopes); } } } } return(response); } return(new InteractionResponse()); }
/// <summary> /// Processes the consent logic. /// </summary> /// <param name="request">The request.</param> /// <param name="consent">The consent.</param> /// <returns></returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentException">Invalid PromptMode</exception> protected internal virtual async Task <InteractionResponse> ProcessConsentAsync(ValidatedAuthorizeRequest request, ConsentResponse consent = null) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (request.PromptModes.Any() && !request.PromptModes.Contains(OidcConstants.PromptModes.None) && !request.PromptModes.Contains(OidcConstants.PromptModes.Consent)) { Logger.LogError("Invalid prompt mode: {promptMode}", request.PromptModes.ToSpaceSeparatedString()); throw new ArgumentException("Invalid PromptMode"); } var consentRequired = await Consent.RequiresConsentAsync(request.Subject, request.Client, request.ValidatedResources.ParsedScopes); if (consentRequired && request.PromptModes.Contains(OidcConstants.PromptModes.None)) { Logger.LogInformation("Error: prompt=none requested, but consent is required."); return(new InteractionResponse { Error = OidcConstants.AuthorizeErrors.ConsentRequired }); } if (request.PromptModes.Contains(OidcConstants.PromptModes.Consent) || consentRequired) { var response = new InteractionResponse(); // did user provide consent if (consent == null) { // user was not yet shown conset screen response.IsConsent = true; Logger.LogInformation("Showing consent: User has not yet consented"); } else { request.WasConsentShown = true; Logger.LogTrace("Consent was shown to user"); // user was shown consent -- did they say yes or no if (consent.Granted == false) { // no need to show consent screen again // build error to return to client Logger.LogInformation("Error: User consent result: {error}", consent.Error); var error = consent.Error switch { AuthorizationError.AccountSelectionRequired => OidcConstants.AuthorizeErrors.AccountSelectionRequired, AuthorizationError.ConsentRequired => OidcConstants.AuthorizeErrors.ConsentRequired, AuthorizationError.InteractionRequired => OidcConstants.AuthorizeErrors.InteractionRequired, AuthorizationError.LoginRequired => OidcConstants.AuthorizeErrors.LoginRequired, _ => OidcConstants.AuthorizeErrors.AccessDenied }; response.Error = error; response.ErrorDescription = consent.ErrorDescription; } else { // double check that required scopes are in the list of consented scopes var requiredScopes = request.ValidatedResources.GetRequiredScopeValues(); var valid = requiredScopes.All(x => consent.ScopesValuesConsented.Contains(x)); if (valid == false) { response.Error = OidcConstants.AuthorizeErrors.AccessDenied; Logger.LogInformation("Error: User denied consent to required scopes"); } else { // they said yes, set scopes they chose request.Description = consent.Description; request.ValidatedResources = request.ValidatedResources.Filter(consent.ScopesValuesConsented); Logger.LogInformation("User consented to scopes: {scopes}", consent.ScopesValuesConsented); if (request.Client.AllowRememberConsent) { // remember consent var scopes = Enumerable.Empty <string>(); if (consent.RememberConsent) { // remember what user actually selected scopes = request.ValidatedResources.ScopeValues; Logger.LogDebug("User indicated to remember consent for scopes: {scopes}", scopes); } await Consent.UpdateConsentAsync(request.Subject, request.Client, request.ValidatedResources.ParsedScopes); } } } } return(response); } return(new InteractionResponse()); }