Skip to content

Commit

Permalink
small fixes and adjustments around btcpay auth
Browse files Browse the repository at this point in the history
  • Loading branch information
Kukks committed Mar 18, 2021
1 parent 8e3051e commit c7fe582
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 38 deletions.
6 changes: 5 additions & 1 deletion BtcTransmuter/Areas/Identity/Pages/Account/Login.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,11 @@ public class GetCurrentUserResponse {
public bool EmailConfirmed { get; set; }

[JsonProperty("requiresEmailConfirmation")]
public bool RequiresEmailConfirmation { get; set; }
public bool RequiresEmailConfirmation { get; set; }


[JsonProperty("roles")]
public string[] Roles { get; set; }

public override string ToString()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Net.Http;
using System.Net.Http.Headers;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using BtcTransmuter.Data.Entities;
using BtcTransmuter.Data.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace BtcTransmuter.Areas.Identity.Pages.Account.Manage
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@
<ul class="nav nav-pills flex-column">
<li class="nav-item"><a class="nav-link @ManageNavPages.IndexNavClass(ViewContext)" id="profile" asp-page="./Index">Profile</a></li>
@if (!BtcTransmuterOptions.DisableInternalAuth)
{

{
<li class="nav-item"><a class="nav-link @ManageNavPages.ChangePasswordNavClass(ViewContext)" id="change-password" asp-page="./ChangePassword">Password</a></li>
}
@if (BtcTransmuterOptions.BTCPayAuthServer != null)
{
<li class="nav-item"><a class="nav-link @ManageNavPages.BTCPayAccountLinkNavClass(ViewContext)" id="btcpay-account-link" asp-page="./BTCPayAccountLinkNavClass">BTCPay account link</a></li>
<li class="nav-item"><a class="nav-link @ManageNavPages.BTCPayAccountLinkNavClass(ViewContext)" id="btcpay-account-link" asp-page="./BTCPayAccountLink">BTCPay account link</a></li>

}

Expand Down
87 changes: 60 additions & 27 deletions BtcTransmuter/BTCPayAuthService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using BtcTransmuter.Data.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

Expand All @@ -20,12 +21,16 @@ public class BTCPayAuthService
private readonly UserManager<User> _userManager;
private readonly IBtcTransmuterOptions _btcTransmuterOptions;
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<BTCPayAuthService> _logger;

public BTCPayAuthService(UserManager<User> userManager, IBtcTransmuterOptions btcTransmuterOptions, IHttpClientFactory httpClientFactory)
public BTCPayAuthService(
UserManager<User> userManager, IBtcTransmuterOptions btcTransmuterOptions,
IHttpClientFactory httpClientFactory, ILogger<BTCPayAuthService> logger)
{
_userManager = userManager;
_btcTransmuterOptions = btcTransmuterOptions;
_httpClientFactory = httpClientFactory;
_logger = logger;
}

public async Task<User> LoginAndRegisterIfNeeded(string user, string pass)
Expand All @@ -40,6 +45,7 @@ public async Task<User> LoginAndRegisterIfNeeded(string user, string pass)
{
return null;
}

var matchedUser = await FindUserByBTCPayUserId(response.Id);
if (matchedUser == null)
{
Expand All @@ -48,6 +54,7 @@ public async Task<User> LoginAndRegisterIfNeeded(string user, string pass)
{
return null;
}

//create account
matchedUser = new User()
{
Expand All @@ -65,7 +72,8 @@ public async Task<User> LoginAndRegisterIfNeeded(string user, string pass)
});
if ((await _userManager.CreateAsync(matchedUser)).Succeeded)
{
if (await _userManager.Users.CountAsync() == 1)

if (response.Roles.Contains("ServerAdmin") || await _userManager.Users.CountAsync() == 1)
{
await _userManager.AddToRoleAsync(matchedUser, "Admin");
}
Expand All @@ -78,16 +86,26 @@ public async Task<User> LoginAndRegisterIfNeeded(string user, string pass)
else
{
var tokenResponse = await CheckToken(matchedUser);

if (!(tokenResponse?.ToString()?.Equals(response.ToString()) is true) && await GenerateKeyAndSet(user, pass, matchedUser))

if (!(tokenResponse?.ToString()?.Equals(response.ToString()) is true) &&
await GenerateKeyAndSet(user, pass, matchedUser))
{
await _userManager.UpdateAsync(matchedUser);
}else if (!(tokenResponse?.ToString()?.Equals(response.ToString()) is true))
}
else if (!(tokenResponse?.ToString()?.Equals(response.ToString()) is true))
{
return null;
}
}

if (response.Roles.Contains("ServerAdmin"))
{
await _userManager.AddToRoleAsync(matchedUser, "Admin");
}
else if(!await _userManager.HasPasswordAsync(matchedUser))
{
await _userManager.RemoveFromRoleAsync(matchedUser, "Admin");
}

return matchedUser;
}

Expand All @@ -100,29 +118,33 @@ private async Task<bool> GenerateKeyAndSet(string user, string pass, User matche
}

var blob = matchedUser.Get<UserBlob>();
blob.BTCPayAuthDetails.AccessToken = key;
blob.BTCPayAuthDetails.AccessToken = key;
if (_btcTransmuterOptions.DisableInternalAuth || !await _userManager.HasPasswordAsync(matchedUser))
{
matchedUser.Email = user;
matchedUser.UserName= user;
matchedUser.UserName = user;
}

matchedUser.Set(blob);
return true;
}

