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); }; }
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))); }
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))); }