Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 72 additions & 51 deletions SecurityService.UserInterface/Pages/Consent/Index.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,73 +57,94 @@ public async Task<IActionResult> OnGet(string returnUrl)

public async Task<IActionResult> 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<ConsentResponse?> 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<ConsentResponse> 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<ConsentResponse?> 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<string> 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<ViewModel> BuildViewModelAsync(string returnUrl, InputModel model = null)
{
var request = await _interaction.GetAuthorizationContextAsync(returnUrl);
Expand Down
Loading