Use claim based authentication

This commit is contained in:
nicolas.dorier 2018-04-28 02:09:24 +09:00
parent c3ee43c228
commit 8ff81f1648
8 changed files with 30 additions and 50 deletions

View file

@ -89,7 +89,7 @@ services:
- "bitcoin_datadir:/data"
customer_lightningd:
image: nicolasdorier/clightning:0.0.0.9-dev
image: nicolasdorier/clightning:0.0.0.11-dev
environment:
EXPOSE_TCP: "true"
LIGHTNINGD_OPT: |
@ -130,7 +130,7 @@ services:
- merchant_lightningd
merchant_lightningd:
image: nicolasdorier/clightning:0.0.0.9-dev
image: nicolasdorier/clightning:0.0.0.11-dev
environment:
EXPOSE_TCP: "true"
LIGHTNINGD_OPT: |

View file

@ -1,35 +0,0 @@
using NBitcoin;
using NBitcoin.DataEncoders;
using System;
using System.Collections.Generic;
using System.Security.Principal;
using System.Text;
namespace BTCPayServer.Authentication
{
public class BitIdentity : IIdentity
{
public BitIdentity(PubKey key)
{
PubKey = key;
_Name = Encoders.Base58Check.EncodeData(Encoders.Hex.DecodeData("0f02" + key.Hash.ToString()));
SIN = NBitpayClient.Extensions.BitIdExtensions.GetBitIDSIN(key);
}
string _Name;
public string SIN
{
get;
}
public PubKey PubKey
{
get;
}
public string AuthenticationType => "BitID";
public bool IsAuthenticated => true;
public string Name => _Name;
}
}

View file

@ -33,6 +33,8 @@ namespace BTCPayServer.Authentication
public async Task<BitTokenEntity[]> GetTokens(string sin)
{
if (sin == null)
return Array.Empty<BitTokenEntity>();
using (var ctx = _Factory.CreateContext())
{
return (await ctx.PairedSINData

View file

@ -23,7 +23,7 @@ namespace BTCPayServer.Controllers
[Route("tokens")]
public async Task<GetTokensResponse> Tokens()
{
var tokens = await _TokenRepository.GetTokens(this.GetBitIdentity().SIN);
var tokens = await _TokenRepository.GetTokens(this.User.GetSIN());
return new GetTokensResponse(tokens);
}
@ -51,7 +51,7 @@ namespace BTCPayServer.Controllers
}
else
{
var sin = this.GetBitIdentity(false)?.SIN ?? request.Id;
var sin = this.User.GetSIN() ?? request.Id;
if (string.IsNullOrEmpty(request.Id) || !NBitpayClient.Extensions.BitIdExtensions.ValidateSIN(request.Id))
throw new BitpayHttpException(400, "'id' property is required, alternatively, use BitId");

View file

@ -103,13 +103,13 @@ namespace BTCPayServer.Controllers
if (facade == null)
throw new ArgumentNullException(nameof(facade));
var actualTokens = (await _TokenRepository.GetTokens(this.GetBitIdentity().SIN)).ToArray();
var actualTokens = (await _TokenRepository.GetTokens(this.User.GetSIN())).ToArray();
actualTokens = actualTokens.SelectMany(t => GetCompatibleTokens(t)).ToArray();
var actualToken = actualTokens.FirstOrDefault(a => a.Value.Equals(expectedToken, StringComparison.Ordinal));
if (expectedToken == null || actualToken == null)
{
Logs.PayServer.LogDebug($"No token found for facade {facade} for SIN {this.GetBitIdentity().SIN}");
Logs.PayServer.LogDebug($"No token found for facade {facade} for SIN {this.User.GetSIN()}");
throw new BitpayHttpException(401, $"This endpoint does not support the `{actualTokens.Select(a => a.Facade).Concat(new[] { "user" }).FirstOrDefault()}` facade");
}
return actualToken;

View file

@ -29,6 +29,7 @@ using Microsoft.AspNetCore.Identity;
using BTCPayServer.Models;
using System.Security.Claims;
using System.Globalization;
using BTCPayServer.Services;
namespace BTCPayServer
{
@ -142,12 +143,9 @@ namespace BTCPayServer
return services;
}
public static BitIdentity GetBitIdentity(this Controller controller, bool throws = true)
public static string GetSIN(this ClaimsPrincipal principal)
{
if (!(controller.User.Identity is BitIdentity))
return throws ? throw new UnauthorizedAccessException("no-bitid") : (BitIdentity)null;
return (BitIdentity)controller.User.Identity;
return principal.Claims.Where(c => c.Type == Claims.SIN).Select(c => c.Value).FirstOrDefault();
}
private static JsonSerializerSettings jsonSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };

View file

@ -23,6 +23,8 @@ using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Http.Extensions;
using BTCPayServer.Controllers;
using System.Net.WebSockets;
using System.Security.Claims;
using BTCPayServer.Services;
namespace BTCPayServer.Hosting
{
@ -69,13 +71,14 @@ namespace BTCPayServer.Hosting
var key = new PubKey(id);
if (BitIdExtensions.CheckBitIDSignature(key, sig, url, body))
{
var bitid = new BitIdentity(key);
httpContext.User = new GenericPrincipal(bitid, Array.Empty<string>());
Logs.PayServer.LogDebug($"BitId signature check success for SIN {bitid.SIN}");
var sin = key.GetBitIDSIN();
var identity = ((ClaimsIdentity)httpContext.User.Identity);
identity.AddClaim(new Claim(Claims.SIN, sin));
Logs.PayServer.LogDebug($"BitId signature check success for SIN {sin}");
}
}
catch (FormatException) { }
if (!(httpContext.User.Identity is BitIdentity))
if (!httpContext.User.HasClaim(c=> c.Type == Claims.SIN))
Logs.PayServer.LogDebug("BitId signature check failed");
}

View file

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace BTCPayServer.Services
{
public class Claims
{
public const string SIN = "BITID_SIN";
}
}