Beispiel #1
0
        public IntegratedAuthenticationModule(ILog log, IAuthCookieCreator tokenIssuer, IApiActionResponseCreator responseCreator, IWebPortalConfigurationStore webPortalConfigurationStore)
        {
            Get[DirectoryServicesConstants.ChallengePath] = c =>
            {
                if (Context.CurrentUser == null)
                {
                    return(responseCreator.Unauthorized(Request));
                }

                var principal   = (IOctopusPrincipal)Context.CurrentUser;
                var tokenCookie = tokenIssuer.CreateAuthCookie(Context, principal.IdentificationToken, false);

                var directoryPathResult = Request.AbsoluteVirtualDirectoryPath();
                if (!directoryPathResult.IsValid)
                {
                    return(responseCreator.BadRequest(directoryPathResult.InvalidReason));
                }

                var      whitelist = webPortalConfigurationStore.GetTrustedRedirectUrls();
                Response response;
                if (Request.Query["redirectTo"].HasValue && Requests.IsLocalUrl(directoryPathResult.Path, Request.Query["redirectTo"].Value, whitelist))
                {
                    var redirectLocation = Request.Query["redirectTo"].Value;
                    response = new RedirectResponse(redirectLocation).WithCookie(tokenCookie);
                }
                else
                {
                    log.WarnFormat("Prevented potential Open Redirection attack on an NTLM challenge from the local instance {0} to the non-local url {1}", directoryPathResult.Path, Request.Query["redirectTo"].Value);
                    response = new RedirectResponse(directoryPathResult.Path ?? "/").WithCookie(tokenCookie);
                }

                return(response);
            };
        }
Beispiel #2
0
        public Response Execute(NancyContext context, IResponseFormatter response)
        {
            if (!configurationStore.GetIsEnabled())
            {
                return(responseCreator.AsStatusCode(HttpStatusCode.BadRequest));
            }

            var model = modelBinder.Bind <LoginCommand>(context);

            var attemptedUsername      = model.Username;
            var requestUserHostAddress = context.Request.UserHostAddress;

            var action = loginTracker.BeforeAttempt(attemptedUsername, requestUserHostAddress);

            if (action == InvalidLoginAction.Ban)
            {
                return(responseCreator.BadRequest("You have had too many failed login attempts in a short period of time. Please try again later."));
            }

            var userResult = credentialValidator.ValidateCredentials(attemptedUsername, model.Password);

            if (!userResult.Succeeded)
            {
                loginTracker.RecordFailure(attemptedUsername, requestUserHostAddress);

                if (action == InvalidLoginAction.Slow)
                {
                    sleep.For(1000);
                }

                return(responseCreator.BadRequest(userResult.FailureReason));
            }

            var user = userResult.User;

            if (user == null || !user.IsActive || user.IsService)
            {
                loginTracker.RecordFailure(attemptedUsername, requestUserHostAddress);

                if (action == InvalidLoginAction.Slow)
                {
                    sleep.For(1000);
                }

                return(responseCreator.BadRequest("Invalid username or password."));
            }

            loginTracker.RecordSucess(attemptedUsername, requestUserHostAddress);

            var cookie = issuer.CreateAuthCookie(context, user.IdentificationToken, model.RememberMe);

            return(responseCreator.AsOctopusJson(response, userMapper.MapToResource(user))
                   .WithCookie(cookie)
                   .WithStatusCode(HttpStatusCode.OK)
                   .WithHeader("Expires", DateTime.UtcNow.AddYears(1).ToString("R", DateTimeFormatInfo.InvariantInfo)));
        }
Beispiel #3
0
        public async Task <Response> ExecuteAsync(NancyContext context, IResponseFormatter response)
        {
            string state;
            var    principalContainer = await authTokenHandler.GetPrincipalAsync(context.Request, out state);

            var principal = principalContainer.principal;

            if (principal == null || !string.IsNullOrEmpty(principalContainer.error))
            {
                log.Info($"User login failed - {principalContainer.error}");
                return(RedirectResponse(response, $"{context.Request.Form["state"]}?error={principalContainer.error}"));
            }

            var cookieStateHash = string.Empty;

            if (context.Request.Cookies.ContainsKey("s"))
            {
                cookieStateHash = HttpUtility.UrlDecode(context.Request.Cookies["s"]);
            }
            if (State.Protect(state) != cookieStateHash)
            {
                log.Info($"User login failed - invalid state");
                return(RedirectResponse(response, $"{state}?error=Invalid state"));
            }

            var cookieNonceHash = string.Empty;

            if (context.Request.Cookies.ContainsKey("n"))
            {
                cookieNonceHash = HttpUtility.UrlDecode(context.Request.Cookies["n"]);
            }

            var nonce = principal.Claims.FirstOrDefault(c => c.Type == "nonce");

            if (nonce == null || Nonce.Protect(nonce.Value) != cookieNonceHash)
            {
                log.Info("User login failed - invalid nonce");
                return(RedirectResponse(response, $"{state}?error=Invalid nonce"));
            }

            var model = principalToUserHandler.GetUserResource(principal);

            var action = loginTracker.BeforeAttempt(model.Username, context.Request.UserHostAddress);

            if (action == InvalidLoginAction.Ban)
            {
                return(RedirectResponse(response, $"{state}?error=You have had too many failed login attempts in a short period of time. Please try again later."));
            }

            var userResult = GetOrCreateUser(model, principal);

            if (!userResult.Succeeded)
            {
                loginTracker.RecordFailure(model.Username, context.Request.UserHostAddress);

                if (action == InvalidLoginAction.Slow)
                {
                    sleep.For(1000);
                }

                return(RedirectResponse(response, $"{state}?error={userResult.FailureReason}"));
            }

            if (!userResult.User.IsActive || userResult.User.IsService)
            {
                loginTracker.RecordFailure(model.Username, context.Request.UserHostAddress);

                if (action == InvalidLoginAction.Slow)
                {
                    sleep.For(1000);
                }

                return(RedirectResponse(response, $"{state}?error=Invalid username or password"));
            }

            loginTracker.RecordSucess(model.Username, context.Request.UserHostAddress);

            var cookie = authCookieCreator.CreateAuthCookie(context, userResult.User.IdentificationToken, true);

            return(RedirectResponse(response, state)
                   .WithCookie(cookie)
                   .WithHeader("Expires", DateTime.UtcNow.AddYears(1).ToString("R", DateTimeFormatInfo.InvariantInfo)));
        }