Update to OpenIddict3.0

This commit is contained in:
nicolas.dorier 2019-10-08 15:21:30 +09:00
parent d56a5ad86e
commit 3c9b58916b
No known key found for this signature in database
GPG Key ID: 6618763EF09186FE
29 changed files with 220 additions and 337 deletions

View File

@ -6,14 +6,14 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.4" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.1.2" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.1.2" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="2.0.0" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="3.0.0-alpha1.19515.63" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp2.1'">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.0.1" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.0.0-rc1.final" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="3.0.0-alpha1.19509.59" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="3.0.0-alpha1.19515.63" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0" />
</ItemGroup>
</Project>

View File

@ -4,16 +4,9 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
#if NETCOREAPP21
using OpenIddictRequest = AspNet.Security.OpenIdConnect.Primitives.OpenIdConnectRequest;
using OpenIddictResponse = AspNet.Security.OpenIdConnect.Primitives.OpenIdConnectResponse;
using OpenIdConnectDefaults = OpenIddict.Server.OpenIddictServerDefaults;
using AspNet.Security.OpenIdConnect.Primitives;
#else
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
#endif
using BTCPayServer.Tests.Logging;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Xunit;
using Xunit.Abstractions;
@ -31,7 +24,7 @@ namespace BTCPayServer.Tests
{
public class AuthenticationTests
{
public const int TestTimeout = 60_000;
public const int TestTimeout = TestUtils.TestTimeout;
public AuthenticationTests(ITestOutputHelper helper)
{
Logs.Tester = new XUnitLog(helper) {Name = "Tests"};
@ -112,6 +105,7 @@ namespace BTCPayServer.Tests
var user = tester.NewAccount();
user.GrantAccess();
await user.MakeAdmin();
var id = Guid.NewGuid().ToString();
var redirecturi = new Uri("http://127.0.0.1/oidc-callback");
var openIdClient = await user.RegisterOpenIdClient(
@ -124,7 +118,7 @@ namespace BTCPayServer.Tests
});
var implicitAuthorizeUrl = new Uri(tester.PayTester.ServerUri,
$"connect/authorize?response_type=token&client_id={id}&redirect_uri={redirecturi.AbsoluteUri}&scope=openid&nonce={Guid.NewGuid().ToString()}");
$"connect/authorize?response_type=token&client_id={id}&redirect_uri={redirecturi.AbsoluteUri}&scope=openid server_management store_management&nonce={Guid.NewGuid().ToString()}");
s.Driver.Navigate().GoToUrl(implicitAuthorizeUrl);
s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password);
s.Driver.FindElement(By.Id("consent-yes")).Click();
@ -225,7 +219,7 @@ namespace BTCPayServer.Tests
RedirectUris = {redirecturi}
}, secret);
var authorizeUrl = new Uri(tester.PayTester.ServerUri,
$"connect/authorize?response_type=code&client_id={id}&redirect_uri={redirecturi.AbsoluteUri}&scope=openid offline_access&state={Guid.NewGuid().ToString()}");
$"connect/authorize?response_type=code&client_id={id}&redirect_uri={redirecturi.AbsoluteUri}&scope=openid offline_access server_management store_management&state={Guid.NewGuid().ToString()}");
s.Driver.Navigate().GoToUrl(authorizeUrl);
s.Login(user.RegisterDetails.Email, user.RegisterDetails.Password);
s.Driver.FindElement(By.Id("consent-yes")).Click();
@ -325,7 +319,8 @@ namespace BTCPayServer.Tests
new KeyValuePair<string, string>("grant_type",
OpenIddictConstants.GrantTypes.ClientCredentials),
new KeyValuePair<string, string>("client_id", openIdClient.ClientId),
new KeyValuePair<string, string>("client_secret", secret)
new KeyValuePair<string, string>("client_secret", secret),
new KeyValuePair<string, string>("scope", "server_management store_management")
})
};
@ -365,7 +360,8 @@ namespace BTCPayServer.Tests
new KeyValuePair<string, string>("username", user.RegisterDetails.Email),
new KeyValuePair<string, string>("password", user.RegisterDetails.Password),
new KeyValuePair<string, string>("client_id", openIdClient.ClientId),
new KeyValuePair<string, string>("client_secret", secret)
new KeyValuePair<string, string>("client_secret", secret),
new KeyValuePair<string, string>("scope", "server_management store_management")
})
};

View File

