/* * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) * See https://github.com/openiddict/openiddict-core for more information concerning * the license and the contributors participating to this project. */ using System; using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; using BTCPayServer.Security.OpenId; using BTCPayServer.Data; using BTCPayServer.Models; using BTCPayServer.Models.Authorization; using BTCPayServer.Security; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Microsoft.AspNetCore; using OpenIddict.Abstractions; using OpenIddict.Core; using OpenIddict.Server; using System.Security.Claims; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using OpenIddict.Server.AspNetCore; namespace BTCPayServer.Controllers { public class AuthorizationController : Controller { private readonly OpenIddictApplicationManager _applicationManager; private readonly SignInManager _signInManager; private readonly OpenIddictAuthorizationManager _authorizationManager; private readonly UserManager _userManager; private readonly IOptions _IdentityOptions; public AuthorizationController( OpenIddictApplicationManager applicationManager, SignInManager signInManager, OpenIddictAuthorizationManager authorizationManager, UserManager userManager, IOptions identityOptions) { _applicationManager = applicationManager; _signInManager = signInManager; _authorizationManager = authorizationManager; _userManager = userManager; _IdentityOptions = identityOptions; } [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] [HttpGet("/connect/authorize")] public async Task Authorize() { var request = HttpContext.GetOpenIddictServerRequest(); // Retrieve the application details from the database. var application = await _applicationManager.FindByClientIdAsync(request.ClientId); if (application == null) { return View("Error", new ErrorViewModel { Error = OpenIddictConstants.Errors.InvalidClient, ErrorDescription = "Details concerning the calling client application cannot be found in the database" }); } var userId = _userManager.GetUserId(User); if (!string.IsNullOrEmpty( await OpenIdExtensions.IsUserAuthorized(_authorizationManager, request, userId, application.Id))) { return await Authorize("YES", false); } // Flow the request_id to allow OpenIddict to restore // the original authorization request from the cache. return View(new AuthorizeViewModel { ApplicationName = await _applicationManager.GetDisplayNameAsync(application), RequestId = request.RequestId, Scope = request.GetScopes() }); } [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] [HttpPost("/connect/authorize")] public async Task Authorize(string consent, bool createAuthorization = true) { var request = HttpContext.GetOpenIddictServerRequest(); var user = await _userManager.GetUserAsync(User); if (user == null) { return View("Error", new ErrorViewModel { Error = OpenIddictConstants.Errors.ServerError, ErrorDescription = "The specified user could not be found" }); } string type = null; switch (consent.ToUpperInvariant()) { case "YESTEMPORARY": type = OpenIddictConstants.AuthorizationTypes.AdHoc; break; case "YES": type = OpenIddictConstants.AuthorizationTypes.Permanent; break; case "NO": default: // Notify OpenIddict that the authorization grant has been denied by the resource owner // to redirect the user agent to the client application using the appropriate response_mode. return Forbid(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); } var principal = await _signInManager.CreateUserPrincipalAsync(user); principal = await _signInManager.CreateUserPrincipalAsync(user); principal.SetScopes(request.GetScopes().Restrict(principal)); principal.SetDestinations(_IdentityOptions.Value); if (createAuthorization) { var application = await _applicationManager.FindByClientIdAsync(request.ClientId); var authorization = await _authorizationManager.CreateAsync(User, user.Id, application.Id, type, principal.GetScopes().ToImmutableArray()); principal.SetInternalAuthorizationId(authorization.Id); } // Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens. return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); } } }