2016-11-24 15:31:33 +01:00
|
|
|
|
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
|
|
|
|
|
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using IdentityServer4.Services;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using IdentityServer4.Models;
|
|
|
|
|
using IdentityServer4.Stores;
|
|
|
|
|
using IdentityServer4.Quickstart.UI.Models;
|
2017-01-30 11:35:16 +01:00
|
|
|
|
using Identity.API.Models.AccountViewModels;
|
|
|
|
|
using Identity.API.Services;
|
2016-11-24 15:31:33 +01:00
|
|
|
|
|
|
|
|
|
namespace IdentityServer4.Quickstart.UI.Controllers
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// This controller implements the consent logic
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class ConsentController : Controller
|
|
|
|
|
{
|
|
|
|
|
private readonly ILogger<ConsentController> _logger;
|
|
|
|
|
private readonly IClientStore _clientStore;
|
2017-04-05 09:18:14 -03:00
|
|
|
|
private readonly IResourceStore _resourceStore;
|
2016-11-24 15:31:33 +01:00
|
|
|
|
private readonly IIdentityServerInteractionService _interaction;
|
2016-12-29 16:26:02 +01:00
|
|
|
|
|
2016-11-24 15:31:33 +01:00
|
|
|
|
|
|
|
|
|
public ConsentController(
|
|
|
|
|
ILogger<ConsentController> logger,
|
|
|
|
|
IIdentityServerInteractionService interaction,
|
|
|
|
|
IClientStore clientStore,
|
2017-04-05 09:18:14 -03:00
|
|
|
|
IResourceStore resourceStore)
|
2016-11-24 15:31:33 +01:00
|
|
|
|
{
|
|
|
|
|
_logger = logger;
|
|
|
|
|
_interaction = interaction;
|
|
|
|
|
_clientStore = clientStore;
|
2017-04-05 09:18:14 -03:00
|
|
|
|
_resourceStore = resourceStore;
|
2016-11-24 15:31:33 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Shows the consent screen
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="returnUrl"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpGet]
|
|
|
|
|
public async Task<IActionResult> Index(string returnUrl)
|
|
|
|
|
{
|
|
|
|
|
var vm = await BuildViewModelAsync(returnUrl);
|
2016-12-29 16:26:02 +01:00
|
|
|
|
ViewData["ReturnUrl"] = returnUrl;
|
2016-11-24 15:31:33 +01:00
|
|
|
|
if (vm != null)
|
|
|
|
|
{
|
|
|
|
|
return View("Index", vm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return View("Error");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Handles the consent screen postback
|
|
|
|
|
/// </summary>
|
|
|
|
|
[HttpPost]
|
|
|
|
|
[ValidateAntiForgeryToken]
|
|
|
|
|
public async Task<IActionResult> Index(ConsentInputModel model)
|
|
|
|
|
{
|
|
|
|
|
// parse the return URL back to an AuthorizeRequest object
|
|
|
|
|
var request = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);
|
|
|
|
|
ConsentResponse response = null;
|
|
|
|
|
|
|
|
|
|
// user clicked 'no' - send back the standard 'access_denied' response
|
|
|
|
|
if (model.Button == "no")
|
|
|
|
|
{
|
|
|
|
|
response = ConsentResponse.Denied;
|
|
|
|
|
}
|
|
|
|
|
// user clicked 'yes' - validate the data
|
|
|
|
|
else if (model.Button == "yes" && model != null)
|
|
|
|
|
{
|
|
|
|
|
// if the user consented to some scope, build the response model
|
|
|
|
|
if (model.ScopesConsented != null && model.ScopesConsented.Any())
|
|
|
|
|
{
|
|
|
|
|
response = new ConsentResponse
|
|
|
|
|
{
|
|
|
|
|
RememberConsent = model.RememberConsent,
|
|
|
|
|
ScopesConsented = model.ScopesConsented
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ModelState.AddModelError("", "You must pick at least one permission.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ModelState.AddModelError("", "Invalid Selection");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (response != null)
|
|
|
|
|
{
|
|
|
|
|
// communicate outcome of consent back to identityserver
|
|
|
|
|
await _interaction.GrantConsentAsync(request, response);
|
|
|
|
|
|
|
|
|
|
// redirect back to authorization endpoint
|
|
|
|
|
return Redirect(model.ReturnUrl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var vm = await BuildViewModelAsync(model.ReturnUrl, model);
|
|
|
|
|
if (vm != null)
|
|
|
|
|
{
|
|
|
|
|
return View("Index", vm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return View("Error");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async Task<ConsentViewModel> BuildViewModelAsync(string returnUrl, ConsentInputModel model = null)
|
|
|
|
|
{
|
|
|
|
|
var request = await _interaction.GetAuthorizationContextAsync(returnUrl);
|
|
|
|
|
if (request != null)
|
|
|
|
|
{
|
|
|
|
|
var client = await _clientStore.FindEnabledClientByIdAsync(request.ClientId);
|
|
|
|
|
if (client != null)
|
|
|
|
|
{
|
2017-04-05 09:18:14 -03:00
|
|
|
|
var resources = await _resourceStore.FindEnabledResourcesByScopeAsync(request.ScopesRequested);
|
|
|
|
|
if (resources != null && (resources.IdentityResources.Any() || resources.ApiResources.Any()))
|
2016-11-24 15:31:33 +01:00
|
|
|
|
{
|
2017-04-05 09:18:14 -03:00
|
|
|
|
return new ConsentViewModel(model, returnUrl, request, client, resources);
|
2016-11-24 15:31:33 +01:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError("No scopes matching: {0}", request.ScopesRequested.Aggregate((x, y) => x + ", " + y));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError("Invalid client id: {0}", request.ClientId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError("No consent request matching request: {0}", returnUrl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|