@ -32,11 +32,7 @@ using System.Security.Claims;
using System.Security.Principal;
using System.Text;
using System.Threading;
#if NETCOREAPP21
using AspNet.Security.OpenIdConnect.Primitives;
#else
using OpenIdConnectConstants = OpenIddict.Abstractions.OpenIddictConstants;
#endif
using OpenIddict.Abstractions;
using Xunit;
using BTCPayServer.Services;
using System.Net.Http;
@ -305,7 +301,7 @@ namespace BTCPayServer.Tests
if (userId != null)
{
List<Claim> claims = new List<Claim>();
claims.Add(new Claim(OpenIdConnectConstants.Claims.Subject, userId));
claims.Add(new Claim(OpenIddictConstants.Claims.Subject, userId));
if (isAdmin)
claims.Add(new Claim(ClaimTypes.Role, Roles.ServerAdmin));
context.User = new ClaimsPrincipal(new ClaimsIdentity(claims.ToArray(), AuthenticationSchemes.Cookie));

View File

@ -5,10 +5,12 @@ ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8
WORKDIR /source
COPY nuget.config nuget.config
COPY Build/Common.csproj Build/Common.csproj
COPY BTCPayServer/BTCPayServer.csproj BTCPayServer/BTCPayServer.csproj
COPY BTCPayServer.Common/BTCPayServer.Common.csproj BTCPayServer.Common/BTCPayServer.Common.csproj
COPY BTCPayServer.Rating/BTCPayServer.Rating.csproj BTCPayServer.Rating/BTCPayServer.Rating.csproj
COPY BTCPayServer.Data/BTCPayServer.Data.csproj BTCPayServer.Data/BTCPayServer.Data.csproj
COPY BTCPayServer.Tests/BTCPayServer.Tests.csproj BTCPayServer.Tests/BTCPayServer.Tests.csproj
RUN dotnet restore BTCPayServer.Tests/BTCPayServer.Tests.csproj

View File

@ -15,6 +15,11 @@ namespace BTCPayServer.Tests
{
public static class TestUtils
{
#if DEBUG
public const int TestTimeout = 600_000;
#else
public const int TestTimeout = 60_000;
#endif
public static DirectoryInfo TryGetSolutionDirectoryInfo(string currentPath = null)
{
var directory = new DirectoryInfo(

View File

@ -30,6 +30,7 @@ namespace BTCPayServer.Authentication
//create and manage apps
public const string AppManagement = "app_management";
public const string WalletManagement = "wallet_management";
public const string ServerManagement = "server_management";
}
public const string CanViewStores = nameof(CanViewStores);

View File

@ -1,27 +0,0 @@
using AspNet.Security.OpenIdConnect.Primitives;
using BTCPayServer.Data;
using BTCPayServer.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using OpenIddict.Core;
namespace BTCPayServer.Authentication.OpenId
{
public class AuthorizationCodeGrantTypeEventHandler : OpenIdGrantHandlerCheckCanSignIn
{
public AuthorizationCodeGrantTypeEventHandler(
OpenIddictApplicationManager<BTCPayOpenIdClient> applicationManager,
OpenIddictAuthorizationManager<BTCPayOpenIdAuthorization> authorizationManager,
SignInManager<ApplicationUser> signInManager,
IOptions<IdentityOptions> identityOptions,
UserManager<ApplicationUser> userManager) : base(applicationManager, authorizationManager, signInManager,
identityOptions, userManager)
{
}
protected override bool IsValid(OpenIdConnectRequest request)
{
return request.IsAuthorizationCodeGrantType();
}
}
}

View File

@ -1,5 +1,5 @@
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Primitives;
using OpenIdConnectRequest = OpenIddict.Abstractions.OpenIddictRequest;
using BTCPayServer.Data;
using BTCPayServer.Models;
using Microsoft.AspNetCore.Authentication;
@ -7,11 +7,13 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using OpenIddict.Core;
using OpenIddict.Server;
using System.Security.Claims;
namespace BTCPayServer.Authentication.OpenId
{
public abstract class BaseOpenIdGrantHandler<T> : IOpenIddictServerEventHandler<T>
where T : class, IOpenIddictServerEvent
public abstract class BaseOpenIdGrantHandler<T> :
IOpenIddictServerHandler<T>
where T : OpenIddictServerEvents.BaseContext
{
private readonly OpenIddictApplicationManager<BTCPayOpenIdClient> _applicationManager;
private readonly OpenIddictAuthorizationManager<BTCPayOpenIdAuthorization> _authorizationManager;
@ -31,14 +33,11 @@ namespace BTCPayServer.Authentication.OpenId
}
protected async Task<AuthenticationTicket> CreateTicketAsync(
OpenIdConnectRequest request, ApplicationUser user,
AuthenticationProperties properties = null)
protected Task<ClaimsPrincipal> CreateClaimsPrincipalAsync(OpenIdConnectRequest request, ApplicationUser user)
{
return await OpenIdExtensions.CreateAuthenticationTicket(_applicationManager, _authorizationManager,
_identityOptions.Value, _signInManager, request, user, properties);
return OpenIdExtensions.CreateClaimsPrincipalAsync(_applicationManager, _authorizationManager,
_identityOptions.Value, _signInManager, request, user);
}
public abstract Task<OpenIddictServerEventState> HandleAsync(T notification);
public abstract ValueTask HandleAsync(T notification);
}
}

View File

@ -1,7 +1,5 @@
using System.Security.Claims;
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Extensions;
using AspNet.Security.OpenIdConnect.Primitives;
using BTCPayServer.Data;
using BTCPayServer.Models;
using Microsoft.AspNetCore.Authentication;
@ -14,9 +12,13 @@ using OpenIddict.Server;
namespace BTCPayServer.Authentication.OpenId
{
public class
ClientCredentialsGrantTypeEventHandler : BaseOpenIdGrantHandler<OpenIddictServerEvents.HandleTokenRequest>
public class ClientCredentialsGrantTypeEventHandler :
BaseOpenIdGrantHandler<OpenIddictServerEvents.HandleTokenRequestContext>
{
public static OpenIddictServerHandlerDescriptor Descriptor { get; } =
OpenIddictServerHandlerDescriptor.CreateBuilder<OpenIddictServerEvents.HandleTokenRequestContext>()
.UseScopedHandler<ClientCredentialsGrantTypeEventHandler>()
.Build();
private readonly OpenIddictApplicationManager<BTCPayOpenIdClient> _applicationManager;
private readonly UserManager<ApplicationUser> _userManager;
@ -33,32 +35,28 @@ namespace BTCPayServer.Authentication.OpenId
_userManager = userManager;
}
public override async Task<OpenIddictServerEventState> HandleAsync(
OpenIddictServerEvents.HandleTokenRequest notification)
public override async ValueTask HandleAsync(
OpenIddictServerEvents.HandleTokenRequestContext notification)
{
var request = notification.Context.Request;
var request = notification.Request;
var context = notification;
if (!request.IsClientCredentialsGrantType())
{
// Allow other handlers to process the event.
return OpenIddictServerEventState.Unhandled;
return;
}
var application = await _applicationManager.FindByClientIdAsync(request.ClientId,
notification.Context.HttpContext.RequestAborted);
var application = await _applicationManager.FindByClientIdAsync(request.ClientId);
if (application == null)
{
notification.Context.Reject(
context.Reject(
error: OpenIddictConstants.Errors.InvalidClient,
description: "The client application was not found in the database.");
// Don't allow other handlers to process the event.
return OpenIddictServerEventState.Handled;
return;
}
var user = await _userManager.FindByIdAsync(application.ApplicationUserId);
notification.Context.Validate(await CreateTicketAsync(request, user));
// Don't allow other handlers to process the event.
return OpenIddictServerEventState.Handled;
context.Principal = await CreateClaimsPrincipalAsync(request, user);
notification.HandleAuthentication();
}
}
}

View File

@ -3,37 +3,33 @@ using System.Threading.Tasks;
using BTCPayServer.Data;
using BTCPayServer.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using OpenIddict.Core;
using OpenIddict.Server;
using Microsoft.AspNetCore;
using OpenIddict.Server.AspNetCore;
namespace BTCPayServer.Authentication.OpenId
{
public class LogoutEventHandler : BaseOpenIdGrantHandler<OpenIddictServerEvents.HandleLogoutRequest>
public class LogoutEventHandler : IOpenIddictServerHandler<OpenIddictServerEvents.HandleLogoutRequestContext>
{
public LogoutEventHandler(
OpenIddictApplicationManager<BTCPayOpenIdClient> applicationManager,
OpenIddictAuthorizationManager<BTCPayOpenIdAuthorization> authorizationManager,
SignInManager<ApplicationUser> signInManager, IOptions<IdentityOptions> identityOptions) : base(
applicationManager, authorizationManager,
signInManager, identityOptions)
protected readonly SignInManager<ApplicationUser> _signInManager;
public static OpenIddictServerHandlerDescriptor Descriptor { get; } =
OpenIddictServerHandlerDescriptor.CreateBuilder<OpenIddictServerEvents.HandleLogoutRequestContext>()
.UseScopedHandler<LogoutEventHandler>()
.Build();
public LogoutEventHandler(SignInManager<ApplicationUser> signInManager)
{
_signInManager = signInManager;
}
public override async Task<OpenIddictServerEventState> HandleAsync(
OpenIddictServerEvents.HandleLogoutRequest notification)
public async ValueTask HandleAsync(
OpenIddictServerEvents.HandleLogoutRequestContext notification)
{
// Ask ASP.NET Core Identity to delete the local and external cookies created
// when the user agent is redirected from the external identity provider
// after a successful authentication flow (e.g Google or Facebook).
await _signInManager.SignOutAsync();
// Returning a SignOutResult will ask OpenIddict to redirect the user agent
// to the post_logout_redirect_uri specified by the client application.
await notification.Context.HttpContext.SignOutAsync(OpenIddictServerDefaults.AuthenticationScheme);
notification.Context.HandleResponse();
return OpenIddictServerEventState.Handled;
}
}
}

View File

@ -1,10 +1,9 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Extensions;
using AspNet.Security.OpenIdConnect.Primitives;
using BTCPayServer.Data;
using BTCPayServer.Models;
using Microsoft.AspNetCore.Authentication;
@ -12,108 +11,80 @@ using Microsoft.AspNetCore.Identity;
using OpenIddict.Abstractions;
using OpenIddict.Core;
using OpenIddict.Server;
using static BTCPayServer.Authentication.RestAPIPolicies;
namespace BTCPayServer.Authentication.OpenId
{
public static class OpenIdExtensions
{
public static async Task<AuthenticationTicket> CreateAuthenticationTicket(
OpenIddictApplicationManager<BTCPayOpenIdClient> applicationManager,
public static ImmutableHashSet<string> Restrict(this ImmutableHashSet<string> scopes, ClaimsPrincipal claimsPrincipal)
{
HashSet<string> restricted = new HashSet<string>();
foreach (var scope in scopes)
{
if (scope == BTCPayScopes.ServerManagement && !claimsPrincipal.IsInRole(Roles.ServerAdmin))
continue;
restricted.Add(scope);
}
return restricted.ToImmutableHashSet();
}
public static async Task<ClaimsPrincipal> CreateClaimsPrincipalAsync(OpenIddictApplicationManager<BTCPayOpenIdClient> applicationManager,
OpenIddictAuthorizationManager<BTCPayOpenIdAuthorization> authorizationManager,
IdentityOptions identityOptions,
SignInManager<ApplicationUser> signInManager,
OpenIdConnectRequest request,
ApplicationUser user,
AuthenticationProperties properties = null)
OpenIddictRequest request,
ApplicationUser user)
{
var principal = await signInManager.CreateUserPrincipalAsync(user);
// Create a new authentication ticket holding the user identity.
var ticket = new AuthenticationTicket(principal, properties,
OpenIddictServerDefaults.AuthenticationScheme);
if (!request.IsAuthorizationCodeGrantType() && !request.IsRefreshTokenGrantType())
{
ticket.SetScopes(request.GetScopes());
principal.SetScopes(request.GetScopes().Restrict(principal));
}
else if (request.IsAuthorizationCodeGrantType() &&
string.IsNullOrEmpty(ticket.GetInternalAuthorizationId()))
string.IsNullOrEmpty(principal.GetInternalAuthorizationId()))
{
var app = await applicationManager.FindByClientIdAsync(request.ClientId);
var authorizationId = await IsUserAuthorized(authorizationManager, request, user.Id, app.Id);
if (!string.IsNullOrEmpty(authorizationId))
{
ticket.SetInternalAuthorizationId(authorizationId);
principal.SetInternalAuthorizationId(authorizationId);
}
}
foreach (var claim in ticket.Principal.Claims)
{
claim.SetDestinations(GetDestinations(identityOptions, claim, ticket));
}
principal.SetDestinations(identityOptions);
return principal;
}
return ticket;
public static void SetDestinations(this ClaimsPrincipal principal, IdentityOptions identityOptions)
{
foreach (var claim in principal.Claims)
{
claim.SetDestinations(GetDestinations(identityOptions, claim, principal));
}
}
private static IEnumerable<string> GetDestinations(IdentityOptions identityOptions, Claim claim,
AuthenticationTicket ticket)
ClaimsPrincipal principal)
{
// Note: by default, claims are NOT automatically included in the access and identity tokens.
// To allow OpenIddict to serialize them, you must attach them a destination, that specifies
// whether they should be included in access tokens, in identity tokens or in both.
switch (claim.Type)
{
case OpenIddictConstants.Claims.Name:
yield return OpenIddictConstants.Destinations.AccessToken;
if (ticket.HasScope(OpenIddictConstants.Scopes.Profile))
yield return OpenIddictConstants.Destinations.IdentityToken;
yield break;
case OpenIddictConstants.Claims.Email:
yield return OpenIddictConstants.Destinations.AccessToken;
if (ticket.HasScope(OpenIddictConstants.Scopes.Email))
yield return OpenIddictConstants.Destinations.IdentityToken;
yield break;
case OpenIddictConstants.Claims.Role:
yield return OpenIddictConstants.Destinations.AccessToken;
if (ticket.HasScope(OpenIddictConstants.Scopes.Roles))
yield return OpenIddictConstants.Destinations.IdentityToken;
yield break;
default:
if (claim.Type == identityOptions.ClaimsIdentity.SecurityStampClaimType)
{
// Never include the security stamp in the access and identity tokens, as it's a secret value.
yield break;
}
else
{
yield return OpenIddictConstants.Destinations.AccessToken;
yield break;
}
}
}
public static async Task<string> IsUserAuthorized(
OpenIddictAuthorizationManager<BTCPayOpenIdAuthorization> authorizationManager,
OpenIdConnectRequest request, string userId, string applicationId)
OpenIddictRequest request, string userId, string applicationId)
{
var authorizations =
await authorizationManager.ListAsync(queryable =>
var authorizations = await authorizationManager.ListAsync(queryable =>
queryable.Where(authorization =>
authorization.Subject.Equals(userId, StringComparison.OrdinalIgnoreCase) &&
applicationId.Equals(authorization.Application.Id, StringComparison.OrdinalIgnoreCase) &&
authorization.Status.Equals(OpenIddictConstants.Statuses.Valid,
StringComparison.OrdinalIgnoreCase)));
StringComparison.OrdinalIgnoreCase))).ToArrayAsync();
if (authorizations.Length > 0)
{

View File

@ -1,22 +1,29 @@
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Primitives;
using OpenIddict.Abstractions;
using BTCPayServer.Data;
using BTCPayServer.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using OpenIddict.Abstractions;
using OpenIddict.Core;
using OpenIddict.Server;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using OpenIddict.Server.AspNetCore;
namespace BTCPayServer.Authentication.OpenId
{
public abstract class
OpenIdGrantHandlerCheckCanSignIn : BaseOpenIdGrantHandler<OpenIddictServerEvents.HandleTokenRequest>
public class OpenIdGrantHandlerCheckCanSignIn :
BaseOpenIdGrantHandler<OpenIddictServerEvents.HandleTokenRequestContext>
{
public static OpenIddictServerHandlerDescriptor Descriptor { get; } =
OpenIddictServerHandlerDescriptor.CreateBuilder<OpenIddictServerEvents.HandleTokenRequestContext>()
.UseScopedHandler<OpenIdGrantHandlerCheckCanSignIn>()
.Build();
private readonly UserManager<ApplicationUser> _userManager;
protected OpenIdGrantHandlerCheckCanSignIn(
public OpenIdGrantHandlerCheckCanSignIn(
OpenIddictApplicationManager<BTCPayOpenIdClient> applicationManager,
OpenIddictAuthorizationManager<BTCPayOpenIdAuthorization> authorizationManager,
SignInManager<ApplicationUser> signInManager,
@ -27,44 +34,39 @@ namespace BTCPayServer.Authentication.OpenId
_userManager = userManager;
}
protected abstract bool IsValid(OpenIdConnectRequest request);
public override async Task<OpenIddictServerEventState> HandleAsync(
OpenIddictServerEvents.HandleTokenRequest notification)
public override async ValueTask HandleAsync(
OpenIddictServerEvents.HandleTokenRequestContext notification)
{
var request = notification.Context.Request;
if (!IsValid(request))
var request = notification.Request;
if (!request.IsRefreshTokenGrantType() && !request.IsAuthorizationCodeGrantType())
{
// Allow other handlers to process the event.
return OpenIddictServerEventState.Unhandled;
return;
}
var scheme = notification.Context.Scheme.Name;
var authenticateResult = (await notification.Context.HttpContext.AuthenticateAsync(scheme));
var httpContext = notification.Transaction.GetHttpRequest().HttpContext;
var authenticateResult = (await httpContext.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme));
var user = await _userManager.GetUserAsync(authenticateResult.Principal);
if (user == null)
{
notification.Context.Reject(
notification.Reject(
error: OpenIddictConstants.Errors.InvalidGrant,
description: "The token is no longer valid.");
// Don't allow other handlers to process the event.
return OpenIddictServerEventState.Handled;
return;
}
// Ensure the user is still allowed to sign in.
if (!await _signInManager.CanSignInAsync(user))
{
notification.Context.Reject(
notification.Reject(
error: OpenIddictConstants.Errors.InvalidGrant,
description: "The user is no longer allowed to sign in.");
// Don't allow other handlers to process the event.
return OpenIddictServerEventState.Handled;
return;
}
notification.Context.Validate(await CreateTicketAsync(request, user));
// Don't allow other handlers to process the event.
return OpenIddictServerEventState.Handled;
notification.Principal = await this.CreateClaimsPrincipalAsync(request, user);
notification.HandleAuthentication();
}
}
}

View File

@ -1,5 +1,5 @@
using System;
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Primitives;
using BTCPayServer.Data;
using BTCPayServer.Models;
using BTCPayServer.U2F;
@ -8,12 +8,14 @@ using Microsoft.Extensions.Options;
using OpenIddict.Abstractions;
using OpenIddict.Core;
using OpenIddict.Server;
using Microsoft.AspNetCore;
namespace BTCPayServer.Authentication.OpenId
{
public class PasswordGrantTypeEventHandler : BaseOpenIdGrantHandler<OpenIddictServerEvents.HandleTokenRequest>
public class PasswordGrantTypeEventHandler : BaseOpenIdGrantHandler<OpenIddictServerEvents.HandleTokenRequestContext>
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly NicolasDorier.RateLimits.RateLimitService _rateLimitService;
private readonly U2FService _u2FService;
public PasswordGrantTypeEventHandler(
@ -21,43 +23,44 @@ namespace BTCPayServer.Authentication.OpenId
OpenIddictAuthorizationManager<BTCPayOpenIdAuthorization> authorizationManager,
SignInManager<ApplicationUser> signInManager,
UserManager<ApplicationUser> userManager,
NicolasDorier.RateLimits.RateLimitService rateLimitService,
IOptions<IdentityOptions> identityOptions, U2FService u2FService) : base(applicationManager,
authorizationManager, signInManager, identityOptions)
{
_userManager = userManager;
_rateLimitService = rateLimitService;
_u2FService = u2FService;
}
public override async Task<OpenIddictServerEventState> HandleAsync(
OpenIddictServerEvents.HandleTokenRequest notification)
public static OpenIddictServerHandlerDescriptor Descriptor { get; } =
OpenIddictServerHandlerDescriptor.CreateBuilder<OpenIddictServerEvents.HandleTokenRequestContext>()
.UseScopedHandler<PasswordGrantTypeEventHandler>()
.Build();
public override async ValueTask HandleAsync(
OpenIddictServerEvents.HandleTokenRequestContext notification)
{
var request = notification.Context.Request;
var request = notification.Request;
if (!request.IsPasswordGrantType())
{
// Allow other handlers to process the event.
return OpenIddictServerEventState.Unhandled;
return;
}
// Validate the user credentials.
// Note: to mitigate brute force attacks, you SHOULD strongly consider
// applying a key derivation function like PBKDF2 to slow down
// the password validation process. You SHOULD also consider
// using a time-constant comparer to prevent timing attacks.
var httpContext = notification.Transaction.GetHttpRequest().HttpContext;
await _rateLimitService.Throttle(ZoneLimits.Login, httpContext.Connection.RemoteIpAddress.ToString(), httpContext.RequestAborted);
var user = await _userManager.FindByNameAsync(request.Username);
if (user == null || await _u2FService.HasDevices(user.Id) ||
!(await _signInManager.CheckPasswordSignInAsync(user, request.Password, lockoutOnFailure: true))
.Succeeded)
{
notification.Context.Reject(
notification.Reject(
error: OpenIddictConstants.Errors.InvalidGrant,
description: "The specified credentials are invalid.");
// Don't allow other handlers to process the event.
return OpenIddictServerEventState.Handled;
return;
}
notification.Context.Validate(await CreateTicketAsync(request, user));
// Don't allow other handlers to process the event.
return OpenIddictServerEventState.Handled;
notification.Principal = await CreateClaimsPrincipalAsync(request, user);
notification.HandleAuthentication();
}
}
}

View File

@ -1,27 +0,0 @@
using AspNet.Security.OpenIdConnect.Primitives;
using BTCPayServer.Data;
using BTCPayServer.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using OpenIddict.Core;
namespace BTCPayServer.Authentication.OpenId
{
public class RefreshTokenGrantTypeEventHandler : OpenIdGrantHandlerCheckCanSignIn
{
public RefreshTokenGrantTypeEventHandler(
OpenIddictApplicationManager<BTCPayOpenIdClient> applicationManager,
OpenIddictAuthorizationManager<BTCPayOpenIdAuthorization> authorizationManager,
SignInManager<ApplicationUser> signInManager,
IOptions<IdentityOptions> identityOptions, UserManager<ApplicationUser> userManager) : base(
applicationManager, authorizationManager, signInManager,
identityOptions, userManager)
{
}
protected override bool IsValid(OpenIdConnectRequest request)
{
return request.IsRefreshTokenGrantType();
}
}
}

View File

@ -6,9 +6,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Remove="Build\**" />
<Compile Remove="Authentication\OpenId\**" Condition="'$(TargetFramework)' != 'netcoreapp2.1'" />
<Compile Remove="Storage\Services\Providers\GoogleCloudStorage\**" Condition="'$(TargetFramework)' != 'netcoreapp2.1'" />
<Compile Remove="Authentication\OpenId3\**" Condition="'$(TargetFramework)' == 'netcoreapp2.1'" />
<Compile Remove="wwwroot\bundles\jqueryvalidate\**" />
<Compile Remove="wwwroot\css\**" />
<Compile Remove="wwwroot\vendor\jquery-nice-select\**" />
@ -51,7 +49,6 @@
<PackageReference Include="NicolasDorier.CommandLine.Configuration" Version="1.0.0.3" />
<PackageReference Include="NicolasDorier.RateLimits" Version="1.0.0.9" />
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="1.0.0.18" />
<PackageReference Include="OpenIddict" Version="2.0.0" Condition="'$(TargetFramework)' == 'netcoreapp2.1'" />
<PackageReference Include="Serilog" Version="2.7.1" />
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.0.0" />
@ -71,13 +68,14 @@
<PackageReference Include="TwentyTwenty.Storage.Local" Version="2.11.2" />
<PackageReference Include="U2F.Core" Version="1.0.4" />
<PackageReference Include="YamlDotNet" Version="5.2.1" />
<PackageReference Include="OpenIddict" Version="3.0.0-alpha1.19515.63" />
<PackageReference Include="OpenIddict.Server.AspNetCore" Version="3.0.0-alpha1.19515.63"></PackageReference>
<PackageReference Include="OpenIddict.Validation.AspNetCore" Version="3.0.0-alpha1.19515.63"></PackageReference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'netcoreapp2.1'">
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0"></PackageReference>
<PackageReference Include="OpenIddict" Version="3.0.0-alpha1.19503.62" />
<PackageReference Include="OpenIddict.Server.AspNetCore" Version="3.0.0-alpha1.19503.62"></PackageReference>
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.0.0" />
</ItemGroup>
@ -223,4 +221,4 @@
<Pack>$(IncludeRazorContentInPack)</Pack>
</Content>
</ItemGroup>
</Project>
</Project>

View File

@ -17,18 +17,13 @@ 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;
#if NETCOREAPP21
using OpenIddictRequest = AspNet.Security.OpenIdConnect.Primitives.OpenIdConnectRequest;
using OpenIdConnectDefaults = OpenIddict.Server.OpenIddictServerDefaults;
using AspNet.Security.OpenIdConnect.Extensions;
using AspNet.Security.OpenIdConnect.Primitives;
#else
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
#endif
using OpenIddict.Server.AspNetCore;
namespace BTCPayServer.Controllers
{
@ -56,10 +51,11 @@ namespace BTCPayServer.Controllers
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[HttpGet("/connect/authorize")]
public async Task<IActionResult> Authorize(OpenIddictRequest openIdConnectRequest)
public async Task<IActionResult> Authorize()
{
var request = HttpContext.GetOpenIddictServerRequest();
// Retrieve the application details from the database.
var application = await _applicationManager.FindByClientIdAsync(openIdConnectRequest.ClientId);
var application = await _applicationManager.FindByClientIdAsync(request.ClientId);
if (application == null)
{
@ -74,9 +70,9 @@ namespace BTCPayServer.Controllers
var userId = _userManager.GetUserId(User);
if (!string.IsNullOrEmpty(
await OpenIdExtensions.IsUserAuthorized(_authorizationManager, openIdConnectRequest, userId, application.Id)))
await OpenIdExtensions.IsUserAuthorized(_authorizationManager, request, userId, application.Id)))
{
return await Authorize(openIdConnectRequest, "YES", false);
return await Authorize("YES", false);
}
// Flow the request_id to allow OpenIddict to restore
@ -84,16 +80,16 @@ namespace BTCPayServer.Controllers
return View(new AuthorizeViewModel
{
ApplicationName = await _applicationManager.GetDisplayNameAsync(application),
RequestId = openIdConnectRequest.RequestId,
Scope = openIdConnectRequest.GetScopes()
RequestId = request.RequestId,
Scope = request.GetScopes()
});
}
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[HttpPost("/connect/authorize")]
public async Task<IActionResult> Authorize(OpenIddictRequest openIdConnectRequest,
string consent, bool createAuthorization = true)
public async Task<IActionResult> Authorize(string consent, bool createAuthorization = true)
{
var request = HttpContext.GetOpenIddictServerRequest();
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
@ -118,26 +114,24 @@ namespace BTCPayServer.Controllers
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(OpenIdConnectDefaults.AuthenticationScheme);
return Forbid(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
// Create a new authentication ticket.
var ticket =
await OpenIdExtensions.CreateAuthenticationTicket(_applicationManager, _authorizationManager,
_IdentityOptions.Value, _signInManager,
openIdConnectRequest, user);
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(openIdConnectRequest.ClientId);
var application = await _applicationManager.FindByClientIdAsync(request.ClientId);
var authorization = await _authorizationManager.CreateAsync(User, user.Id, application.Id,
type, ticket.GetScopes().ToImmutableArray(),
ticket.Properties.Items.ToImmutableDictionary());
ticket.SetInternalAuthorizationId(authorization.Id);
type, principal.GetScopes().ToImmutableArray());
principal.SetInternalAuthorizationId(authorization.Id);
}
// Returning a SignInResult will ask OpenIddict to issue the appropriate access/identity tokens.
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
}
}

View File

@ -7,10 +7,7 @@ using BTCPayServer.Services.Stores;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using OpenIddict.Validation;
#if !NETCOREAPP21
using OpenIddictValidationDefaults = Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectDefaults;
#endif
using OpenIddict.Validation.AspNetCore;
namespace BTCPayServer.Controllers.RestApi
{
@ -111,7 +108,6 @@ namespace BTCPayServer.Controllers.RestApi
[Authorize(Policy = RestAPIPolicies.CanViewProfile,
AuthenticationSchemes = AuthenticationSchemes.OpenId)]
[HttpGet(nameof(ScopeCanViewProfile))]
public bool ScopeCanViewProfile() { return true; }

View File

@ -10,10 +10,10 @@ namespace BTCPayServer
{
public static class OpenIddictExtensions
{
public static SecurityKey GetSigningKey(IConfiguration configuration)
public static SecurityKey GetSigningKey(IConfiguration configuration, string fileName)
{
var file = Path.Combine(configuration.GetDataDir(), "rsaparams");
var file = Path.Combine(configuration.GetDataDir(), fileName);
var rsa = new RSACryptoServiceProvider(2048);
if (File.Exists(file))
{
@ -29,7 +29,9 @@ namespace BTCPayServer
public static OpenIddictServerBuilder ConfigureSigningKey(this OpenIddictServerBuilder builder,
IConfiguration configuration)
{
return builder.AddSigningKey(GetSigningKey(configuration));
return builder
.AddSigningKey(GetSigningKey(configuration, "signing.rsaparams"))
.AddEncryptionKey(GetSigningKey(configuration, "encrypting.rsaparams"));
}
}
}

View File

@ -276,21 +276,7 @@ namespace BTCPayServer.Hosting
private static void AddBtcPayServerAuthenticationSchemes(this IServiceCollection services,
IConfiguration configuration)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();
services.AddAuthentication()
.AddJwtBearer(options =>
{
//Disabled so that Tor works witt JWT auth
options.RequireHttpsMetadata = false;
options.TokenValidationParameters.ValidateAudience = false;
//we do not validate the issuer directly because btcpay can be accessed through multiple urls that we cannot predetermine
options.TokenValidationParameters.ValidateIssuer = false;
options.TokenValidationParameters.IssuerSigningKey =
OpenIddictExtensions.GetSigningKey(configuration);
options.IncludeErrorDetails = true;
})
.AddCookie()
.AddBitpayAuthentication();
}

View File

@ -1,11 +1,11 @@
using Microsoft.AspNetCore.Hosting;
#if NETCOREAPP21
using IWebHostEnvironment = Microsoft.AspNetCore.Hosting.IHostingEnvironment;
using AspNet.Security.OpenIdConnect.Primitives;
#else
using Microsoft.Extensions.Hosting;
using OpenIdConnectConstants = OpenIddict.Abstractions.OpenIddictConstants;
#endif
using OpenIddict.Validation.AspNetCore;
using OpenIddict.Abstractions;
using Microsoft.AspNetCore.Builder;
using System;
using Microsoft.Extensions.DependencyInjection;
@ -22,7 +22,6 @@ using System.IO;
using Microsoft.Extensions.DependencyInjection.Extensions;
using BTCPayServer.Security;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using OpenIddict.Abstractions;
using OpenIddict.EntityFrameworkCore.Models;
using System.Net;
using BTCPayServer.Authentication;
@ -57,8 +56,8 @@ namespace BTCPayServer.Hosting
services.AddMemoryCache();
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
.AddDefaultTokenProviders();
ConfigureOpenIddict(services);
services.AddBTCPayServer(Configuration);
@ -95,13 +94,13 @@ namespace BTCPayServer.Hosting
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
options.Password.RequireUppercase = false;
options.Password.RequireUppercase = false;
// Configure Identity to use the same JWT claims as OpenIddict instead
// of the legacy WS-Federation claims it uses by default (ClaimTypes),
// which saves you from doing the mapping in your authorization controller.
options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
options.ClaimsIdentity.UserNameClaimType = OpenIddictConstants.Claims.Name;
options.ClaimsIdentity.UserIdClaimType = OpenIddictConstants.Claims.Subject;
options.ClaimsIdentity.RoleClaimType = OpenIddictConstants.Claims.Role;
});
// If the HTTPS certificate path is not set this logic will NOT be used and the default Kestrel binding logic will be.
string httpsCertificateFilePath = Configuration.GetOrDefault<string>("HttpsCertificateFilePath", null);
@ -123,7 +122,7 @@ namespace BTCPayServer.Hosting
// Note that by design this is a fatal error condition that will cause the process to exit.
throw new ConfigException($"The https certificate file could not be found at {httpsCertificateFilePath}.");
}
if(hasCertPath && useDefaultCertificate)
if (hasCertPath && useDefaultCertificate)
{
throw new ConfigException($"Conflicting settings: if HttpsUseDefaultCertificate is true, HttpsCertificateFilePath should not be used");
}
@ -147,7 +146,7 @@ namespace BTCPayServer.Hosting
private void ConfigureOpenIddict(IServiceCollection services)
{
// Register the OpenIddict services.
// Register the OpenIddict services.
services.AddOpenIddict()
.AddCore(options =>
{
@ -159,15 +158,6 @@ namespace BTCPayServer.Hosting
})
.AddServer(options =>
{
#if NETCOREAPP21
options.EnableRequestCaching();
//Disabled so that Tor works with OpenIddict too
options.DisableHttpsRequirement();
// Register the ASP.NET Core MVC binder used by OpenIddict.
// Note: if you don't call this method, you won't be able to
// bind OpenIdConnectRequest or OpenIdConnectResponse parameters.
options.UseMvc();
#else
options.UseAspNetCore()
.EnableStatusCodePagesIntegration()
.EnableAuthorizationEndpointPassthrough()
@ -175,18 +165,11 @@ namespace BTCPayServer.Hosting
.EnableTokenEndpointPassthrough()
.EnableRequestCaching()
.DisableTransportSecurityRequirement();
#endif
// Enable the token endpoint (required to use the password flow).
#if NETCOREAPP21
options.EnableTokenEndpoint("/connect/token");
options.EnableAuthorizationEndpoint("/connect/authorize");
options.EnableLogoutEndpoint("/connect/logout");
#else
options.SetTokenEndpointUris("/connect/token");
options.SetAuthorizationEndpointUris("/connect/authorize");
options.SetLogoutEndpointUris("/connect/logout");
#endif
//we do not care about these granular controls for now
options.IgnoreScopePermissions();
@ -198,36 +181,26 @@ namespace BTCPayServer.Hosting
options.AllowPasswordFlow();
options.AllowAuthorizationCodeFlow();
options.UseRollingTokens();
#if NETCOREAPP21
options.UseJsonWebTokens();
#endif
options.RegisterScopes(
OpenIdConnectConstants.Scopes.OpenId,
OpenIdConnectConstants.Scopes.OfflineAccess,
OpenIdConnectConstants.Scopes.Email,
OpenIdConnectConstants.Scopes.Profile,
OpenIddictConstants.Scopes.Roles,
OpenIddictConstants.Scopes.OpenId,
RestAPIPolicies.BTCPayScopes.ViewStores,
RestAPIPolicies.BTCPayScopes.CreateInvoices,
RestAPIPolicies.BTCPayScopes.StoreManagement,
RestAPIPolicies.BTCPayScopes.ViewApps,
RestAPIPolicies.BTCPayScopes.ServerManagement,
RestAPIPolicies.BTCPayScopes.AppManagement
);
#if NETCOREAPP21
options.AddEventHandler<PasswordGrantTypeEventHandler>();
options.AddEventHandler<AuthorizationCodeGrantTypeEventHandler>();
options.AddEventHandler<RefreshTokenGrantTypeEventHandler>();
options.AddEventHandler<ClientCredentialsGrantTypeEventHandler>();
options.AddEventHandler<LogoutEventHandler>();
#else
options.AddEventHandler(PasswordGrantTypeEventHandler.Descriptor);
options.AddEventHandler(AuthorizationCodeGrantTypeEventHandler.Descriptor);
options.AddEventHandler(RefreshTokenGrantTypeEventHandler.Descriptor);
options.AddEventHandler(OpenIdGrantHandlerCheckCanSignIn.Descriptor);
options.AddEventHandler(ClientCredentialsGrantTypeEventHandler.Descriptor);
options.AddEventHandler(LogoutEventHandler.Descriptor);
#endif
options.ConfigureSigningKey(Configuration);
})
.AddValidation(options =>
{
options.UseLocalServer();
options.UseAspNetCore();
});
}

View File

@ -53,7 +53,7 @@ namespace BTCPayServer
l.AddFilter("Microsoft", LogLevel.Error);
l.AddFilter("System.Net.Http.HttpClient", LogLevel.Critical);
l.AddFilter("Microsoft.AspNetCore.Antiforgery.Internal", LogLevel.Critical);
l.AddFilter("AspNet.Security.OpenIdConnect.Server.OpenIdConnectServerHandler", LogLevel.Error);
l.AddFilter("OpenIddict.Server.OpenIddictServerProvider", LogLevel.Error);
l.AddProvider(new CustomConsoleLogProvider(processor));
// Use Serilog for debug log file.

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using OpenIddict.Validation;
using OpenIddict.Validation.AspNetCore;
namespace BTCPayServer.Security
{
@ -10,6 +11,6 @@ namespace BTCPayServer.Security
{
public const string Cookie = "Identity.Application";
public const string Bitpay = "Bitpay";
public const string OpenId = OpenIddictValidationDefaults.AuthenticationScheme;
public const string OpenId = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
}
}

View File

@ -66,6 +66,11 @@ namespace BTCPayServer.Security
success = context.HasScopes(OpenIddictConstants.Scopes.Profile);
break;
case Policies.CanModifyStoreSettings.Key:
if (!context.HasScopes(BTCPayScopes.StoreManagement))
break;
// TODO: It should be possible to grant permission to a specific store
// we can do this by adding saving a claim with the specific store id
// to the access_token
string storeId = _HttpContext.GetImplicitStoreId();
if (storeId == null)
break;
@ -79,7 +84,15 @@ namespace BTCPayServer.Security
_HttpContext.SetStoreData(store);
break;
case Policies.CanModifyServerSettings.Key:
success = context.User.HasClaim("role", Roles.ServerAdmin);
if (!context.HasScopes(BTCPayScopes.ServerManagement))
break;
// For this authorization, we stil check in database because it is super sensitive.
var user = await _userManager.GetUserAsync(context.User);
if (user == null)
break;
if (!await _userManager.IsInRoleAsync(user, Roles.ServerAdmin))
break;
success = true;
break;
}

View File

@ -16,7 +16,7 @@ namespace BTCPayServer.Security
{
public static bool HasScopes(this AuthorizationHandlerContext context, params string[] scopes)
{
return scopes.All(s => context.User.HasClaim(OpenIddictConstants.Claims.Scope, s));
return scopes.All(s => context.User.HasClaim(c => c.Type == OpenIddictConstants.Claims.Scope && c.Value.Split(' ').Contains(s)));
}
public static string GetImplicitStoreId(this HttpContext httpContext)
{

View File

@ -12,10 +12,8 @@
{RestAPIPolicies.BTCPayScopes.StoreManagement, ("Manage your stores", "The app will be able to create, modify and delete all your stores.")},
{RestAPIPolicies.BTCPayScopes.ViewStores, ("View your stores", "The app will be able to list and view all your stores.")},
{RestAPIPolicies.BTCPayScopes.WalletManagement, ("Manage your wallet", "The app will be able to manage your wallet associate to stores. This includes configuring it, transaction creation and signing.")},
{RestAPIPolicies.BTCPayScopes.ServerManagement, ("Manage your server", "The app will have total control on your server")},
{RestAPIPolicies.BTCPayScopes.ViewInvoices, ("View your invoices", "The app will be able to list and view all your apps.")},
{OpenIddictConstants.Scopes.Email, ("View your email", "The app will have access to your email.")},
{OpenIddictConstants.Scopes.Profile, ("View your account", "The app will have access to your account details.")},
{OpenIddictConstants.Scopes.Roles, ("View your roles", "The app will know if you are a server admin.")},
};
}
<form method="post">

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear/>
<add key="aspnetcidev" value="https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json"/>
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json"/>
</packageSources>
</configuration>

