mirror of
https://github.com/bitwarden/server.git
synced 2025-07-05 18:12:48 -05:00
[PM-2032] Server endpoints to support authentication with a passkey (#3361)
* [PM-2032] feat: add assertion options tokenable * [PM-2032] feat: add request and response models * [PM-2032] feat: implement `assertion-options` identity endpoint * [PM-2032] feat: implement authentication with passkey * [PM-2032] chore: rename to `WebAuthnGrantValidator` * [PM-2032] fix: add missing subsitute * [PM-2032] feat: start adding builder * [PM-2032] feat: add support for KeyConnector * [PM-2032] feat: add first version of TDE * [PM-2032] chore: refactor WithSso * [PM-2023] feat: add support for TDE feature flag * [PM-2023] feat: add support for approving devices * [PM-2023] feat: add support for hasManageResetPasswordPermission * [PM-2032] feat: add support for hasAdminApproval * [PM-2032] chore: don't supply device if not necessary * [PM-2032] chore: clean up imports * [PM-2023] feat: extract interface * [PM-2023] chore: add clarifying comment * [PM-2023] feat: use new builder in production code * [PM-2032] feat: add support for PRF * [PM-2032] chore: clean-up todos * [PM-2023] chore: remove token which is no longer used * [PM-2032] chore: remove todo * [PM-2032] feat: improve assertion error handling * [PM-2032] fix: linting issues * [PM-2032] fix: revert changes to `launchSettings.json` * [PM-2023] chore: clean up assertion endpoint * [PM-2032] feat: bypass 2FA * [PM-2032] fix: rename prf option to singular * [PM-2032] fix: lint * [PM-2032] fix: typo * [PM-2032] chore: improve builder tests Co-authored-by: Jared Snider <116684653+JaredSnider-Bitwarden@users.noreply.github.com> * [PM-2032] chore: clarify why we don't require 2FA * [PM-2023] feat: move `identityProvider` constant to common class * [PM-2032] fix: lint * [PM-2023] fix: move `IdentityProvider` to core.Constants * [PM-2032] fix: missing import * [PM-2032] chore: refactor token timespan to use `TimeSpan` * [PM-2032] chore: make `StartWebAuthnLoginAssertion` sync * [PM-2032] chore: use `FromMinutes` * [PM-2032] fix: change to 17 minutes to cover webauthn assertion * [PM-2032] chore: do not use `async void` * [PM-2032] fix: comment saying wrong amount of minutes * [PM-2032] feat: put validator behind feature flag * [PM-2032] fix: lint --------- Co-authored-by: Jared Snider <116684653+JaredSnider-Bitwarden@users.noreply.github.com>
This commit is contained in:
@ -1,6 +1,8 @@
|
||||
using Bit.Core;
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
||||
using Bit.Core.Auth.Models.Api.Response.Accounts;
|
||||
using Bit.Core.Auth.Models.Business.Tokenables;
|
||||
using Bit.Core.Auth.Services;
|
||||
using Bit.Core.Auth.Utilities;
|
||||
using Bit.Core.Enums;
|
||||
@ -8,9 +10,9 @@ using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Tokens;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.SharedWeb.Utilities;
|
||||
using Fido2NetLib;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Bit.Identity.Controllers;
|
||||
@ -23,17 +25,21 @@ public class AccountsController : Controller
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly IUserService _userService;
|
||||
private readonly ICaptchaValidationService _captchaValidationService;
|
||||
private readonly IDataProtectorTokenFactory<WebAuthnLoginAssertionOptionsTokenable> _assertionOptionsDataProtector;
|
||||
|
||||
|
||||
public AccountsController(
|
||||
ILogger<AccountsController> logger,
|
||||
IUserRepository userRepository,
|
||||
IUserService userService,
|
||||
ICaptchaValidationService captchaValidationService)
|
||||
ICaptchaValidationService captchaValidationService,
|
||||
IDataProtectorTokenFactory<WebAuthnLoginAssertionOptionsTokenable> assertionOptionsDataProtector)
|
||||
{
|
||||
_logger = logger;
|
||||
_userRepository = userRepository;
|
||||
_userService = userService;
|
||||
_captchaValidationService = captchaValidationService;
|
||||
_assertionOptionsDataProtector = assertionOptionsDataProtector;
|
||||
}
|
||||
|
||||
// Moved from API, If you modify this endpoint, please update API as well. Self hosted installs still use the API endpoints.
|
||||
@ -75,36 +81,19 @@ public class AccountsController : Controller
|
||||
return new PreloginResponseModel(kdfInformation);
|
||||
}
|
||||
|
||||
[HttpPost("webauthn-assertion-options")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)] // Disable Swagger due to CredentialCreateOptions not converting properly
|
||||
[HttpPost("webauthn/assertion-options")]
|
||||
[RequireFeature(FeatureFlagKeys.PasswordlessLogin)]
|
||||
// TODO: Create proper models for this call
|
||||
public async Task<AssertionOptions> PostWebAuthnAssertionOptions([FromBody] PreloginRequestModel model)
|
||||
public WebAuthnLoginAssertionOptionsResponseModel PostWebAuthnLoginAssertionOptions()
|
||||
{
|
||||
var user = await _userRepository.GetByEmailAsync(model.Email);
|
||||
if (user == null)
|
||||
var options = _userService.StartWebAuthnLoginAssertion();
|
||||
|
||||
var tokenable = new WebAuthnLoginAssertionOptionsTokenable(WebAuthnLoginAssertionOptionsScope.Authentication, options);
|
||||
var token = _assertionOptionsDataProtector.Protect(tokenable);
|
||||
|
||||
return new WebAuthnLoginAssertionOptionsResponseModel
|
||||
{
|
||||
// TODO: return something? possible enumeration attacks with this response
|
||||
return new AssertionOptions();
|
||||
}
|
||||
|
||||
var options = await _userService.StartWebAuthnLoginAssertionAsync(user);
|
||||
return options;
|
||||
}
|
||||
|
||||
[HttpPost("webauthn-assertion")]
|
||||
[RequireFeature(FeatureFlagKeys.PasswordlessLogin)]
|
||||
// TODO: Create proper models for this call
|
||||
public async Task<string> PostWebAuthnAssertion([FromBody] PreloginRequestModel model)
|
||||
{
|
||||
var user = await _userRepository.GetByEmailAsync(model.Email);
|
||||
if (user == null)
|
||||
{
|
||||
// TODO: proper response here?
|
||||
throw new BadRequestException();
|
||||
}
|
||||
|
||||
var token = await _userService.CompleteWebAuthLoginAssertionAsync(null, user);
|
||||
return token;
|
||||
Options = options,
|
||||
Token = token
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user