Skip to content

Instantly share code, notes, and snippets.

@aggieben
Created February 18, 2017 21:35
Show Gist options
  • Save aggieben/df9a18d4fc0863298ad45ba22d4d29f9 to your computer and use it in GitHub Desktop.
Save aggieben/df9a18d4fc0863298ad45ba22d4d29f9 to your computer and use it in GitHub Desktop.
A consent controller with business logic
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using IdentityServer4.Services;
using IdentityServer4.Stores;
using IdentityServer4.Models;
namespace MyProject.Web
{
[Authorize]
[Route("consent")]
public class ConsentController : Controller
{
private readonly ILogger _logger;
private readonly IIdentityServerInteractionService _identityService;
private readonly IClientStore _clientStore;
private readonly IResourceStore _resourceStore;
public ConsentController(ILogger<ConsentController> logger,
IIdentityServerInteractionService identityService,
IClientStore clientStore,
IResourceStore resourceStore)
{
_logger = logger;
_identityService = identityService;
_clientStore = clientStore;
_resourceStore = resourceStore;
}
public async Task<IActionResult> Index(string returnUrl)
{
var vm = await BuildViewModelAsync(returnUrl);
if (vm != null)
return View("Error");
return View(vm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Index(ConsentInputModel model)
{
if (model == null || !ModelState.IsValid)
{
return View(model);
}
var request = await _identityService.GetAuthorizationContextAsync(model.ReturnUrl);
ConsentResponse response = null;
// the button values here are specific to the controls on my consent form - you just need to collect whatever input you need
// to make a decision about consent.
if (model.Button == "no")
{
response = ConsentResponse.Denied;
}
else if (model.Button == "yes" && model.HasValue())
{
if (model.ResourcesConsented.HasValue())
{
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.HasValue())
{
await _identityService.GrantConsentAsync(request, response);
return Redirect(model.ReturnUrl);
}
var vm = await BuildViewModelAsync(model.ReturnUrl, model);
if (vm != null)
return View(vm);
throw new Exception("Unknown error occurred during consent.");
}
private async Task<ConsentViewModel> BuildViewModelAsync(string returnUrl, ConsentInputModel model = null)
{
var request = await _identityService.GetAuthorizationContextAsync(returnUrl);
if (request == null)
{
_logger.LogError("No consent request matching request: {0}", returnUrl);
return null;
}
var client = await _clientStore.FindEnabledClientByIdAsync(request.ClientId);
if (client == null)
{
_logger.LogError("Invalid client id: {0}", request.ClientId);
return null;
}
var resources = await _resourceStore.FindEnabledResourcesByScopeAsync(request.ScopesRequested);
if (resources == null || (!resources.ApiResources.Any() && resources.IdentityResources.Any()))
{
_logger.LogError("No resources in scopes: {0}", request.ScopesRequested);
return null;
}
return new ConsentViewModel(model, returnUrl, request, client, resources);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment