Fix authentication

This commit is contained in:
nicolas.dorier 2018-06-06 16:02:37 +09:00
parent b7c58c2083
commit 04174b7431
4 changed files with 35 additions and 23 deletions

View file

@ -771,6 +771,7 @@ namespace BTCPayServer.Tests
Assert.False(user.BitPay.TestAccess(Facade.Merchant));
user.GrantAccess();
user.RegisterDerivationScheme("BTC");
Assert.True(user.BitPay.TestAccess(Facade.Merchant));
// Test request pairing code client side
@ -784,10 +785,15 @@ namespace BTCPayServer.Tests
Assert.NotNull(storeController.GeneratedPairingCode);
var bitpay = new Bitpay(new Key(), tester.PayTester.ServerUri);
var k = new Key();
var bitpay = new Bitpay(k, tester.PayTester.ServerUri);
bitpay.AuthorizeClient(new PairingCode(storeController.GeneratedPairingCode)).Wait();
Assert.True(bitpay.TestAccess(Facade.Merchant));
Assert.True(bitpay.TestAccess(Facade.PointOfSale));
// Same with new instance
bitpay = new Bitpay(k, tester.PayTester.ServerUri);
Assert.True(bitpay.TestAccess(Facade.Merchant));
Assert.True(bitpay.TestAccess(Facade.PointOfSale));
// Can generate API Key
var repo = tester.PayTester.GetService<TokenRepository>();

View file

@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<Version>1.0.2.33</Version>
<Version>1.0.2.34</Version>
<NoWarn>NU1701,CA1816,CA1308,CA1810,CA2208</NoWarn>
</PropertyGroup>
<ItemGroup>

View file

@ -13,6 +13,7 @@ using System.Threading.Tasks;
namespace BTCPayServer.Controllers
{
[Authorize(AuthenticationSchemes = Security.Policies.BitpayAuthentication)]
[BitpayAPIConstraint(true)]
public class AccessTokenController : Controller
{
TokenRepository _TokenRepository;

View file

@ -54,17 +54,19 @@ namespace BTCPayServer.Security
{
if (Context.Request.HttpContext.GetIsBitpayAPI())
{
List<Claim> claims = new List<Claim>();
var bitpayAuth = Context.Request.HttpContext.GetBitpayAuth();
string storeId = null;
// Careful, those are not the opposite. failedAuth says if a the tentative failed.
// successAuth, ensure that at least one succeed.
var failedAuth = false;
var successAuth = false;
if (!string.IsNullOrEmpty(bitpayAuth.Signature) && !string.IsNullOrEmpty(bitpayAuth.Id))
{
storeId = await CheckBitId(Context.Request.HttpContext, bitpayAuth.Signature, bitpayAuth.Id);
if (!Context.User.Claims.Any(c => c.Type == Claims.SIN))
{
Logs.PayServer.LogDebug("BitId signature check failed");
failedAuth = true;
}
var result = await CheckBitId(Context.Request.HttpContext, bitpayAuth.Signature, bitpayAuth.Id, claims);
storeId = result.StoreId;
failedAuth = !result.SuccessAuth;
successAuth = result.SuccessAuth;
}
else if (!string.IsNullOrEmpty(bitpayAuth.Authorization))
{
@ -74,25 +76,29 @@ namespace BTCPayServer.Security
Logs.PayServer.LogDebug("API key check failed");
failedAuth = true;
}
successAuth = storeId != null;
}
if (storeId != null)
{
var identity = ((ClaimsIdentity)Context.User.Identity);
identity.AddClaim(new Claim(Policies.CanUseStore.Key, storeId));
var store = await _StoreRepository.FindStore(storeId);
Context.Request.HttpContext.SetStoreData(store);
return AuthenticateResult.Success(new AuthenticationTicket(Context.User, Policies.BitpayAuthentication));
}
else if (failedAuth)
if (failedAuth)
{
return AuthenticateResult.Fail("Invalid credentials");
}
if (successAuth)
{
if (storeId != null)
{
claims.Add(new Claim(Policies.CanUseStore.Key, storeId));
var store = await _StoreRepository.FindStore(storeId);
Context.Request.HttpContext.SetStoreData(store);
}
return AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(new ClaimsIdentity(claims, Policies.BitpayAuthentication)), Policies.BitpayAuthentication));
}
}
return AuthenticateResult.NoResult();
}
private async Task<string> CheckBitId(HttpContext httpContext, string sig, string id)
private async Task<(string StoreId, bool SuccessAuth)> CheckBitId(HttpContext httpContext, string sig, string id, List<Claim> claims)
{
httpContext.Request.EnableRewind();
@ -114,8 +120,7 @@ namespace BTCPayServer.Security
if (BitIdExtensions.CheckBitIDSignature(key, sig, url, body))
{
var sin = key.GetBitIDSIN();
var identity = ((ClaimsIdentity)httpContext.User.Identity);
identity.AddClaim(new Claim(Claims.SIN, sin));
claims.Add(new Claim(Claims.SIN, sin));
string token = null;
if (httpContext.Request.Query.TryGetValue("token", out var tokenValues))
@ -137,14 +142,14 @@ namespace BTCPayServer.Security
var bitToken = await GetTokenPermissionAsync(sin, token);
if (bitToken == null)
{
return null;
return (null, false);
}
storeId = bitToken.StoreId;
}
}
}
catch (FormatException) { }
return storeId;
return (storeId, true);
}
private async Task<string> CheckLegacyAPIKey(HttpContext httpContext, string auth)
@ -235,7 +240,7 @@ namespace BTCPayServer.Security
}
internal static void AddAuthentication(IServiceCollection services, Action<BitpayAuthOptions> bitpayAuth = null)
{
bitpayAuth = bitpayAuth ?? new Action<BitpayAuthOptions>((o) =>{ });
bitpayAuth = bitpayAuth ?? new Action<BitpayAuthOptions>((o) => { });
services.AddAuthentication().AddScheme<BitpayAuthOptions, BitpayAuthHandler>(Policies.BitpayAuthentication, bitpayAuth);
}
}