public async Task ExecuteAsync(UserIdentitiesData input, CacheItem relatedItem) { var recoveryToken = !string.IsNullOrEmpty(input.RecoveryData) ? Guid.NewGuid().ToString("N") : null; // Credentials created at web app if (input.ActualChallengeType.HasValue && input.ActualChallengeType != relatedItem.ChallengeType) { relatedItem.ChallengeType = input.ActualChallengeType.Value; } // check if users exists or not. If not - then this is LinkOnLogin else if (relatedItem.ChallengeType == ChallengeType.Login) { var isUserExists = await _userHandlerAdapter.IsUserExistsAsync(input.PublicKey); if (!isUserExists) { relatedItem.ChallengeType = ChallengeType.LinkOnLogin; } } await _cacheItemRepository.UpdateAsync(relatedItem.Context, item => { item.ChallengeType = relatedItem.ChallengeType; item.RecoveryToken = recoveryToken; item.RecoveryData = input.RecoveryData; item.FinishFlow(input.DID, input.PublicKey); }); }
public async Task <bool> ExecuteAsync(UserIdentification input) { // Do nothing for recovery flow // var relatedItem = await _cacheItemService.GetCacheItemByContextAsync(input.Context); // if (relatedItem.ChallengeType == ChallengeType.Recover) // return false; bool result; if (string.IsNullOrWhiteSpace(input.UserIdentifier)) { result = false; } else if (!input.AuthenticatorType.HasValue) { result = await _userHandlerAdapter.IsUserExistsAsync(input.UserIdentifier); } else { result = input.AuthenticatorType switch { ExtAuthenticatorType.Fido2 => await _userHandlerAdapter.IsFido2UserExistsAsync(input.UserIdentifier), _ => false } }; return(result); }
public async Task <AuthResult> ExecuteAsync(AddConnectionRequest request) { var cacheItem = await _cacheItemRepository.GetAsync(request.Context); if (cacheItem.Nonce != request.Nonce || cacheItem.Status != CacheItemStatus.Popped) { throw new CommandValidationException( $"No cacheItem with context {request.Context} and nonce {request.Nonce}"); } if (cacheItem.FlowType != FlowType.Fido2Register && cacheItem.FlowType != FlowType.PartialAuthorize) { throw new CommandValidationException($"Wrong flow type {cacheItem.FlowType}"); } var connectionState = await _accountLinkHandler.GetCurrentUserLinkStateAsync(request.Payload); if (connectionState.ConnectedDevicesCount >= _coreConfiguration.MaximumNumberOfConnectedDevices) { return(new AuthResult(_localizationService.GetLocalizedString("Error_PhoneAlreadyConnected"))); } var connectionExists = !string.IsNullOrEmpty(cacheItem.Fido2CredentialId) ? await _userHandlerAdapter.IsFido2UserExistsAsync(cacheItem.Fido2CredentialId) : await _userHandlerAdapter.IsUserExistsAsync(cacheItem.PublicKey); if (connectionExists) { return(new AuthResult("Can not add connection. Connection already exists")); } await _accountLinkHandler.OnLinkAsync(connectionState.DID, new OwnIdConnection { Fido2CredentialId = cacheItem.Fido2CredentialId, Fido2SignatureCounter = cacheItem.Fido2SignatureCounter.ToString(), PublicKey = cacheItem.PublicKey, RecoveryToken = cacheItem.RecoveryToken, RecoveryData = cacheItem.RecoveryData, AuthType = cacheItem.AuthCookieType switch { CookieType.Fido2 => ConnectionAuthType.Fido2, CookieType.Passcode => ConnectionAuthType.Passcode, _ => ConnectionAuthType.Basic } });
public async Task <CacheItem> ExecuteAsync(JwtContainer input, CacheItem relatedItem) { var userData = _jwtService.GetDataFromJwt <UserIdentitiesData>(input.Jwt).Data; if (relatedItem.ChallengeType == ChallengeType.Link && relatedItem.DID != userData.DID) { throw new CommandValidationException($"Wrong user for linking {userData.DID}"); } var userExists = await _userHandlerAdapter.IsUserExistsAsync(userData.PublicKey); if (userExists) { throw new OwnIdException(ErrorType.UserAlreadyExists); } // preventing data substitution userData.DID = relatedItem.DID; // TODO: code duplication var recoveryToken = !string.IsNullOrEmpty(userData.RecoveryData) ? Guid.NewGuid().ToString("N") : null; var connection = new OwnIdConnection { PublicKey = userData.PublicKey, RecoveryToken = recoveryToken, RecoveryData = userData.RecoveryData, AuthType = relatedItem.AuthCookieType switch { CookieType.Fido2 => ConnectionAuthType.Fido2, CookieType.Passcode => ConnectionAuthType.Passcode, _ => ConnectionAuthType.Basic } }; await _linkHandler.OnLinkAsync(userData.DID, connection); return(await _cacheItemRepository.UpdateAsync(relatedItem.Context, item => { item.RecoveryToken = recoveryToken; item.RecoveryData = userData.RecoveryData; item.FinishFlow(userData.DID, userData.PublicKey); })); }
private async Task <GetStatusResponse> GetContextStatus(GetStatusRequest requestItem) { if (string.IsNullOrEmpty(requestItem.Context) || string.IsNullOrEmpty(requestItem.Nonce)) { return(null); } var cacheItem = await _cacheItemRepository.GetAsync(requestItem.Context, false); if (cacheItem == null || cacheItem.Nonce != requestItem.Nonce || cacheItem.Status == CacheItemStatus.Popped) { return(null); } var result = new GetStatusResponse { Status = cacheItem.Status, Context = requestItem.Context }; if (cacheItem.SecurityCode != null && cacheItem.Status == CacheItemStatus.WaitingForApproval) { // TODO: refactor to entity result.Payload = new { data = new { pin = cacheItem.SecurityCode } } } ; if (cacheItem.Status != CacheItemStatus.Finished) { return(result); } await _cacheItemRepository.UpdateAsync(cacheItem.Context, item => { item.Status = CacheItemStatus.Popped; }); if (!string.IsNullOrEmpty(cacheItem.Error)) { result.Payload = new AuthResult <object>(_localizationService.GetLocalizedString(cacheItem.Error)); return(result); } var action = cacheItem.ChallengeType.ToString(); if (cacheItem.FlowType == FlowType.Authorize) { result.Payload = await _userHandlerAdapter.OnSuccessLoginAsync(cacheItem.DID, cacheItem.PublicKey); } else { switch (cacheItem.ChallengeType) { case ChallengeType.Login when cacheItem.FlowType == FlowType.Fido2Login && string.IsNullOrWhiteSpace(cacheItem.Fido2CredentialId): { var errorMessage = _localizationService.GetLocalizedString("Error_UserNotFound"); result.Payload = new AuthResult <object>(errorMessage); break; } case ChallengeType.Login when !string.IsNullOrWhiteSpace(cacheItem.Fido2CredentialId) && cacheItem.Fido2SignatureCounter.HasValue: { result.Payload = await _userHandlerAdapter.OnSuccessLoginByFido2Async( cacheItem.Fido2CredentialId, cacheItem.Fido2SignatureCounter.Value); break; } case ChallengeType.Login: result.Payload = await _userHandlerAdapter.OnSuccessLoginByPublicKeyAsync(cacheItem.PublicKey); break; case ChallengeType.LinkOnLogin: action = ChallengeType.Link.ToString(); result.Payload = SetPartialRegisterResult(cacheItem); break; case ChallengeType.Register when await _userHandlerAdapter.IsUserExistsAsync(cacheItem.PublicKey): { var errorMessage = _localizationService.GetLocalizedString("Error_PhoneAlreadyConnected"); result.Payload = new AuthResult <object>(errorMessage); return(result); } case ChallengeType.Register when string.IsNullOrWhiteSpace(cacheItem.Fido2CredentialId): { result.Payload = SetPartialRegisterResult(cacheItem); break; } case ChallengeType.Register: result.Payload = new { data = new { pubKey = cacheItem.PublicKey, fido2SignatureCounter = cacheItem.Fido2SignatureCounter.ToString(), fido2CredentialId = cacheItem.Fido2CredentialId } }; if (cacheItem.InitialChallengeType == ChallengeType.Login && cacheItem.ChallengeType == ChallengeType.Register) { action = ChallengeType.Link.ToString(); } break; // // TODO: fix needed at web-ui-sdk to avoid error in console if data is undefined // case ChallengeType.Recover: case ChallengeType.Link: result.Payload = new { data = new { } }; break; } } result.Metadata = _jwtService.GenerateDataJwt(new Dictionary <string, object> { { "data", new { action, authType = cacheItem.GetAuthType() } } }); return(result); }