public async Task <CredentialMakeResult> MakeCredential([Required, FromBody] MakeCredentialsRequest request) { using (AuthLogic.Disable()) { var optionsEntity = Database.Retrieve <WebAuthnMakeCredentialsOptionsEntity>(request.CreateOptionsId); var options = CredentialCreateOptions.FromJson(optionsEntity.Json); var result = await fido2.MakeNewCredentialAsync(request.AttestationRawResponse, options, async (args) => { return(!(await Database.Query <WebAuthnCredentialEntity>().AnyAsync(c => c.CredentialId == args.CredentialId))); }); if (result.Status != "ok") { throw new InvalidOperationException(options.ErrorMessage); } new WebAuthnCredentialEntity { CredentialId = result.Result.CredentialId, PublicKey = result.Result.PublicKey, User = Lite.ParsePrimaryKey <UserEntity>(Encoding.UTF8.GetString(result.Result.User.Id)), Counter = (int)result.Result.Counter, CredType = result.Result.CredType, Aaguid = result.Result.Aaguid, }.Save(); return(result); } }
public async Task <JsonResult> MakeCredentialResultTest([FromBody] AuthenticatorAttestationRawResponse attestationResponse) { // 1. get the options we sent the client var jsonOptions = HttpContext.Session.GetString("fido2.attestationOptions"); var options = CredentialCreateOptions.FromJson(jsonOptions); // 2. Create callback so that lib can verify credential id is unique to this user IsCredentialIdUniqueToUserAsyncDelegate callback = async(IsCredentialIdUniqueToUserParams args) => { var users = await DemoStorage.GetUsersByCredentialIdAsync(args.CredentialId); if (users.Count > 0) { return(false); } return(true); }; // 2. Verify and make the credentials var success = await _lib.MakeNewCredentialAsync(attestationResponse, options, callback); // 3. Store the credentials in db DemoStorage.AddCredentialToUser(options.User, new StoredCredential { Descriptor = new PublicKeyCredentialDescriptor(success.Result.CredentialId), PublicKey = success.Result.PublicKey, UserHandle = success.Result.User.Id, SignatureCounter = success.Result.Counter }); // 4. return "ok" to the client return(Json(success)); }
public async Task <JsonResult> MakeCredential([FromBody] AuthenticatorAttestationRawResponse attestationResponse, CancellationToken cancellationToken) { try { // 1. get the options we sent the client var jsonOptions = HttpContext.Session.GetString("fido2.attestationOptions"); var options = CredentialCreateOptions.FromJson(jsonOptions); // 2. Create callback so that lib can verify credential id is unique to this user IsCredentialIdUniqueToUserAsyncDelegate callback = static async(args, cancellationToken) =>
/// <summary> /// 注册:验证用户凭证 /// <para>当客户端返回响应时,我们验证并注册凭据。</para> /// </summary> /// <param name="attestationResponse"></param> public async Task <CredentialMakeResult> RegisterCredentials(User user, string fido2Name, AuthenticatorAttestationRawResponse attestationResponse) { // 1. get the options we sent the client var jsonOptions = distributedCache.GetString(user.UserId.ToString() + "attestationOptions"); if (string.IsNullOrEmpty(jsonOptions)) { return(null); } var options = CredentialCreateOptions.FromJson(jsonOptions); // 2. Create callback so that lib can verify credential id is unique to this user IsCredentialIdUniqueToUserAsyncDelegate callback = async(IsCredentialIdUniqueToUserParams args) => { //var users = await DemoStorage.GetUsersByCredentialIdAsync(args.CredentialId); //if (users.Count > 0) // return false; var argUserId = args.CredentialId; if (this.dataContext.FIDO2Repository.Where(b => b.CredentialId.Equals(argUserId)).Any()) { return(false); } return(true); }; // 2. Verify and make the credentials var success = await _fido2.MakeNewCredentialAsync(attestationResponse, options, callback); // 3. Store the credentials in db //var user = dataContext.User.Where(b => b.UserId == userId).FirstOrDefault(); if (user == null) { return(null); } var fido2 = new FIDO2Item() { Id = IdGenerator.NextId(), UserId = user.UserId, FIDO2Name = fido2Name, CredentialId = success.Result.CredentialId, PublicKey = success.Result.PublicKey, UserHandle = success.Result.User.Id, SignatureCounter = success.Result.Counter, CredType = success.Result.CredType, RegDate = DateTime.Now, AaGuid = success.Result.Aaguid }; dataContext.FIDO2Repository.Add(fido2); dataContext.SaveChanges(); return(success); }
public async Task <ActionResult <CredentialMakeResult> > MakeCredential(AuthenticatorAttestationRawResponse attestationResponse) { try { // 1. get the options we sent the client var jsonOptions = HttpContext.Session.GetString("fido2.attestationOptions"); var options = CredentialCreateOptions.FromJson(jsonOptions); // 2. Create callback so that lib can verify credential id is unique to this user IsCredentialIdUniqueToUserAsyncDelegate callback = async(IsCredentialIdUniqueToUserParams args) => { var credentialIdString = Base64Url.Encode(args.CredentialId); var cred = await context.StoredCredentials.Where(x => x.DescriptorJson.Contains(credentialIdString)).FirstOrDefaultAsync(); if (cred == null) { return(true); } var users = await context.Members.Where(x => x.UserId == cred.UserId).Select(u => new Fido2User { DisplayName = u.DisplayName, Name = u.UserName, Id = u.UserId }).ToListAsync(); return(users.Count == 0); }; // 2. Verify and make the credentials var success = await _fido2.MakeNewCredentialAsync(attestationResponse, options, callback); context.StoredCredentials.Add(new StoredCredential { Descriptor = new PublicKeyCredentialDescriptor(success.Result.CredentialId), UserId = options.User.Id, PublicKey = success.Result.PublicKey, UserHandle = success.Result.User.Id, SignatureCounter = success.Result.Counter, CredType = success.Result.CredType, RegDate = DateTime.Now, AaGuid = success.Result.Aaguid }); await context.SaveChangesAsync(); return(Ok(success)); } catch (Exception e) { return(BadRequest(new CredentialMakeResult { Status = "error", ErrorMessage = FormatException(e) })); } }
public async Task <IActionResult> MakeCredential([FromBody] AuthenticatorAttestationRawResponse attestationResponse) { var o = new { challenge = string.Empty, origin = string.Empty, type = string.Empty }; var username = string.Empty; try { o = JsonConvert.DeserializeAnonymousType((Encoding.UTF8.GetString(attestationResponse.Response.ClientDataJson)), o); var jsonOptions = _memoryCache.Get <string>(o.challenge); var options = CredentialCreateOptions.FromJson(jsonOptions); username = options.User.Name; async Task <bool> Callback(IsCredentialIdUniqueToUserParams args) { var users = await _dataStore.GetUsersByCredentialIdAsync(args.CredentialId); return(users.Count <= 0); } var success = await _lib.MakeNewCredentialAsync(attestationResponse, options, Callback); _dataStore.AddCredentialToUser(options.User, new StoredCredential { Descriptor = new PublicKeyCredentialDescriptor(success.Result.CredentialId), PublicKey = success.Result.PublicKey, UserHandle = success.Result.User.Id, SignatureCounter = success.Result.Counter, CredType = success.Result.CredType, RegDate = DateTime.Now, AaGuid = success.Result.Aaguid }); var ev = new Event(username, "Successfully logged the person in", nameof(RegistrationController), nameof(MakeCredential)); await _elasticClient.IndexAsync(ev, i => i.Index(GetIndexName(nameof(Ok)))); return(Ok(success)); } catch (Exception e) { var errorEvent = new ErrorEvent(e, username, nameof(RegistrationController), nameof(MakeCredential)); await _elasticClient.IndexAsync(errorEvent, i => i.Index(GetIndexName(nameof(Exception)))); return(Ok(new Fido2.CredentialMakeResult { Status = "error", ErrorMessage = FormatException(e) + $"ClientDataJson = {Encoding.UTF8.GetString(attestationResponse.Response.ClientDataJson)}" })); } }
public async Task <ActionResult> MakeCredential([ModelBinder(typeof(NewtonsoftJsonAdapter.Binder))] MakeCredentialRequest request) { var subjectId = User.Claims.FirstOrDefault(c => c.Type == "sub")?.Value; try { // 1. get the options we sent the client var jsonOptions = TestUsers.FidoAttestationOptions[request.SessionId]; var options = CredentialCreateOptions.FromJson(jsonOptions); // 2. Verify and make the credentials var success = await _lib.MakeNewCredentialAsync( attestationResponse : request.AttestationResponse, origChallenge : options, isCredentialIdUniqueToUser : async(IsCredentialIdUniqueToUserParams args) => { var users = TestUsers.FidoCredentials.Where(c => c.Descriptor.Id.SequenceEqual(args.CredentialId)).ToList(); if (users.Count > 0) { return(false); } return(true); }); // 3. Store the credentials in db TestUsers.FidoCredentials.Add(new TestUsers.StoredFidoCredential { UserId = options.User.Id, SubjectId = subjectId, Descriptor = new PublicKeyCredentialDescriptor(success.Result.CredentialId), PublicKey = success.Result.PublicKey, UserHandle = success.Result.User.Id, SignatureCounter = success.Result.Counter, CredType = success.Result.CredType, RegDate = DateTime.Now, AaGuid = success.Result.Aaguid }); // 4. return "ok" to the client return(Ok(success)); } catch (Exception e) { return(BadRequest(new CredentialMakeResult { Status = "error", ErrorMessage = FormatException(e) })); } }
public async Task <IActionResult> CompleteAuthDeviceRegistration( [FromBody] CompleteAuthDeviceRegistrationRequest model) { var jsonOptions = this.TempData["CredentialData"] as string; var options = CredentialCreateOptions.FromJson(jsonOptions); var result = await this._mediator.Send(new EnrollAuthenticatorDeviceCommand( model.Name, model.AttestationResponse, options)); return(this.Json(result.IsFailure ? new CompleteAuthDeviceRegistrationResponse() : new CompleteAuthDeviceRegistrationResponse(result.Value.CredentialMakeResult, result.Value.DeviceId, model.Name))); }
public async Task <ActionResult> MakeCredential( [FromBody] AuthenticatorAttestationRawResponse attestationResponse) { try { // 1. get the options we sent the client var jsonOptions = HttpContext.Session.GetString("fido2.attestationOptions"); var options = CredentialCreateOptions.FromJson(jsonOptions); // 2. Create callback so that lib can verify credential id is unique to this user IsCredentialIdUniqueToUserAsyncDelegate callback = async(IsCredentialIdUniqueToUserParams args) => { var users = await fidoStore.GetUsersByCredentialIdAsync(args.CredentialId); if (users.Count > 0) { return(false); } return(true); }; // 2. Verify and make the credentials var success = await fido2.MakeNewCredentialAsync(attestationResponse, options, callback); // 3. Store the credentials in db fidoStore.AddCredentialToUser(options.User, new StoredCredential { Descriptor = new PublicKeyCredentialDescriptor(success.Result.CredentialId), PublicKey = success.Result.PublicKey, UserHandle = success.Result.User.Id, SignatureCounter = success.Result.Counter, CredType = success.Result.CredType, RegDate = DateTime.Now, AaGuid = success.Result.Aaguid }); // 4. return "ok" to the client return(Ok(success)); } catch (Exception e) { return(BadRequest(new Fido2.CredentialMakeResult { Status = "error", ErrorMessage = FormatException(e) })); } }
public async Task <JsonResult> SaveCredentials([FromBody] AuthenticatorAttestationRawResponse attestationResponse) { try { var jsonOptions = HttpContext.Session.GetString("fido2.attestationOptions"); var options = CredentialCreateOptions.FromJson(jsonOptions); var fidoCredentials = await fido2.MakeNewCredentialAsync(attestationResponse, options, IsCredentialUnique); var storedCredential = new StoredCredential { Descriptor = new PublicKeyCredentialDescriptor(fidoCredentials.Result.CredentialId), PublicKey = fidoCredentials.Result.PublicKey, UserHandle = fidoCredentials.Result.User.Id, SignatureCounter = fidoCredentials.Result.Counter, CredType = fidoCredentials.Result.CredType, RegDate = DateTime.Now, AaGuid = fidoCredentials.Result.Aaguid }; var names = options.User.DisplayName.Split(' '); var result = await oktaClient.Users.CreateUserAsync(new CreateUserWithoutCredentialsOptions { Profile = new UserProfile { Login = options.User.Name, Email = options.User.Name, DisplayName = options.User.DisplayName, FirstName = names[0], LastName = names[1], ["CredentialId"] = Convert.ToBase64String(fidoCredentials.Result.CredentialId), ["PasswordlessPublicKey"] = JsonConvert.SerializeObject(storedCredential) } }); return(Json(fidoCredentials)); } catch (Exception e) { return(Json(new Fido2.CredentialMakeResult { Status = "error", ErrorMessage = e.Message })); } }
public async Task <IActionResult> CompleteAuthDeviceRegistration( [FromBody] CompleteAuthDeviceRegistrationRequest model) { var jsonOptions = this.TempData["CredentialData"] as string; var options = CredentialCreateOptions.FromJson(jsonOptions); var result = await this._mediator.Send(new EnrollDeviceCommand( model.Name, model.AttestationResponse, options)); if (result.IsFailure) { return(this.Json(new Fido2.CredentialMakeResult { Status = "error" })); } return(this.Json(result.Value.CredentialMakeResult)); }
public async Task <bool> CompleteWebAuthRegistrationAsync(User user, int id, string name, AuthenticatorAttestationRawResponse attestationResponse) { var keyId = $"Key{id}"; var provider = user.GetTwoFactorProvider(TwoFactorProviderType.WebAuthn); if (!provider?.MetaData?.ContainsKey("pending") ?? true) { return(false); } var options = CredentialCreateOptions.FromJson((string)provider.MetaData["pending"]); // Callback to ensure credential id is unique. Always return true since we don't care if another // account uses the same 2fa key. IsCredentialIdUniqueToUserAsyncDelegate callback = args => Task.FromResult(true); var success = await _fido2.MakeNewCredentialAsync(attestationResponse, options, callback); provider.MetaData.Remove("pending"); provider.MetaData[keyId] = new TwoFactorProvider.WebAuthnData { Name = name, Descriptor = new PublicKeyCredentialDescriptor(success.Result.CredentialId), PublicKey = success.Result.PublicKey, UserHandle = success.Result.User.Id, SignatureCounter = success.Result.Counter, CredType = success.Result.CredType, RegDate = DateTime.Now, AaGuid = success.Result.Aaguid }; var providers = user.GetTwoFactorProviders(); providers[TwoFactorProviderType.WebAuthn] = provider; user.SetTwoFactorProviders(providers); await UpdateTwoFactorProviderAsync(user, TwoFactorProviderType.WebAuthn); return(true); }
public async Task <JsonResult> MakeCredential([FromBody] AuthenticatorAttestationRawResponse authenticatorAttestationRawResponse) { try { var user = await _userManager.GetUserAsync(User); if (user == null) { throw new Exception("Unable to retrieve user."); } var jsonOptions = await _distributedCache.GetStringAsync(UniqueId); if (string.IsNullOrEmpty(jsonOptions)) { throw new Exception("Cant get Credential options from cache."); } var options = CredentialCreateOptions.FromJson(jsonOptions); IsCredentialIdUniqueToUserAsyncDelegate isCredentialIdUniqueToUserAsyncDelegate = async(IsCredentialIdUniqueToUserParams isCredentialIdUniqueToUserParams) => { var fido2Users = await _fido2Service.GetFido2UsersByCredentialIdAsync(isCredentialIdUniqueToUserParams.CredentialId); if (fido2Users.Count > 0) { return(false); } return(true); }; var result = await _fido2.MakeNewCredentialAsync(authenticatorAttestationRawResponse, options, isCredentialIdUniqueToUserAsyncDelegate); if (result.Status != "ok") { throw new Exception("Unable to create credential."); } var newFido2StoredCredential = new Fido2StoredCredential { }; newFido2StoredCredential.UserName = options.User.Name; newFido2StoredCredential.UserId = options.User.Id; newFido2StoredCredential.PublicKey = result.Result.PublicKey; newFido2StoredCredential.UserHandle = result.Result.User.Id; newFido2StoredCredential.SignatureCounter = result.Result.Counter; newFido2StoredCredential.CredType = result.Result.CredType; newFido2StoredCredential.RegDate = DateTime.Now; newFido2StoredCredential.AaGuid = Guid.NewGuid(); newFido2StoredCredential.Descriptor = new PublicKeyCredentialDescriptor(result.Result.CredentialId); _fido2Service.AddFido2StoredCredential(newFido2StoredCredential); return(Json(result)); } catch (Exception exception) { return(Json(new CredentialCreateOptions() { Status = "error", ErrorMessage = CommonFunctions.FormatException(exception) })); } }
public async Task <IActionResult> RegisterCallback([FromBody] AuthenticatorAttestationRawResponse model) { var sub = HttpContext.User.Claims.FirstOrDefault(x => x.Type == "sub")?.Value; if (string.IsNullOrEmpty(sub)) { return(RedirectToAction("Index", "Home")); } var user = await _users.FindByIdAsync(sub); if (user == null) { return(RedirectToAction("Index", "Home")); } try { // 1. get the options we sent the client var jsonOptions = HttpContext.Session.GetString("fido2.attestationOptions"); var options = CredentialCreateOptions.FromJson(jsonOptions); var authenticatorName = HttpContext.Session.GetString("fido2.attestationOptions.authenticatorType"); // 2. Create callback so that lib can verify credential id is unique to this user IsCredentialIdUniqueToUserAsyncDelegate callback = async(IsCredentialIdUniqueToUserParams args) => { var users = _authContext.FidoLogins.Where(l => l.PublicKeyIdBytes.SequenceEqual(args.CredentialId)); if (users.Count() > 0) { return(false); } return(true); }; // 2. Verify and make the credentials var success = await _lib.MakeNewCredentialAsync(model, options, callback); var parsedResponse = AuthenticatorAttestationResponse.Parse(model);; var authData = new AuthenticatorData(parsedResponse.AttestationObject.AuthData); var dbUser = _authContext.Users.First(x => x.Id == user.Id); dbUser.TwoFactorEnabled = true; var login = new FidoLogin() { PublicKeyIdBytes = success.Result.CredentialId, PublicKeyId = Fido2NetLib.Base64Url.Encode(success.Result.CredentialId), AaGuid = success.Result.Aaguid.ToString(), PublicKey = success.Result.PublicKey, SignatureCounter = success.Result.Counter, CredType = success.Result.CredType, RegistrationDate = DateTime.Now, User = dbUser, UserHandle = success.Result.User.Id, AuthenticatorName = authenticatorName }; _authContext.FidoLogins.Add(login); _authContext.SaveChanges(); // 4. return "ok" to the client return(Json(new { success = true })); } catch (Exception e) { return(Json(new { error = true })); } }
public async Task <JsonResult> MakeCredential([FromBody] AuthenticatorAttestationRawResponse attestationResponse) { try { // 1. get the options we sent the client var jsonOptions = HttpContext.Session.GetString("fido2.attestationOptions"); var options = CredentialCreateOptions.FromJson(jsonOptions); // 2. Create callback so that lib can verify credential id is unique to this user IsCredentialIdUniqueToUserAsyncDelegate callback = async(IsCredentialIdUniqueToUserParams args) => { var users = await _fido2Storage.GetUsersByCredentialIdAsync(args.CredentialId); if (users.Count > 0) { return(false); } return(true); }; // 2. Verify and make the credentials var success = await _lib.MakeNewCredentialAsync(attestationResponse, options, callback); // 3. Store the credentials in db await _fido2Storage.AddCredentialToUser(options.User, new FidoStoredCredential { Username = options.User.Name, Descriptor = new PublicKeyCredentialDescriptor(success.Result.CredentialId), PublicKey = success.Result.PublicKey, UserHandle = success.Result.User.Id, SignatureCounter = success.Result.Counter, CredType = success.Result.CredType, RegDate = DateTime.Now, AaGuid = success.Result.Aaguid }); // 4. return "ok" to the client var user = await _userManager.GetUserAsync(User); if (user == null) { return(Json(new CredentialMakeResult { Status = "error", ErrorMessage = _sharedLocalizer["FIDO2_USER_NOTFOUND", _userManager.GetUserId(User)] })); } await _userManager.SetTwoFactorEnabledAsync(user, true); var userId = await _userManager.GetUserIdAsync(user); return(Json(success)); } catch (Exception e) { return(Json(new CredentialMakeResult { Status = "error", ErrorMessage = FormatException(e) })); } }
public async Task <JsonResult> MakeCredential([FromBody] AuthenticatorAttestationRawResponse attestationResponse) { try { // 1. get the options we sent the client //var jsonOptions = HttpContext.Session.GetString("fido2.attestationOptions"); var jsonOptions = await _distributedCache.GetStringAsync(UniqueId); if (string.IsNullOrEmpty(jsonOptions)) { throw new Exception("Can't get CredentialOptions from cache"); } var options = CredentialCreateOptions.FromJson(jsonOptions); // 2. Create callback so that lib can verify credential id is unique to this user IsCredentialIdUniqueToUserAsyncDelegate callback = async(IsCredentialIdUniqueToUserParams args) => { var users = await _fido2Storage.GetUsersByCredentialIdAsync(args.CredentialId); if (users.Count > 0) { return(false); } return(true); }; // 2. Verify and make the credentials var success = await _lib.MakeNewCredentialAsync(attestationResponse, options, callback); // 3. Store the credentials in db await _fido2Storage.AddCredentialToUser(options.User, new FidoStoredCredential { Username = options.User.Name, Descriptor = new PublicKeyCredentialDescriptor(success.Result.CredentialId), PublicKey = success.Result.PublicKey, UserHandle = success.Result.User.Id, SignatureCounter = success.Result.Counter, CredType = success.Result.CredType, RegDate = DateTime.Now, AaGuid = success.Result.Aaguid }); // 4. return "ok" to the client var user = await _userManager.GetUserAsync(User); if (user == null) { return(Json(new CredentialMakeResult { Status = "error", ErrorMessage = $"Unable to load user with ID '{_userManager.GetUserId(User)}'." })); } await _userManager.SetTwoFactorEnabledAsync(user, true); if (await _userManager.CountRecoveryCodesAsync(user) == 0) { var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); RecoveryCodes = recoveryCodes.ToArray(); } return(Json(success)); } catch (Exception e) { return(Json(new CredentialMakeResult { Status = "error", ErrorMessage = FormatException(e) })); } }
public async Task <JsonResult> MakeCredential([FromBody] AuthenticatorAttestationRawResponse attestationResponse) { try { // 1. get the options we sent the client var jsonOptions = HttpContext.Session.GetString("fido2.attestationOptions"); var options = CredentialCreateOptions.FromJson(jsonOptions); // 2. Create callback so that lib can verify credential id is unique to this user // IsCredentialIdUniqueToUserAsyncDelegate callback = async (IsCredentialIdUniqueToUserParams args) => // { // // var users = await DemoStorage.GetUsersByCredentialIdAsync(args.CredentialId); // var users = await _fido2CredentialService.GetUsersByCredentialIdAsync(args.CredentialId); // if (users.Count > 0) // return false; // // return true; // }; IsCredentialIdUniqueToUserAsyncDelegate callback = async(IsCredentialIdUniqueToUserParams args) => { // TODO Check if credentials are unique return(true); }; // 2. Verify and make the credentials var success = await _fido2.MakeNewCredentialAsync(attestationResponse, options, callback); var applicationUser = await _userManager.GetUserAsync(HttpContext.User); // Schreibe die Credentials in die Datenbank var newFido2Credential = await _fido2CredentialService.AddCredentialToUser(new Fido2Credential() { UserId = applicationUser.Id, Descriptor = success.Result.CredentialId, PublicKey = success.Result.PublicKey, UserHandle = success.Result.User.Id, SignatureCounter = success.Result.Counter, CredType = success.Result.CredType, RegDate = DateTime.Now, AaGuid = success.Result.Aaguid }); // applicationUser.Fido2Credentials.Add(newFido2Credential); applicationUser.TwoFactorEnabled = true; applicationUser.TwoFactorMethod = TwoFactorType.Fido2; await _userManager.UpdateAsync(applicationUser); // TODO Return Databse Entry not just JSON // 4. return "ok" to the client return(new JsonResult(success)); } catch (Exception e) { return(new JsonResult(new Fido2.CredentialMakeResult { Status = "error", ErrorMessage = FormatException(e) })); } }