Example #1
0
        // TODO: change return type
        public async Task <ITransitionResult> RunAsync(ITransitionInput input, StepType currentStep)
        {
            var item = await _cacheItemRepository.GetAsync(input.Context);

            input.IsDesktop = item.IsDesktop;
            return(await Flows[item.FlowType].RunAsync(input, currentStep, item));
        }
        public async Task <Fido2Settings> ExecuteAsync(string context, string requestToken, string locale)
        {
            var item = await _cacheItemRepository.GetAsync(context);

            if (item.RequestToken != requestToken)
            {
                throw new CommandValidationException(
                          $"Can not provide settings for FIDO2. Wrong nonce actual '{requestToken}' expected '{item.ResponseToken}'");
            }

            if (item.Status != CacheItemStatus.Approved && item.Status != CacheItemStatus.Initiated &&
                item.Status != CacheItemStatus.Started)
            {
                throw new CommandValidationException(
                          $"Can not provide settings for FIDO2. Wrong item status {item.Status}");
            }

            var url = _urlProvider.GetWebAppSignWithCallbackUrl(_urlProvider.GetStartFlowUrl(context), locale,
                                                                item.RequestToken, item.ResponseToken);

            return(new Fido2Settings
            {
                CredId = item.Fido2CredentialId,
                UserName = _ownIdCoreConfiguration.Fido2.UserName,
                UserDisplayName = _ownIdCoreConfiguration.Fido2.UserDisplayName,
                RelyingPartyId = _ownIdCoreConfiguration.Fido2.RelyingPartyId,
                RelyingPartyName = _ownIdCoreConfiguration.Fido2.RelyingPartyName,
                CallbackUrl = url.ToString(),
                LogLevel = ((int)_ownIdCoreConfiguration.LogLevel).ToString(),
                LogoUrl = _ownIdCoreConfiguration.LogoUrl?.ToString()
            });
        }
        public async Task <object> ExecuteAsync(ExchangeMagicLinkRequest request)
        {
            if (string.IsNullOrWhiteSpace(request.Context) || string.IsNullOrWhiteSpace(request.MagicToken))
            {
                throw new CommandValidationException("Magic link required params were not provided");
            }

            if (_magicLinkConfiguration.SameBrowserUsageOnly && string.IsNullOrWhiteSpace(request.CheckToken))
            {
                return(CreateErrorResult("Error_MagicLink_SameBrowser"));
            }

            var cacheItem = await _cacheItemRepository.GetAsync(request.Context);

            if (_magicLinkConfiguration.SameBrowserUsageOnly && request.CheckToken
                != SendMagicLinkCommand.GetCheckToken(request.Context, request.MagicToken, cacheItem.DID))
            {
                return(CreateErrorResult("Error_MagicLink_SameBrowser"));
            }

            if (cacheItem.Payload != request.MagicToken)
            {
                throw new CommandValidationException("Magic link wrong MagicToken");
            }

            var result = await _userHandlerAdapter.OnSuccessLoginAsync(cacheItem.DID, null);

            await _cacheItemRepository.RemoveAsync(request.Context);

            return(result);
        }
Example #4
0
        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
                }
            });
        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);
        }