/// <summary> /// Attempts to login in the system. /// </summary> /// <param name="UserName">User name</param> /// <param name="Password">Password</param> /// <param name="RemoteEndPoint">Remote endpoint of user attempting to login.</param> /// <param name="Protocol">Protocol used for login.</param> /// <returns>Login result.</returns> public static async Task <LoginResult> Login(string UserName, string Password, string RemoteEndPoint, string Protocol) { if (string.IsNullOrEmpty(Password)) { return(new LoginResult()); } if (!(loginAuditor is null)) { DateTime?Next = await loginAuditor.GetEarliestLoginOpportunity(RemoteEndPoint, Protocol); if (Next.HasValue) { return(new LoginResult(Next.Value)); } } User User = await GetUser(UserName, false); if (!(User is null) && User.PasswordHash != Convert.ToBase64String(ComputeHash(UserName, Password))) { User = null; } if (User is null) { LoginAuditor.Fail("Invalid login.", UserName, RemoteEndPoint, Protocol); } else { LoginAuditor.Success("Successful login.", UserName, RemoteEndPoint, Protocol); } return(new LoginResult(User)); }
/// <summary> /// Checks if the request is authorized. /// </summary> /// <param name="Request">Request object.</param> /// <param name="User">User object, if authenticated.</param> /// <returns>If the request is authorized.</returns> public override bool IsAuthenticated(HttpRequest Request, out IUser User) { HttpFieldAuthorization Authorization = Request.Header.Authorization; if (Authorization != null && Authorization.Value.StartsWith("Basic ", StringComparison.CurrentCultureIgnoreCase)) { byte[] Data = Convert.FromBase64String(Authorization.Value.Substring(6).Trim()); string s = InternetContent.ISO_8859_1.GetString(Data); int i = s.IndexOf(':'); if (i > 0) { string UserName = s.Substring(0, i); string Password = s.Substring(i + 1); if (!this.users.TryGetUser(UserName, out User)) { LoginAuditor.Fail("Login attempt using invalid user name.", UserName, Request.RemoteEndPoint, "HTTP"); return(false); } switch (User.PasswordHashType) { case "": break; case "DIGEST-MD5": Password = DigestAuthentication.ToHex(DigestAuthentication.H(UserName + ":" + this.realm + ":" + Password)); break; default: User = null; return(false); } if (Password == User.PasswordHash) { LoginAuditor.Success("Login successful.", UserName, Request.RemoteEndPoint, "HTTP"); return(true); } else { LoginAuditor.Fail("Login attempt failed.", UserName, Request.RemoteEndPoint, "HTTP"); User = null; return(false); } } } User = null; return(false); }
/// <summary> /// Checks if the request is authorized. /// </summary> /// <param name="Request">Request object.</param> /// <returns>User object, if authenticated, or null otherwise.</returns> public override async Task <IUser> IsAuthenticated(HttpRequest Request) { HttpFieldAuthorization Authorization = Request.Header.Authorization; if (Authorization != null && Authorization.Value.StartsWith("Bearer ", StringComparison.CurrentCultureIgnoreCase)) { try { string TokenStr = Authorization.Value.Substring(7).Trim(); JwtToken Token = new JwtToken(TokenStr); string UserName = Token.Subject; if (!this.factory.IsValid(Token) || UserName is null) { LoginAuditor.Fail("Login attempt failed.", UserName ?? string.Empty, Request.RemoteEndPoint, "HTTP"); return(null); } IUser User = await this.users.TryGetUser(UserName); if (User is null) { LoginAuditor.Fail("Login attempt failed.", UserName, Request.RemoteEndPoint, "HTTP"); return(null); } else { LoginAuditor.Success("Login successful.", UserName, Request.RemoteEndPoint, "HTTP"); return(User); } } catch (Exception) { return(null); } } return(null); }
/// <summary> /// Checks if the request is authorized. /// </summary> /// <param name="Request">Request object.</param> /// <returns>User object, if authenticated, or null otherwise.</returns> public override async Task <IUser> IsAuthenticated(HttpRequest Request) { HttpFieldAuthorization Authorization = Request.Header.Authorization; if (Authorization != null && Authorization.Value.StartsWith("Digest ", StringComparison.CurrentCultureIgnoreCase)) { string UserName = null; string Opaque = null; string Realm = null; string Nonce = null; string Cnonce = null; string Nc = null; string Uri = null; string Qop = null; string[] QopItems; string Response = null; bool Auth = false; bool AuthInt = false; foreach (KeyValuePair <string, string> P in CommonTypes.ParseFieldValues(Authorization.Value.Substring(7))) { switch (P.Key.ToLower()) { case "username": UserName = P.Value; break; case "opaque": Opaque = P.Value; break; case "realm": Realm = P.Value; break; case "nonce": Nonce = P.Value; break; case "cnonce": Cnonce = P.Value; break; case "nc": Nc = P.Value; break; case "uri": Uri = P.Value; break; case "qop": Qop = P.Value; QopItems = Qop.Split(','); Auth = (Array.IndexOf(QopItems, "auth") >= 0); AuthInt = (Array.IndexOf(QopItems, "auth-int") >= 0); break; case "response": Response = P.Value; break; } } if (this.realm != Realm || Qop is null || Nonce is null || Cnonce is null || Nc is null || Uri is null || Response is null || UserName is null || (!Auth && !AuthInt)) { return(null); } if (this.opaque != Opaque) { // We need to ignore the opaque value if it's a POST from a web form, since it can be used from the original GET // (which might have ocurred when another instance of the application ran). if (Request.Header.Method != "POST" || Request.Header.ContentType.Value != "application/x-www-form-urlencoded") { return(null); } } DateTime TP = DateTime.Now; lock (this) { LinkedList <DateTime> ToRemove = null; foreach (KeyValuePair <DateTime, string> Pair in this.nonceByExpiration) { if (Pair.Key <= TP) { if (ToRemove is null) { ToRemove = new LinkedList <DateTime>(); } ToRemove.AddLast(Pair.Key); this.expirationByNonce.Remove(Pair.Value); } else { break; } } if (ToRemove != null) { foreach (DateTime ExpiryDate in ToRemove) { this.nonceByExpiration.Remove(ExpiryDate); } } if (!this.expirationByNonce.TryGetValue(Nonce, out TP)) { // We need to ignore the nonce value if it's a POST from a web form, since it can be used from the original GET // (which might have ocurred when another instance of the application ran). if (Request.Header.Method != "POST" || Request.Header.ContentType.Value != "application/x-www-form-urlencoded") { return(null); } } if (Request.Header.Method != "HEAD") { this.expirationByNonce.Remove(Nonce); this.nonceByExpiration.Remove(TP); } } string HA1; string HA2; string Digest; IUser User = await this.users.TryGetUser(UserName); if (User is null) { return(null); } switch (User.PasswordHashType) { case "": HA1 = ToHex(H(UserName + ":" + this.realm + ":" + User.PasswordHash)); break; case "DIGEST-MD5": HA1 = User.PasswordHash; break; default: return(null); } if (AuthInt) { HA2 = ToHex(H(Request.Header.Method + ":" + Uri + ":" + ToHex(H(string.Empty)))); } else { HA2 = ToHex(H(Request.Header.Method + ":" + Uri)); } Digest = HA1 + ":" + Nonce + ":" + Nc + ":" + Cnonce + ":" + Qop + ":" + HA2; Digest = ToHex(H(Digest)); if (Digest == Response) { LoginAuditor.Success("Login successful.", UserName, Request.RemoteEndPoint, "HTTP"); return(User); } else { LoginAuditor.Fail("Login attempt failed.", UserName, Request.RemoteEndPoint, "HTTP"); return(null); } } return(null); }