protected override async Task <ITransitionResult> ExecuteInternalAsync(TransitionInput <JwtContainer> input,
                                                                               CacheItem relatedItem)
        {
            var userData = _jwtService.GetDataFromJwt <UserIdentitiesData>(input.Data.Jwt).Data;

            relatedItem.AuthCookieType = CookieType.Passcode;

            await _savePartialConnectionCommand.ExecuteAsync(userData, relatedItem);

            await _userHandlerAdapter.UpgradeConnectionAsync(userData.PublicKey, new OwnIdConnection
            {
                AuthType      = ConnectionAuthType.Passcode,
                PublicKey     = userData.PublicKey,
                RecoveryData  = userData.RecoveryData,
                RecoveryToken = relatedItem.RecoveryToken
            });

            var composeInfo = new BaseJwtComposeInfo(input)
            {
                Behavior = GetNextBehaviorFunc(input, relatedItem)
            };
            var jwt = JwtComposer.GenerateFinalStepJwt(composeInfo);

            return(new StateResult(jwt, _cookieService.CreateAuthCookies(relatedItem)));
        }
Пример #2
0
        protected override async Task <ITransitionResult> ExecuteInternalAsync(TransitionInput <JwtContainer> input,
                                                                               CacheItem relatedItem)
        {
            var userData = _jwtService.GetDataFromJwt <UserIdentitiesData>(input.Data.Jwt).Data;

            // Process registration
            if (relatedItem.ChallengeType == ChallengeType.Register)
            {
                return(await FinishAuthProcessAsync(userData, relatedItem, input));
            }

            // Check if user settings override global one
            var settings = await _userHandlerAdapter.GetUserSettingsAsync(userData.PublicKey);

            if (
                _configuration.TFAEnabled == false &&
                settings?.EnforceTFA == true &&
                userData.AuthType == ConnectionAuthType.Basic)
            {
                return(await SwitchConnectionAuthTypeAsync(relatedItem, input, userData.SupportsFido2,
                                                           userData.PublicKey));
            }

            return(await FinishAuthProcessAsync(userData, relatedItem, input));
        }
        protected override async Task <ITransitionResult> ExecuteInternalAsync(TransitionInput <StartRequest> input,
                                                                               CacheItem relatedItem)
        {
            var wasContinued = CheckIfContinued(input, relatedItem);
            var composeInfo  = new BaseJwtComposeInfo(input)
            {
                Behavior         = GetNextBehaviorFunc(input, relatedItem),
                IncludeRequester = true
            };

            var jwt = JwtComposer.GenerateBaseStepJwt(composeInfo, IdentitiesProvider.GenerateUserId());

            if (!wasContinued)
            {
                await StartFlowCommand.ExecuteAsync(new StartFlowCommand.Input
                {
                    Context                    = input.Context,
                    ResponseJwt                = jwt,
                    CredIdCookieValue          = input.Data.CredId,
                    EncryptionTokenCookieValue = input.Data.EncryptionToken,
                    RecoveryTokenCookieValue   = input.Data.RecoveryToken,
                    RequestToken               = input.RequestToken
                });
            }

            return(new JwtContainer
            {
                Jwt = jwt
            });
        }
        protected override async Task <ITransitionResult> ExecuteInternalAsync(TransitionInput <string> input,
                                                                               CacheItem relatedItem)
        {
            relatedItem = await _fido2LinkCommand.ExecuteAsync(input.Data, relatedItem);

            return(GenerateResult(input, relatedItem));
        }
 protected override void Validate(TransitionInput<JwtContainer> input, CacheItem relatedItem)
 {
     if (!relatedItem.IsValidForLink)
         throw new CommandValidationException(
             "Cache item should be not Finished with Link challenge type. " +
             $"Actual Status={relatedItem.Status.ToString()} ChallengeType={relatedItem.ChallengeType}");
 }
        protected override async Task ExecuteAsync(HttpContext httpContext)
        {
            var input = new TransitionInput(RequestIdentity, GetRequestCulture(httpContext), ClientDate);

            var result = await _flowRunner.RunAsync(input, StepType.InternalConnectionRecovery);

            await JsonAsync(httpContext, result, StatusCodes.Status200OK);
        }
        protected override void Validate(TransitionInput <string> input, CacheItem relatedItem)
        {
            base.Validate(input, relatedItem);

            if (string.IsNullOrEmpty(relatedItem.DID))
            {
                throw new CommandValidationException("No user DID was found for recovery");
            }
        }
