/// <summary> /// Checks if the request carries a valid long-term cookie, and replaces it with a new valid cookie. /// If a hijack is performed, the response headers will be flushed. /// Callers should check the flush status after calling this method. /// </summary> /// <returns><c>True</c> if the long-term cookie is valid, <c>false</c> otherwise.</returns> /// <param name="context">The http context.</param> protected virtual async Task <bool> PerformLongTermLogin(IHttpContext context) { if (!UseLongTermCookieStorage || LongTermStorage == null) { return(false); } var longterm = context.Request.Cookies[AuthCookieName]; if (string.IsNullOrWhiteSpace(longterm)) { return(false); } var ltc = new LongTermCookie(longterm); if (!ltc.IsValid) { return(false); } var lts = await LongTermStorage.GetLongTermLoginAsync(ltc.Series); if (Utility.IsNullOrExpired(lts)) { return(false); } if (!PBKDF2.ComparePassword(ltc.Token, lts.Token)) { await LongTermStorage.DropAllLongTermLoginsAsync(lts.UserID, lts.Series); SetHijackError(context); await context.Response.FlushHeadersAsync(); return(false); } await PerformLoginAsync(context, lts.UserID, lts.Series, true); return(true); }
/// <summary> /// Attempts to use the HTTP basic auth header to perform a login /// </summary> /// <returns><c>True</c> if the login succeded, <c>false</c> otherwise.</returns> /// <param name="context">The http context.</param> protected virtual async Task <bool> LoginWithBasicAuth(IHttpContext context) { if (AllowBasicAuth && Authentication != null) { var authstring = context.Request.Headers["Authorization"]; if (authstring != null && authstring.StartsWith("Basic ", StringComparison.OrdinalIgnoreCase)) { try { var parts = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(authstring)); if (parts != null) { var ix = parts.IndexOf(':'); if (ix > 0) { var username = parts.Substring(0, ix); var password = parts.Substring(ix + 1); var user = (await Authentication.GetLoginEntriesAsync(username)) .FirstOrDefault(x => x != null && PBKDF2.ComparePassword(password, x.Token)); if (user != null) { await PerformLoginAsync(context, user.UserID, null, false); return(true); } } } } catch { } } } return(false); }
/// <summary> /// Handles the request /// </summary> /// <returns>The awaitable task.</returns> /// <param name="context">The requests context.</param> public async Task <bool> HandleAsync(IHttpContext context) { if (context.Request.Method != "POST") { return(context.SetResponseMethodNotAllowed()); } var xsrf = context.Request.Headers[XSRFHeaderName]; if (RequireXSRFToken && string.IsNullOrWhiteSpace(xsrf)) { return(SetXSRFError(context)); } var username = ExtractUsername(context); var password = ExtractPassword(context); var rememberme = ExtractRememberMe(context); if (string.IsNullOrWhiteSpace(username)) { return(SetLoginError(context)); } if (string.IsNullOrWhiteSpace(password)) { return(SetLoginError(context)); } if (RequireXSRFToken) { var session = await ShortTermStorage.GetSessionFromXSRFAsync(xsrf); if (Utility.IsNullOrExpired(session)) { return(SetXSRFError(context)); } } if (UseLongTermCookieStorage && LongTermStorage != null) { if (await PerformLongTermLogin(context)) { return(true); } // Check for a Hijack response if (context.Response.HasSentHeaders) { return(true); } } var user = (await Authentication.GetLoginEntriesAsync(username)) .FirstOrDefault(x => x != null && PBKDF2.ComparePassword(password, x.Token)); if (user == null) { if (await LoginWithBasicAuth(context)) { return(true); } return(SetLoginError(context)); } await PerformLoginAsync(context, user.UserID, null, rememberme); return(true); }