public async Task<string> GenerateKey(string user, string pass)
{
var client = _httpClientFactory.CreateClient("BTCPayAuthServer");
var request = new HttpRequestMessage(HttpMethod.Post, new Uri(_btcTransmuterOptions.BTCPayAuthServer, "/api/v1/api-keys"));
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{user}:{pass}")));
var request = new HttpRequestMessage(HttpMethod.Post,
new Uri(_btcTransmuterOptions.BTCPayAuthServer, "/api/v1/api-keys"));
request.Headers.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(Encoding.UTF8.GetBytes($"{user}:{pass}")));
request.Content = new StringContent(JsonConvert.SerializeObject(new
{
label = "transmuter login access token",
permissions = new[]{ "btcpay.user.canmodifyprofile"}
permissions = new[] {"btcpay.user.canmodifyprofile"}
}), Encoding.UTF8, "application/json");

var response = await client.SendAsync(request);

if(response.IsSuccessStatusCode)
if (response.IsSuccessStatusCode)
{
var accessTokenResponse =
JsonConvert.DeserializeObject<JObject>((await response.Content.ReadAsStringAsync()));
Expand All @@ -131,6 +153,7 @@ public async Task<string> GenerateKey(string user, string pass)

return null;
}

public async Task<User> FindUserByBTCPayUserId(string userId)
{
return _userManager.Users.AsEnumerable().SingleOrDefault(user =>
Expand All @@ -143,18 +166,27 @@ public async Task<GetCurrentUserResponse> BasicAuthLogin(string user, string pas
{
return null;
}

var client = _httpClientFactory.CreateClient("BTCPayAuthServer");
var fetchUserId = new Uri(_btcTransmuterOptions.BTCPayAuthServer, "api/v1/users/me");
var request = new HttpRequestMessage(HttpMethod.Get, fetchUserId);
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{user}:{pass}")));
var response = await client.SendAsync(request);
if (!response.IsSuccessStatusCode)

try
{
return null;
var client = _httpClientFactory.CreateClient("BTCPayAuthServer");
var fetchUserId = new Uri(_btcTransmuterOptions.BTCPayAuthServer, "api/v1/users/me");
var request = new HttpRequestMessage(HttpMethod.Get, fetchUserId);
request.Headers.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(Encoding.UTF8.GetBytes($"{user}:{pass}")));
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
return JsonConvert.DeserializeObject<GetCurrentUserResponse>(
await response.Content.ReadAsStringAsync());
}
}
return JsonConvert.DeserializeObject<GetCurrentUserResponse>(
await response.Content.ReadAsStringAsync());
catch (Exception e)
{
_logger.LogError(e, "error while attempting to authenticate with btcpay");
}

return null;
}

public async Task<GetCurrentUserResponse> CheckToken(User user)
Expand All @@ -163,23 +195,25 @@ public async Task<GetCurrentUserResponse> CheckToken(User user)
{
return null;
}

var blob = user.Get<UserBlob>();
return await CheckToken(blob.BTCPayAuthDetails.AccessToken);
}

public async Task<GetCurrentUserResponse> CheckToken(string token)
{
if (_btcTransmuterOptions.BTCPayAuthServer is null)
{
return null;
}

var client = _httpClientFactory.CreateClient("BTCPayAuthServer");

if (string.IsNullOrEmpty(token))
{
return null;
}

var fetchUserId = new Uri(_btcTransmuterOptions.BTCPayAuthServer, "api/v1/users/me");
var request = new HttpRequestMessage(HttpMethod.Get, fetchUserId);
request.Headers.Authorization = new AuthenticationHeaderValue("token", token);
Expand All @@ -188,10 +222,9 @@ public async Task<GetCurrentUserResponse> CheckToken(string token)
{
return null;
}

return JsonConvert.DeserializeObject<GetCurrentUserResponse>(
await response.Content.ReadAsStringAsync());
}


}
}
3 changes: 2 additions & 1 deletion BtcTransmuter/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"NBXplorer_Uri": "http://127.0.0.1:32838/",
"NBXplorer_NetworkType":"Regtest",
"NBXplorer_UseDefaultCookie": "1",
"BTCPayAuthServer": "https://localhost:14142"
"BTCPayAuthServer": "http://localhost:14142",
"DisableInternalAuth": "false"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
},
Expand Down

0 comments on commit c7fe582

Please sign in to comment.