Пример #8
0
 protected override void Validate(TransitionInput <JwtContainer> input, CacheItem relatedItem)
 {
     if (!relatedItem.IsValidForAuthorize)
     {
         throw new CommandValidationException(
                   "Cache item should be not be Finished with PARTIAL Login or Register challenge type. "
                   + $"Actual Status={relatedItem.Status.ToString()} ChallengeType={relatedItem.ChallengeType.ToString()}");
     }
 }
 private FrontendBehavior NavigateToEnterPasscode(TransitionInput <AcceptStartRequest> input,
                                                  CacheItem relatedItem)
 {
     return(new(StepType.EnterPasscode, relatedItem.ChallengeType,
                GetNextBehaviorFunc(input, relatedItem))
     {
         AlternativeBehavior = new FrontendBehavior(StepType.ResetPasscode, relatedItem.ChallengeType,
                                                    new CallAction(UrlProvider.GetResetPasscodeUrl(relatedItem.Context),
                                                                   HttpMethod.Delete.ToString()))
     });
        private async Task <FrontendBehavior> NavigateToPasswordlessPageAsync(TransitionInput <AcceptStartRequest> input,
                                                                              CacheItem relatedItem)
        {
            await _verifyFido2CredentialIdCommand.ExecuteAsync(relatedItem);

            var fido2Url = UrlProvider.GetFido2Url(relatedItem.Context, relatedItem.RequestToken,
                                                   input.CultureInfo?.Name);

            return(FrontendBehavior.CreateRedirect(fido2Url));
        }
        protected override async Task ExecuteAsync(HttpContext httpContext)
        {
            var request = await OwnIdSerializer.DeserializeAsync <UserIdentification>(httpContext.Request.Body);

            var commandInput = new TransitionInput <UserIdentification>(RequestIdentity, GetRequestCulture(httpContext),
                                                                        request, ClientDate);

            var result = await _flowRunner.RunAsync(commandInput, StepType.CheckUserExistence);

            await JsonAsync(httpContext, result, StatusCodes.Status200OK);
        }
Пример #12
0
        private FrontendBehavior OnSuccess(TransitionInput <string> _, CacheItem item)
        {
            var challengeType = item.ChallengeType;

            if (item.ChallengeType == ChallengeType.Register && item.InitialChallengeType == ChallengeType.Login)
            {
                challengeType = ChallengeType.LinkOnLogin;
            }

            return(FrontendBehavior.CreateSuccessFinish(challengeType));
        }
Пример #13
0
        protected override async Task <ITransitionResult> ExecuteInternalAsync(TransitionInput <AcceptStartRequest> input,
                                                                               CacheItem relatedItem)
        {
            // TODO: rework preventing fido2 to use recovery link second time
            if (!input.Data.SupportsFido2 || string.IsNullOrEmpty(input.Data.ExtAuthPayload) || string.IsNullOrEmpty(relatedItem.DID))
            {
                relatedItem = await _recoverAccountCommand.ExecuteAsync(relatedItem);
            }

            return(await base.ExecuteInternalAsync(input, relatedItem));
        }
Пример #14
0
        protected override async Task ExecuteAsync(HttpContext httpContext)
        {
            var request = await OwnIdSerializer.DeserializeAsync <AcceptStartRequest>(httpContext.Request.Body);

            var input = new TransitionInput <AcceptStartRequest>(RequestIdentity, GetRequestCulture(httpContext),
                                                                 request, ClientDate);

            var result = await _flowRunner.RunAsync(input, StepType.AcceptStart);

            await JsonAsync(httpContext, result, StatusCodes.Status200OK);
        }
        protected override void Validate(TransitionInput <StartRequest> input, CacheItem relatedItem)
        {
            var wasContinued = CheckIfContinued(input, relatedItem);

            if (wasContinued && relatedItem.RequestToken != input.RequestToken &&
                relatedItem.ResponseToken != input.ResponseToken)
            {
                throw new CommandValidationException(
                          $"Can not continue flow with bypass. Wrong request token actual '{input.RequestToken}' expected '{relatedItem.RequestToken}' or response token actual '{input.ResponseToken}' expected '{relatedItem.ResponseToken}'");
            }
        }
Пример #16
0
        protected override void Validate(TransitionInput <AcceptStartRequest> input, CacheItem relatedItem)
        {
            base.Validate(input, relatedItem);

            if (!relatedItem.IsValidForRecover)
            {
                throw new CommandValidationException(
                          "Cache item should be not Finished with Recover challenge type. " +
                          $"Actual Status={relatedItem.Status.ToString()} ChallengeType={relatedItem.ChallengeType}");
            }
        }
Пример #17
0
        private FrontendBehavior GetOnStartAcceptBehavior(TransitionInput <AcceptStartRequest> input,
                                                          CacheItem cacheItem)
        {
            // Recover connection if there is no such but recovery token is available
            if (!input.Data.AuthType.HasValue && !string.IsNullOrEmpty(cacheItem.RecoveryToken))
            {
                return(GetReferenceToExistingStep(StepType.InternalConnectionRecovery, cacheItem.Context,
                                                  cacheItem.ChallengeType));
            }

            return(GetOnRecoveryConnectionPassedBehavior(cacheItem));
        }
Пример #18
0
        protected StateResult GenerateResult(TransitionInput <string> input, CacheItem relatedItem)
        {
            var composeInfo = new BaseJwtComposeInfo(input)
            {
                Behavior = GetNextBehaviorFunc(input, relatedItem),
            };

            var jwt = JwtComposer.GenerateBaseStepJwt(composeInfo, relatedItem.DID);

            //TODO: add remove other cookies
            return(new StateResult(jwt, _cookieService.CreateAuthCookies(relatedItem)));
        }
        protected override async Task ExecuteAsync(HttpContext httpContext)
        {
            var jwtContainer = await GetRequestJwtContainerAsync(httpContext);

            var commandInput = new TransitionInput <JwtContainer>(RequestIdentity,
                                                                  GetRequestCulture(httpContext),
                                                                  jwtContainer, ClientDate);

            var result = await _flowRunner.RunAsync(commandInput, StepType.UpgradeToPasscode);

            await JsonAsync(httpContext, result, StatusCodes.Status200OK);
        }
Пример #20
0
        private FrontendBehavior OnSuccess <T>(TransitionInput <T> _, CacheItem item)
        {
            var challengeType = item.ChallengeType;

            if (item.ChallengeType == ChallengeType.Register && item.InitialChallengeType == ChallengeType.Login &&
                !CoreConfiguration.LoginOnlyEnabled)
            {
                challengeType = ChallengeType.LinkOnLogin;
            }

            return(FrontendBehavior.CreateSuccessFinish(challengeType));
        }
        protected override async Task<ITransitionResult> ExecuteInternalAsync(TransitionInput<JwtContainer> input,
            CacheItem relatedItem)
        {
            relatedItem = await _linkAccountCommand.ExecuteAsync(input.Data, relatedItem);

            var composeInfo = new BaseJwtComposeInfo(input)
            {
                Behavior = GetNextBehaviorFunc(input, relatedItem),
            };

            // TODO: change to generic step generation
            var jwt = JwtComposer.GenerateFinalStepJwt(composeInfo);
            return new StateResult(jwt, _cookieService.CreateAuthCookies(relatedItem));
        }
Пример #22
0
        protected override void Validate(TransitionInput <JwtContainer> input, CacheItem relatedItem)
        {
            if (!relatedItem.IsValidForRecover)
            {
                throw new CommandValidationException(
                          "Cache item should be not Finished with Recover challenge type. " +
                          $"Actual Status={relatedItem.Status.ToString()} ChallengeType={relatedItem.ChallengeType}");
            }

            if (string.IsNullOrEmpty(relatedItem.DID))
            {
                throw new CommandValidationException("User DID was not recovered with RecoverAccountCommand");
            }
        }
Пример #23
0
        private async Task <ITransitionResult> FinishAuthProcessAsync(UserIdentitiesData userData, CacheItem relatedItem,
                                                                      TransitionInput <JwtContainer> input)
        {
            await _savePartialConnectionCommand.ExecuteAsync(userData, relatedItem);

            var composeInfo = new BaseJwtComposeInfo(input)
            {
                Behavior = FrontendBehavior.CreateSuccessFinish(relatedItem.ChallengeType)
            };

            var jwt = JwtComposer.GenerateFinalStepJwt(composeInfo);

            return(new StateResult(jwt, _cookieService.CreateAuthCookies(relatedItem)));
        }
        protected override async Task <ITransitionResult> ExecuteInternalAsync(TransitionInput <JwtContainer> input,
                                                                               CacheItem relatedItem)
        {
            var userData = _jwtService.GetDataFromJwt <UserIdentitiesData>(input.Data.Jwt).Data;

            await _savePartialConnectionCommand.ExecuteAsync(userData, relatedItem);

            var composeInfo = new BaseJwtComposeInfo(input)
            {
                Behavior = GetNextBehaviorFunc(input, relatedItem),
            };
            var jwt = JwtComposer.GenerateFinalStepJwt(composeInfo);

            return(new StateResult(jwt, _cookieService.CreateAuthCookies(relatedItem)));
        }
        internal static JsonObject Generate(TransitionInput transitionInput, ServerInfo serverInfo)
        {
            var jsonObject = new JsonObject();

            if (serverInfo.BuildNumber >= ServerVersionConstants.BuildNumberJira5)
            {
                var id = new JsonObject {
                    { "id", transitionInput.Id.ToString() }
                };
                jsonObject.Add("transition", id.ToJson());
            }
            else
            {
                jsonObject.Add("transition", transitionInput.Id.ToString());
            }

            if (transitionInput.Comment != null)
            {
                var comment = CommentJsonGenerator.Generate(transitionInput.Comment, serverInfo).ToJson();
                if (serverInfo.BuildNumber >= ServerVersionConstants.BuildNumberJira5)
                {
                    var jsonComment = new JsonArrayObjects {
                        new JsonObject {
                            { "add", comment }
                        }
                    };
                    var jsonUpdate = new JsonObject {
                        { "comment", jsonComment.ToJson() }
                    };
                    jsonObject.Add("update", jsonUpdate.ToJson());
                }
                else
                {
                    jsonObject.Add("comment", comment);
                }
            }

            if (transitionInput.Fields != null && transitionInput.Fields.Any())
            {
                var list = transitionInput.Fields.Where(f => f.Value != null).ToDictionary(f => f.Id, f => ComplexIssueInputFieldValueJsonGenerator.GenerateFieldValueForJson(f.Value));
                jsonObject.Add("fields", list.ToJson());
            }

            return(jsonObject);
        }
        protected FrontendBehavior TryAddFido2DisclaimerToBehavior(TransitionInput <AcceptStartRequest> input,
                                                                   CacheItem relatedItem, FrontendBehavior expectedBehavior)
        {
            if (CoreConfiguration.TFAEnabled && CoreConfiguration.Fido2FallbackBehavior == Fido2FallbackBehavior.Basic &&
                !input.Data.SupportsFido2 &&
                relatedItem.ChallengeType != ChallengeType.Login)
            {
                return new FrontendBehavior(StepType.Fido2Disclaimer, relatedItem.ChallengeType, expectedBehavior)
                       {
                           AlternativeBehavior = GetReferenceToExistingStep(StepType.Stopped, relatedItem.Context,
                                                                            relatedItem.ChallengeType)
                       }
            }
            ;

            return(expectedBehavior);
        }
    }
        protected override void Validate(TransitionInput <StartRequest> input, CacheItem relatedItem)
        {
            base.Validate(input, relatedItem);

            var wasContinued = CheckIfContinued(input, relatedItem);

            if (!wasContinued && relatedItem.Status != CacheItemStatus.Initiated &&
                relatedItem.Status != CacheItemStatus.Started)
            {
                throw new CommandValidationException(
                          $"Wrong status '{relatedItem.Status.ToString()}' for cache item with context '{input.Context}' to set PIN");
            }

            if (!wasContinued && relatedItem.ConcurrentId != null)
            {
                throw new CommandValidationException($"Context '{input.Context}' is already modified with PIN");
            }
        }
