diff --git a/SecurityService.UserInterface/Pages/Consent/Index.cshtml.cs b/SecurityService.UserInterface/Pages/Consent/Index.cshtml.cs index 4b82c0ad..38c59b49 100644 --- a/SecurityService.UserInterface/Pages/Consent/Index.cshtml.cs +++ b/SecurityService.UserInterface/Pages/Consent/Index.cshtml.cs @@ -57,73 +57,94 @@ public async Task OnGet(string returnUrl) public async Task OnPost() { - // validate return url is still valid var request = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl); - if (request == null) return RedirectToPage("/Home/Error/Index"); + if (request == null) + return RedirectToPage("/Home/Error/Index"); - ConsentResponse grantedConsent = null; + var consent = await HandleConsentAsync(request); + if (consent == null) + { + View = await BuildViewModelAsync(Input.ReturnUrl, Input); + return Page(); + } - // user clicked 'no' - send back the standard 'access_denied' response - if (Input?.Button == "no") + await _interaction.GrantConsentAsync(request, consent); + + return request.IsNativeClient() + ? this.LoadingPage(Input.ReturnUrl) + : Redirect(Input.ReturnUrl); + } + + private async Task HandleConsentAsync(AuthorizationRequest request) + { + return Input?.Button switch { - grantedConsent = new ConsentResponse { Error = AuthorizationError.AccessDenied }; + "no" => await DenyConsentAsync(request), + "yes" => await GrantConsentAsync(request), + _ => InvalidSelection() + }; + } - // emit event - await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues)); - } - // user clicked 'yes' - validate the data - else if (Input?.Button == "yes") + private async Task DenyConsentAsync(AuthorizationRequest request) + { + await _events.RaiseAsync( + new ConsentDeniedEvent( + User.GetSubjectId(), + request.Client.ClientId, + request.ValidatedResources.RawScopeValues)); + + return new ConsentResponse { - // if the user consented to some scope, build the response model - if (Input.ScopesConsented != null && Input.ScopesConsented.Any()) - { - var scopes = Input.ScopesConsented; - if (ConsentOptions.EnableOfflineAccess == false) - { - scopes = scopes.Where(x => x != Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess); - } - - grantedConsent = new ConsentResponse - { - RememberConsent = Input.RememberConsent, - ScopesValuesConsented = scopes.ToArray(), - Description = Input.Description - }; - - // emit event - await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.Client.ClientId, request.ValidatedResources.RawScopeValues, grantedConsent.ScopesValuesConsented, grantedConsent.RememberConsent)); - } - else - { - ModelState.AddModelError("", ConsentOptions.MustChooseOneErrorMessage); - } - } - else + Error = AuthorizationError.AccessDenied + }; + } + + private async Task GrantConsentAsync(AuthorizationRequest request) + { + if (Input.ScopesConsented == null || !Input.ScopesConsented.Any()) { - ModelState.AddModelError("", ConsentOptions.InvalidSelectionErrorMessage); + ModelState.AddModelError("", ConsentOptions.MustChooseOneErrorMessage); + return null; } - if (grantedConsent != null) + var scopes = FilterScopes(Input.ScopesConsented); + + var consent = new ConsentResponse { - // communicate outcome of consent back to identityserver - await _interaction.GrantConsentAsync(request, grantedConsent); + RememberConsent = Input.RememberConsent, + ScopesValuesConsented = scopes, + Description = Input.Description + }; - // redirect back to authorization endpoint - if (request.IsNativeClient() == true) - { - // The client is native, so this change in how to - // return the response is for better UX for the end user. - return this.LoadingPage(Input.ReturnUrl); - } + await _events.RaiseAsync( + new ConsentGrantedEvent( + User.GetSubjectId(), + request.Client.ClientId, + request.ValidatedResources.RawScopeValues, + consent.ScopesValuesConsented, + consent.RememberConsent)); - return Redirect(Input.ReturnUrl); + return consent; + } + + private string[] FilterScopes(IEnumerable scopes) + { + if (!ConsentOptions.EnableOfflineAccess) + { + scopes = scopes.Where(x => + x != Duende.IdentityServer.IdentityServerConstants.StandardScopes.OfflineAccess); } - // we need to redisplay the consent UI - View = await BuildViewModelAsync(Input.ReturnUrl, Input); - return Page(); + return scopes.ToArray(); + } + + private ConsentResponse? InvalidSelection() + { + ModelState.AddModelError("", ConsentOptions.InvalidSelectionErrorMessage); + return null; } + private async Task BuildViewModelAsync(string returnUrl, InputModel model = null) { var request = await _interaction.GetAuthorizationContextAsync(returnUrl);