1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-02 16:42:50 -05:00

[SG-167] Implement Passwordless Authentication via Notifications (#2276)

* [SG-549] Commit Initial AuthRequest Repository (#2174)

* Model Passwordless

* Scaffold database for Passwordless

* Implement SQL Repository

* [SG-167] Base Passwordless API (#2185)

* Implement Passwordless notifications

* Implement Controller

* Add documentation to BaseRequestValidator

* Register AuthRequestRepo

* Remove ExpirationDate from the AuthRequest table

* [SG-407] Create job to delete expired requests (#2187)

* chore: init

* remove exp date

* fix: log name

* [SG-167] Added fingerprint phrase to response model. (#2233)

* Remove FailedLoginAttempt logic

* Block unknown devices

* Add EF Support for passwordless

* Got SignalR working for responses

* Added delete job method to EF repo

* Implement a GetMany API endpoint for AuthRequests

* Ran dotnet format

* Fix a merge issues

* Redated migration scripts

* tried sorting sqlproj

* Remove FailedLoginAttempts from SQL

* Groom Postgres script

* Remove extra commas from migration script

* Correct isSpent()

* [SG-167] Adde identity validation for passwordless requests. Registered IAuthRepository.

* [SG-167] Added origin of the request to response model

* Use display name for device identifier in response

* Add datetime conversions back to postgres migration script

* [SG-655] Add anonymous endpoint for checking if a device & user combo match

* [review] Consolidate error conditions

Co-authored-by: Brandon Maharaj <107377945+BrandonM-Bitwarden@users.noreply.github.com>
Co-authored-by: André Filipe da Silva Bispo <andrefsbispo@hotmail.com>
Co-authored-by: André Bispo <abispo@bitwarden.com>
This commit is contained in:
Addison Beck
2022-09-26 13:21:13 -04:00
committed by GitHub
parent 7c3637c8ba
commit 02bea3c48d
56 changed files with 5853 additions and 61 deletions

View File

@ -0,0 +1,19 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
namespace Bit.Notifications;
[AllowAnonymous]
public class AnonymousNotificationsHub : Microsoft.AspNetCore.SignalR.Hub, INotificationHub
{
public override async Task OnConnectedAsync()
{
var httpContext = Context.GetHttpContext();
var token = httpContext.Request.Query["Token"].FirstOrDefault();
if (!string.IsNullOrWhiteSpace(token))
{
await Groups.AddToGroupAsync(Context.ConnectionId, token);
}
await base.OnConnectedAsync();
}
}

View File

@ -9,6 +9,7 @@ public class AzureQueueHostedService : IHostedService, IDisposable
{
private readonly ILogger _logger;
private readonly IHubContext<NotificationsHub> _hubContext;
private readonly IHubContext<AnonymousNotificationsHub> _anonymousHubContext;
private readonly GlobalSettings _globalSettings;
private Task _executingTask;
@ -18,11 +19,13 @@ public class AzureQueueHostedService : IHostedService, IDisposable
public AzureQueueHostedService(
ILogger<AzureQueueHostedService> logger,
IHubContext<NotificationsHub> hubContext,
IHubContext<AnonymousNotificationsHub> anonymousHubContext,
GlobalSettings globalSettings)
{
_logger = logger;
_hubContext = hubContext;
_globalSettings = globalSettings;
_anonymousHubContext = anonymousHubContext;
}
public Task StartAsync(CancellationToken cancellationToken)
@ -62,7 +65,7 @@ public class AzureQueueHostedService : IHostedService, IDisposable
try
{
await HubHelpers.SendNotificationToHubAsync(
message.DecodeMessageText(), _hubContext, cancellationToken);
message.DecodeMessageText(), _hubContext, _anonymousHubContext, cancellationToken);
await _queueClient.DeleteMessageAsync(message.MessageId, message.PopReceipt);
}
catch (Exception e)

View File

@ -25,7 +25,7 @@ public class SendController : Controller
var notificationJson = await reader.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(notificationJson))
{
await HubHelpers.SendNotificationToHubAsync(notificationJson, _hubContext);
await HubHelpers.SendNotificationToHubAsync(notificationJson, _hubContext, null);
}
}
}

View File

@ -7,8 +7,12 @@ namespace Bit.Notifications;
public static class HubHelpers
{
public static async Task SendNotificationToHubAsync(string notificationJson,
IHubContext<NotificationsHub> hubContext, CancellationToken cancellationToken = default(CancellationToken))
public static async Task SendNotificationToHubAsync(
string notificationJson,
IHubContext<NotificationsHub> hubContext,
IHubContext<AnonymousNotificationsHub> anonymousHubContext,
CancellationToken cancellationToken = default(CancellationToken)
)
{
var notification = JsonSerializer.Deserialize<PushNotificationData<object>>(notificationJson);
switch (notification.Type)
@ -61,6 +65,20 @@ public static class HubHelpers
await hubContext.Clients.User(sendNotification.Payload.UserId.ToString())
.SendAsync("ReceiveMessage", sendNotification, cancellationToken);
break;
case PushType.AuthRequestResponse:
var authRequestResponseNotification =
JsonSerializer.Deserialize<PushNotificationData<AuthRequestPushNotification>>(
notificationJson);
await anonymousHubContext.Clients.Group(authRequestResponseNotification.Payload.Id.ToString())
.SendAsync("AuthRequestResponseRecieved", authRequestResponseNotification, cancellationToken);
break;
case PushType.AuthRequest:
var authRequestNotification =
JsonSerializer.Deserialize<PushNotificationData<AuthRequestPushNotification>>(
notificationJson);
await hubContext.Clients.User(authRequestNotification.Payload.UserId.ToString())
.SendAsync("ReceiveMessage", authRequestNotification, cancellationToken);
break;
default:
break;
}

View File

@ -0,0 +1,7 @@
namespace Bit.Notifications;
public interface INotificationHub
{
Task OnConnectedAsync();
Task OnDisconnectedAsync(Exception exception);
}

View File

@ -110,7 +110,12 @@ public class Startup
{
endpoints.MapHub<NotificationsHub>("/hub", options =>
{
options.ApplicationMaxBufferSize = 2048; // client => server messages are not even used
options.ApplicationMaxBufferSize = 2048;
options.TransportMaxBufferSize = 4096;
});
endpoints.MapHub<AnonymousNotificationsHub>("/anonymousHub", options =>
{
options.ApplicationMaxBufferSize = 2048;
options.TransportMaxBufferSize = 4096;
});
endpoints.MapDefaultControllerRoute();