Пример #28
0
        protected override void Validate(TransitionInput <string> input, CacheItem relatedItem)
        {
            if (relatedItem.FlowType != FlowType.Fido2Login && relatedItem.FlowType != FlowType.Fido2Register &&
                relatedItem.FlowType != FlowType.Fido2LinkWithPin &&
                relatedItem.FlowType != FlowType.Fido2RecoverWithPin &&
                relatedItem.FlowType != FlowType.PartialAuthorize)
            {
                throw new CommandValidationException(
                          $"Can not set Fido2 information for the flow not related to Fido2. Current flow: {relatedItem.FlowType} Context: '{relatedItem.Context}'");
            }

            if (relatedItem.Status != CacheItemStatus.Initiated && relatedItem.Status != CacheItemStatus.Started &&
                relatedItem.Status != CacheItemStatus.Approved)
            {
                throw new CommandValidationException(
                          $"Incorrect status={relatedItem.Status.ToString()} for setting public key for context '{relatedItem.Context}'");
            }
        }
Пример #29
0
        private async Task <ITransitionResult> SwitchConnectionAuthTypeAsync(CacheItem relatedItem,
                                                                             TransitionInput <JwtContainer> input, bool supportsFido2, string publicKey)
        {
            relatedItem.NewAuthType
                = supportsFido2 && _configuration.Fido2.IsEnabled
                    ? ConnectionAuthType.Fido2
                    : ConnectionAuthType.Passcode;

            var composeInfo = new BaseJwtComposeInfo(input)
            {
                EncKey    = relatedItem.EncKey,
                EncVector = relatedItem.EncVector
            };

            switch (relatedItem.NewAuthType)
            {
            case ConnectionAuthType.Passcode:
                composeInfo.Behavior = new FrontendBehavior(StepType.EnterPasscode, relatedItem.ChallengeType,
                                                            GetNextBehaviorFunc(input, relatedItem))
                {
                    AlternativeBehavior = new FrontendBehavior(StepType.ResetPasscode, relatedItem.ChallengeType,
                                                               new CallAction(UrlProvider.GetResetPasscodeUrl(relatedItem.Context),
                                                                              HttpMethod.Delete.ToString()))
                };
                break;

            case ConnectionAuthType.Fido2:
            {
                await _cacheItemRepository.UpdateAsync(relatedItem.Context, item => item.OldPublicKey = publicKey);

                var fido2Url = UrlProvider.GetFido2Url(relatedItem.Context, relatedItem.RequestToken,
                                                       input.CultureInfo?.Name);
                composeInfo.Behavior = FrontendBehavior.CreateRedirect(fido2Url);
                break;
            }

            default:
                throw new ArgumentOutOfRangeException();
            }

            var jwt = JwtComposer.GenerateBaseStepJwt(composeInfo);

            return(new StateResult(jwt, _cookieService.CreateAuthCookies(relatedItem)));
        }
Пример #30
0
        protected override async Task <ITransitionResult> ExecuteInternalAsync(TransitionInput <UserIdentification> input,
                                                                               CacheItem relatedItem)
        {
            var result = await _checkUserExistenceCommand.ExecuteAsync(input.Data);

            if (result)
            {
                throw new OwnIdException(ErrorType.UserAlreadyExists);
            }

            var composeInfo = new BaseJwtComposeInfo(input)
            {
                Behavior = GetNextBehaviorFunc(input, relatedItem)
            };

            var jwt = JwtComposer.GenerateBaseStepJwt(composeInfo);

            return(new JwtContainer(jwt));
        }