View File

@ -1,5 +1,6 @@
FROM mcr.microsoft.com/dotnet/core/sdk:2.1.505-alpine3.7 AS builder
WORKDIR /source
COPY nuget.config nuget.config
COPY Build/Common.csproj Build/Common.csproj
COPY BTCPayServer/BTCPayServer.csproj BTCPayServer/BTCPayServer.csproj
COPY BTCPayServer.Common/BTCPayServer.Common.csproj BTCPayServer.Common/BTCPayServer.Common.csproj

View File

@ -4,6 +4,7 @@ RUN apt-get update \
&& apt-get install -qq --no-install-recommends qemu qemu-user-static qemu-user binfmt-support
WORKDIR /source
COPY nuget.config nuget.config
COPY Build/Common.csproj Build/Common.csproj
COPY BTCPayServer/BTCPayServer.csproj BTCPayServer/BTCPayServer.csproj
COPY BTCPayServer.Common/BTCPayServer.Common.csproj BTCPayServer.Common/BTCPayServer.Common.csproj

13
nuget.config Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="arcade" value="https://dotnetfeed.blob.core.windows.net/dotnet-tools-internal/index.json" />
<add key="dotnet-core" value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" />
<add key="azureadwebstacknightly" value="https://www.myget.org/F/azureadwebstacknightly/api/v3/index.json" />
<add key="aspnetcidev" value="https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json" />
<add key="Openiddict" value="https://www.myget.org/F/openiddict/api/v3/index.json" />
</packageSources>
</configuration>