/// <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) { User = null; 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); if (!this.factory.IsValid(Token)) { return(false); } if (Token.Subject == null) { return(false); } return(this.users.TryGetUser(Token.Subject, out User)); } catch (Exception) { return(false); } } return(false); }
/// <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> /// Parses a specific HTTP header field. /// </summary> /// <param name="KeyLower">Lower-case version of field name.</param> /// <param name="Key">Field name, as it appears in the header.</param> /// <param name="Value">Unparsed header field value</param> /// <returns>HTTP header field object, corresponding to the particular field.</returns> protected override HttpField ParseField(string KeyLower, string Key, string Value) { switch (KeyLower) { case "accept": return(this.accept = new HttpFieldAccept(Key, Value)); case "accept-charset": return(this.acceptCharset = new HttpFieldAcceptCharset(Key, Value)); case "accept-encoding": return(this.acceptEncoding = new HttpFieldAcceptEncoding(Key, Value)); case "accept-language": return(this.acceptLanguage = new HttpFieldAcceptLanguage(Key, Value)); case "authorization": return(this.authorization = new HttpFieldAuthorization(Key, Value)); case "cookie": return(this.cookie = new HttpFieldCookie(Key, Value)); case "expect": return(this.expect = new HttpFieldExpect(Key, Value)); case "from": return(this.from = new HttpFieldFrom(Key, Value)); case "host": return(this.host = new HttpFieldHost(Key, Value)); case "if-match": return(this.ifMatch = new HttpFieldIfMatch(Key, Value)); case "if-modified-since": return(this.ifModifiedSince = new HttpFieldIfModifiedSince(Key, Value)); case "if-none-match": return(this.ifNoneMatch = new HttpFieldIfNoneMatch(Key, Value)); case "if-range": return(this.ifRange = new HttpFieldIfRange(Key, Value)); case "if-unmodified-since": return(this.ifUnmodifiedSince = new HttpFieldIfUnmodifiedSince(Key, Value)); case "referer": return(this.referer = new HttpFieldReferer(Key, Value)); case "range": return(this.range = new HttpFieldRange(Key, Value)); case "user-agent": return(this.userAgent = new HttpFieldUserAgent(Key, Value)); case "upgrade-insecure-requests": return(this.upgradeInsequreRequests = new HttpFieldUpgradeInsecureRequests(Key, Value)); default: return(base.ParseField(KeyLower, Key, Value)); } }
/// <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); }