2019-08-29 09:25:16 +02:00
|
|
|
|
/*
|
|
|
|
|
* 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;
|
2019-10-18 14:36:32 +02:00
|
|
|
|
using BTCPayServer.Security.OpenId;
|
2019-08-29 17:24:42 +02:00
|
|
|
|
using BTCPayServer.Data;
|
2019-08-29 09:25:16 +02:00
|
|
|
|
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;
|
2019-10-08 08:21:30 +02:00
|
|
|
|
using Microsoft.AspNetCore;
|
2019-08-29 09:25:16 +02:00
|
|
|
|
using OpenIddict.Abstractions;
|
|
|
|
|
using OpenIddict.Core;
|
|
|
|
|
using OpenIddict.Server;
|
2019-10-04 10:21:53 +02:00
|
|
|
|
using System.Security.Claims;
|
|
|
|
|
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
2019-10-08 08:21:30 +02:00
|
|
|
|
using OpenIddict.Server.AspNetCore;
|
2019-08-29 09:25:16 +02:00
|
|
|
|
|
|
|
|
|
namespace BTCPayServer.Controllers
|
|
|
|
|
{
|
|
|
|
|
public class AuthorizationController : Controller
|
|
|
|
|
{
|
|
|
|
|
private readonly OpenIddictApplicationManager<BTCPayOpenIdClient> _applicationManager;
|
|
|
|
|
private readonly SignInManager<ApplicationUser> _signInManager;
|
|
|
|
|
private readonly OpenIddictAuthorizationManager<BTCPayOpenIdAuthorization> _authorizationManager;
|
|
|
|
|
private readonly UserManager<ApplicationUser> _userManager;
|
|
|
|
|
private readonly IOptions<IdentityOptions> _IdentityOptions;
|
|
|
|
|
|
|
|
|
|
public AuthorizationController(
|
|
|
|
|
OpenIddictApplicationManager<BTCPayOpenIdClient> applicationManager,
|
|
|
|
|
SignInManager<ApplicationUser> signInManager,
|
|
|
|
|
OpenIddictAuthorizationManager<BTCPayOpenIdAuthorization> authorizationManager,
|
|
|
|
|
UserManager<ApplicationUser> userManager,
|
|
|
|
|
IOptions<IdentityOptions> identityOptions)
|
|
|
|
|
{
|
|
|
|
|
_applicationManager = applicationManager;
|
|
|
|
|
_signInManager = signInManager;
|
|
|
|
|
_authorizationManager = authorizationManager;
|
|
|
|
|
_userManager = userManager;
|
|
|
|
|
_IdentityOptions = identityOptions;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-12 13:35:30 +02:00
|
|
|
|
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
2019-08-29 09:25:16 +02:00
|
|
|
|
[HttpGet("/connect/authorize")]
|
2019-10-08 08:21:30 +02:00
|
|
|
|
public async Task<IActionResult> Authorize()
|
2019-08-29 09:25:16 +02:00
|
|
|
|
{
|
2019-10-08 08:21:30 +02:00
|
|
|
|
var request = HttpContext.GetOpenIddictServerRequest();
|
2019-08-29 09:25:16 +02:00
|
|
|
|
// Retrieve the application details from the database.
|
2019-10-08 08:21:30 +02:00
|
|
|
|
var application = await _applicationManager.FindByClientIdAsync(request.ClientId);
|
2019-08-29 09:25:16 +02:00
|
|
|
|
|
|
|
|
|
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(
|
2019-10-08 08:21:30 +02:00
|
|
|
|
await OpenIdExtensions.IsUserAuthorized(_authorizationManager, request, userId, application.Id)))
|
2019-08-29 09:25:16 +02:00
|
|
|
|
{
|
2019-10-08 08:21:30 +02:00
|
|
|
|
return await Authorize("YES", false);
|
2019-08-29 09:25:16 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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),
|
2019-10-08 08:21:30 +02:00
|
|
|
|
RequestId = request.RequestId,
|
|
|
|
|
Scope = request.GetScopes()
|
2019-08-29 09:25:16 +02:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-12 13:35:30 +02:00
|
|
|
|
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
2019-08-29 09:25:16 +02:00
|
|
|
|
[HttpPost("/connect/authorize")]
|
2019-10-08 08:21:30 +02:00
|
|
|
|
public async Task<IActionResult> Authorize(string consent, bool createAuthorization = true)
|
2019-08-29 09:25:16 +02:00
|
|
|
|
{
|
2019-10-08 08:21:30 +02:00
|
|
|
|
var request = HttpContext.GetOpenIddictServerRequest();
|
2019-08-29 09:25:16 +02:00
|
|
|
|
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.
|
2019-10-08 08:21:30 +02:00
|
|
|
|
return Forbid(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
|
2019-08-29 09:25:16 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2019-10-08 08:21:30 +02:00
|
|
|
|
var principal = await _signInManager.CreateUserPrincipalAsync(user);
|
|
|
|
|
principal = await _signInManager.CreateUserPrincipalAsync(user);
|
|
|
|
|
principal.SetScopes(request.GetScopes().Restrict(principal));
|
|
|
|
|
principal.SetDestinations(_IdentityOptions.Value);
|
2019-08-29 09:25:16 +02:00
|
|
|
|
if (createAuthorization)
|
|
|
|
|
{
|
2019-10-08 08:21:30 +02:00
|
|
|
|
var application = await _applicationManager.FindByClientIdAsync(request.ClientId);
|
2019-08-29 09:25:16 +02:00
|
|
|
|
var authorization = await _authorizationManager.CreateAsync(User, user.Id, application.Id,
|
2019-10-08 08:21:30 +02:00
|
|
|
|
type, principal.GetScopes().ToImmutableArray());
|
|
|
|
|
principal.SetInternalAuthorizationId(authorization.Id);
|
2019-08-29 09:25:16 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens.
|
2019-10-08 08:21:30 +02:00
|
|
|
|
return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
|
2019-08-29 09:25:16 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|