public static AuthenticationChallenge GetChallenge(HttpPipelineMessage message) { AuthenticationChallenge challenge = null; if (message.HasResponse) { challenge = GetChallengeFromResponse(message.Response); // if the challenge is non-null cache it if (challenge != null) { lock (_cacheLock) { _cache[GetRequestAuthority(message.Request)] = challenge; } } } else { // try to get the challenge from the cache lock (_cacheLock) { _cache.TryGetValue(GetRequestAuthority(message.Request), out challenge); } } return(challenge); }
internal AuthenticationResponse ( AuthenticationChallenge challenge, NetworkCredential credentials, uint nonceCount) : this (challenge.Scheme, challenge.Params, credentials, nonceCount) { }
public static AuthenticationChallenge GetChallenge(HttpMessage message) { AuthenticationChallenge challenge = null; if (message.HasResponse) { challenge = GetChallengeFromResponse(message.Response); // if the challenge is non-null cache it if (challenge != null) { string authority = GetRequestAuthority(message.Request); lock (s_cacheLock) { s_cache[authority] = challenge; } } } else { // try to get the challenge from the cache string authority = GetRequestAuthority(message.Request); lock (s_cacheLock) { s_cache.TryGetValue(authority, out challenge); } } return(challenge); }
private static bool TryGetValidAuthenticationChallengeForScheme(string scheme, AuthenticationType authenticationType, Uri uri, ICredentials credentials, HttpHeaderValueCollection <AuthenticationHeaderValue> authenticationHeaderValues, out AuthenticationChallenge challenge) { challenge = default; if (!TryGetChallengeDataForScheme(scheme, authenticationHeaderValues, out string?challengeData)) { return(false); } NetworkCredential?credential = credentials.GetCredential(uri, scheme); if (credential == null) { // We have no credential for this auth type, so we can't respond to the challenge. // We'll continue to look for a different auth type that we do have a credential for. if (NetEventSource.IsEnabled) { NetEventSource.AuthenticationInfo(uri, $"Authentication scheme '{scheme}' supported by server, but not by client."); } return(false); } challenge = new AuthenticationChallenge(authenticationType, scheme, credential, challengeData); if (NetEventSource.IsEnabled) { NetEventSource.AuthenticationInfo(uri, $"Authentication scheme '{scheme}' selected. Client username={challenge.Credential.UserName}"); } return(true); }
internal bool Authenticate(AuthenticationSchemes scheme, string realm, Func <IIdentity, NetworkCredential> credentialsFinder) { var chal = new AuthenticationChallenge(scheme, realm).ToString(); var retry = -1; bool auth() { retry++; if (retry > 99) { return(false); } var user = HttpUtility.CreateUser( _request.Headers["Authorization"], scheme, realm, _request.HttpMethod, credentialsFinder ); if (user != null && user.Identity.IsAuthenticated) { _user = user; return(true); } _request = sendAuthenticationChallenge(chal); return(auth()); } return(auth()); }
private async Task ProcessCoreAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline, bool async) { HttpPipelineRequestContent originalContent = message.Request.Content; // if this policy doesn't have _challenge cached try to get it from the static challenge cache _challenge ??= AuthenticationChallenge.GetChallenge(message); // if we still don't have the challenge for the endpoint // remove the content from the request and send without authentication to get the challenge if (_challenge == null) { message.Request.Content = null; } // otherwise if we already know the challenge authenticate the request else { await AuthenticateRequestAsync(message, async).ConfigureAwait(false); } if (async) { await ProcessNextAsync(message, pipeline).ConfigureAwait(false); } else { ProcessNext(message, pipeline); } // if we get a 401 if (message.Response.Status == 401) { // set the content to the original content in case it was cleared message.Request.Content = originalContent; // update the cached challenge var challenge = AuthenticationChallenge.GetChallenge(message); // if a challenge was returned and it's different from the cached _challenge if (challenge != null && !challenge.Equals(_challenge)) { // update the cached challenge _challenge = challenge; // authenticate the request and resend await AuthenticateRequestAsync(message, async).ConfigureAwait(false); if (async) { await ProcessNextAsync(message, pipeline).ConfigureAwait(false); } else { ProcessNext(message, pipeline); } } } }
internal bool Authenticate( AuthenticationSchemes scheme, string realm, Func <IIdentity, NetworkCredential> credentialsFinder ) { if (scheme == AuthenticationSchemes.Anonymous) { return(true); } if (scheme == AuthenticationSchemes.None) { Close(HttpStatusCode.Forbidden); return(false); } var chal = new AuthenticationChallenge(scheme, realm).ToString(); var retry = -1; Func <bool> auth = null; auth = () => { retry++; if (retry > 99) { Close(HttpStatusCode.Forbidden); return(false); } #if !NETCF || BCC || SSL var user = HttpUtility.CreateUser( _request.Headers["Authorization"], scheme, realm, _request.HttpMethod, credentialsFinder ); if (user != null && user.Identity.IsAuthenticated) { _user = user; return(true); } #endif SendAuthenticationChallenge(chal); return(auth()); }; return(auth()); }
private static AuthenticationChallenge GetChallengeFromResponse(Response response) { AuthenticationChallenge challenge = null; if (response.Headers.TryGetValue("WWW-Authenticate", out string challengeValue) && challengeValue.StartsWith(BearerChallengePrefix, StringComparison.OrdinalIgnoreCase)) { challenge = ParseBearerChallengeHeaderValue(challengeValue); } return(challenge); }
private async Task <bool> AuthenticateRequest(AuthenticationSchemes scheme, TcpListenerWebSocketContext context) { var chal = scheme == AuthenticationSchemes.Basic ? AuthenticationChallenge.CreateBasicChallenge(Realm).ToBasicString() : scheme == AuthenticationSchemes.Digest ? AuthenticationChallenge.CreateDigestChallenge(Realm).ToDigestString() : null; if (chal == null) { await context.Close(HttpStatusCode.Forbidden).ConfigureAwait(false); return(false); } var retry = -1; var schm = scheme.ToString(); var realm = Realm; var credFinder = UserCredentialsFinder; Func <Task <bool> > auth = () => Task.FromResult(false); auth = async() => { var auth1 = auth; retry++; if (retry > 99) { await context.Close(HttpStatusCode.Forbidden).ConfigureAwait(false); return(false); } var res = await context.GetHeader("Authorization").ConfigureAwait(false); if (res == null || !res.StartsWith(schm, StringComparison.OrdinalIgnoreCase)) { context.SendAuthenticationChallenge(chal); return(await auth1().ConfigureAwait(false)); } await context.SetUser(scheme, realm, credFinder).ConfigureAwait(false); if (!context.IsAuthenticated) { context.SendAuthenticationChallenge(chal); return(await auth1().ConfigureAwait(false)); } return(true); }; return(await auth().ConfigureAwait(false)); }
private async Task AuthenticateRequestAsync(HttpMessage message, bool async, AuthenticationChallenge challenge) { if (_headerValue is null || DateTimeOffset.UtcNow >= _refreshOn) { AccessToken token = async ? await _credential.GetTokenAsync(new TokenRequestContext(challenge.Scopes, message.Request.ClientRequestId), message.CancellationToken).ConfigureAwait(false) : _credential.GetToken(new TokenRequestContext(challenge.Scopes, message.Request.ClientRequestId), message.CancellationToken); _headerValue = BearerChallengePrefix + token.Token; _refreshOn = token.ExpiresOn - TimeSpan.FromMinutes(2); } message.Request.Headers.SetValue(HttpHeader.Names.Authorization, _headerValue); }
private bool authenticateRequest( AuthenticationSchemes scheme, TcpListenerWebSocketContext context) { var chal = scheme == AuthenticationSchemes.Basic ? AuthenticationChallenge.CreateBasicChallenge(Realm).ToBasicString() : scheme == AuthenticationSchemes.Digest ? AuthenticationChallenge.CreateDigestChallenge(Realm).ToDigestString() : null; if (chal == null) { context.Close(HttpStatusCode.Forbidden); return(false); } var retry = -1; var schm = scheme.ToString(); var realm = Realm; var credFinder = UserCredentialsFinder; Func <bool> auth = null; auth = () => { retry++; if (retry > 99) { context.Close(HttpStatusCode.Forbidden); return(false); } var res = context.Headers["Authorization"]; if (res == null || !res.StartsWith(schm, StringComparison.OrdinalIgnoreCase)) { context.SendAuthenticationChallenge(chal); return(auth()); } context.SetUser(scheme, realm, credFinder); if (!context.IsAuthenticated) { context.SendAuthenticationChallenge(chal); return(auth()); } return(true); }; return(auth()); }
private static bool authenticate( TcpListenerWebSocketContext context, AuthenticationSchemes scheme, string realm, Func <IIdentity, NetworkCredential> credentialsFinder) { var chal = scheme == AuthenticationSchemes.Basic ? AuthenticationChallenge.CreateBasicChallenge(realm).ToBasicString() : scheme == AuthenticationSchemes.Digest ? AuthenticationChallenge.CreateDigestChallenge(realm).ToDigestString() : null; if (chal == null) { context.Close(HttpStatusCode.Forbidden); return(false); } var retry = -1; Func <bool> auth = null; auth = () => { retry++; if (retry > 99) { context.Close(HttpStatusCode.Forbidden); return(false); } var user = HttpUtility.CreateUser( context.Headers["Authorization"], scheme, realm, context.HttpMethod, credentialsFinder); if (user != null && user.Identity.IsAuthenticated) { context.SetUser(user); return(true); } context.SendAuthenticationChallenge(chal); return(auth()); }; return(auth()); }
public override bool Equals(object obj) { if (base.Equals(obj)) { return(true); } AuthenticationChallenge other = obj as AuthenticationChallenge; // This assumes that Scopes is always non-null and of length one. // This is guaranteed by the way the AuthenticationChallenge cache is constructued. if (other != null) { return(string.Equals(this.Scopes[0], other.Scopes[0], StringComparison.OrdinalIgnoreCase)); } return(false); }
private static AuthenticationChallenge ParseBearerChallengeHeaderValue(string challengeValue) { AuthenticationChallenge challenge = null; // remove the bearer challenge prefix var trimmedChallenge = challengeValue.Substring(BearerChallengePrefix.Length + 1); // Split the trimmed challenge into a set of name=value strings that // are comma separated. The value fields are expected to be within // quotation characters that are stripped here. String[] pairs = trimmedChallenge.Split(new String[] { "," }, StringSplitOptions.RemoveEmptyEntries); if (pairs.Length > 0) { // Process the name=value string for (int i = 0; i < pairs.Length; i++) { String[] pair = pairs[i].Split('='); if (pair.Length == 2) { // We have a key and a value, now need to trim and decode String key = pair[0].Trim().Trim(new char[] { '\"' }); String value = pair[1].Trim().Trim(new char[] { '\"' }); if (!string.IsNullOrEmpty(key)) { if (string.Equals(key, "scope", StringComparison.OrdinalIgnoreCase)) { challenge = new AuthenticationChallenge(value); break; } else if (string.Equals(key, "resource", StringComparison.OrdinalIgnoreCase)) { challenge = new AuthenticationChallenge(value + "/.default"); } } } } } return(challenge); }
private static bool TryGetValidAuthenticationChallengeForScheme(string scheme, AuthenticationType authenticationType, Uri uri, ICredentials credentials, HttpHeaderValueCollection <AuthenticationHeaderValue> authenticationHeaderValues, out AuthenticationChallenge challenge) { challenge = default; if (!TryGetChallengeDataForScheme(scheme, authenticationHeaderValues, out string challengeData)) { return(false); } NetworkCredential credential = credentials.GetCredential(uri, scheme); if (credential == null) { // We have no credential for this auth type, so we can't respond to the challenge. // We'll continue to look for a different auth type that we do have a credential for. return(false); } challenge = new AuthenticationChallenge(authenticationType, scheme, credential, challengeData); return(true); }
private bool authenticateRequest(AuthenticationSchemes scheme, HttpListenerContext context) { if (context.Request.IsAuthenticated) { return(true); } if (scheme == AuthenticationSchemes.Basic) { context.Response.CloseWithAuthChallenge( AuthenticationChallenge.CreateBasicChallenge(_listener.Realm).ToBasicString()); } else if (scheme == AuthenticationSchemes.Digest) { context.Response.CloseWithAuthChallenge( AuthenticationChallenge.CreateDigestChallenge(_listener.Realm).ToDigestString()); } else { context.Response.Close(HttpStatusCode.Forbidden); } return(false); }
private static bool TryGetAuthenticationChallenge(HttpResponseMessage response, bool isProxyAuth, Uri authUri, ICredentials credentials, out AuthenticationChallenge challenge) { challenge = default; if (!IsAuthenticationChallenge(response, isProxyAuth)) { return(false); } HttpHeaderValueCollection <AuthenticationHeaderValue> authenticationHeaderValues = GetResponseAuthenticationHeaderValues(response, isProxyAuth); // Try to get a valid challenge for the schemes we support, in priority order. if (!TryGetValidAuthenticationChallengeForScheme(NegotiateScheme, AuthenticationType.Negotiate, authUri, credentials, authenticationHeaderValues, out challenge) && !TryGetValidAuthenticationChallengeForScheme(NtlmScheme, AuthenticationType.Ntlm, authUri, credentials, authenticationHeaderValues, out challenge) && !TryGetValidAuthenticationChallengeForScheme(DigestScheme, AuthenticationType.Digest, authUri, credentials, authenticationHeaderValues, out challenge) && !TryGetValidAuthenticationChallengeForScheme(BasicScheme, AuthenticationType.Basic, authUri, credentials, authenticationHeaderValues, out challenge)) { return(false); } return(true); }
internal bool Authenticate ( AuthenticationSchemes scheme, string realm, Func<IIdentity, NetworkCredential> credentialsFinder ) { if (scheme == AuthenticationSchemes.Anonymous) return true; if (scheme != AuthenticationSchemes.Basic && scheme != AuthenticationSchemes.Digest) { Close (HttpStatusCode.Forbidden); return false; } var chal = new AuthenticationChallenge (scheme, realm).ToString (); var retry = -1; Func<bool> auth = null; auth = () => { retry++; if (retry > 99) { Close (HttpStatusCode.Forbidden); return false; } var user = HttpUtility.CreateUser ( _request.Headers["Authorization"], scheme, realm, _request.HttpMethod, credentialsFinder ); if (user == null || !user.Identity.IsAuthenticated) { SendAuthenticationChallenge (chal); return auth (); } _user = user; return true; }; return auth (); }
private static bool TryGetAuthenticationChallenge(HttpResponseMessage response, bool isProxyAuth, Uri authUri, ICredentials credentials, out AuthenticationChallenge challenge) { if (!IsAuthenticationChallenge(response, isProxyAuth)) { challenge = default; return(false); } // Try to get a valid challenge for the schemes we support, in priority order. HttpHeaderValueCollection <AuthenticationHeaderValue> authenticationHeaderValues = GetResponseAuthenticationHeaderValues(response, isProxyAuth); if (NetEventSource.IsEnabled) { NetEventSource.AuthenticationInfo(authUri, $"{(isProxyAuth ? "Proxy" : "Server")} authentication requested with WWW-Authenticate header value '{authenticationHeaderValues}'"); } return (TryGetValidAuthenticationChallengeForScheme(NegotiateScheme, AuthenticationType.Negotiate, authUri, credentials, authenticationHeaderValues, out challenge) || TryGetValidAuthenticationChallengeForScheme(NtlmScheme, AuthenticationType.Ntlm, authUri, credentials, authenticationHeaderValues, out challenge) || TryGetValidAuthenticationChallengeForScheme(DigestScheme, AuthenticationType.Digest, authUri, credentials, authenticationHeaderValues, out challenge) || TryGetValidAuthenticationChallengeForScheme(BasicScheme, AuthenticationType.Basic, authUri, credentials, authenticationHeaderValues, out challenge)); }
private async ValueTask ProcessCoreAsync(HttpMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline, bool async) { if (message.Request.Uri.Scheme != Uri.UriSchemeHttps) { throw new InvalidOperationException("Bearer token authentication is not permitted for non TLS protected (https) endpoints."); } RequestContent originalContent = message.Request.Content; // if this policy doesn't have _challenge cached try to get it from the static challenge cache AuthenticationChallenge challenge = _challenge ?? AuthenticationChallenge.GetChallenge(message); // if we still don't have the challenge for the endpoint // remove the content from the request and send without authentication to get the challenge if (challenge == null) { message.Request.Content = null; } // otherwise if we already know the challenge authenticate the request else { await AuthenticateRequestAsync(message, async, challenge).ConfigureAwait(false); } if (async) { await ProcessNextAsync(message, pipeline).ConfigureAwait(false); } else { ProcessNext(message, pipeline); } // if we get a 401 if (message.Response.Status == 401) { // set the content to the original content in case it was cleared message.Request.Content = originalContent; // update the cached challenge challenge = AuthenticationChallenge.GetChallenge(message); if (challenge != null) { // update the cached challenge if not yet set or different from the current challenge (e.g. moved tenants) if (_challenge == null || !challenge.Equals(_challenge)) { _challenge = challenge; } // authenticate the request and resend await AuthenticateRequestAsync(message, async, challenge).ConfigureAwait(false); if (async) { await ProcessNextAsync(message, pipeline).ConfigureAwait(false); } else { ProcessNext(message, pipeline); } } } }
private static bool authenticate(TcpListenerWebSocketContext context, WebSocketSharp.Net.AuthenticationSchemes scheme, string realm, Func <IIdentity, WebSocketSharp.Net.NetworkCredential> credentialsFinder) { string chal = ((scheme == WebSocketSharp.Net.AuthenticationSchemes.Basic) ? AuthenticationChallenge.CreateBasicChallenge(realm).ToBasicString() : ((scheme != WebSocketSharp.Net.AuthenticationSchemes.Digest) ? null : AuthenticationChallenge.CreateDigestChallenge(realm).ToDigestString())); if (chal == null) { context.Close(WebSocketSharp.Net.HttpStatusCode.Forbidden); return(false); } int retry = -1; Func <bool> auth = null; auth = delegate { retry++; if (retry > 99) { context.Close(WebSocketSharp.Net.HttpStatusCode.Forbidden); return(false); } IPrincipal principal = HttpUtility.CreateUser(context.Headers["Authorization"], scheme, realm, context.HttpMethod, credentialsFinder); if (principal != null && principal.Identity.IsAuthenticated) { context.SetUser(principal); return(true); } context.SendAuthenticationChallenge(chal); return(auth()); }; return(auth()); }
// As client private HandshakeResponse sendHandshakeRequest() { var req = createHandshakeRequest (); var res = sendHandshakeRequest (req); if (res.IsUnauthorized) { _authChallenge = res.AuthChallenge; if (_credentials != null && (!_preAuth || _authChallenge.Scheme == "digest")) { if (res.Headers.Contains ("Connection", "close")) { closeClientResources (); setClientStream (); } var authRes = new AuthenticationResponse (_authChallenge, _credentials, _nonceCount); _nonceCount = authRes.NonceCount; req.Headers ["Authorization"] = authRes.ToString (); res = sendHandshakeRequest (req); } } return res; }
// As client private HttpResponse sendHandshakeRequest () { var req = createHandshakeRequest (); var res = sendHttpRequest (req, 90000); if (res.IsUnauthorized) { var chal = res.Headers["WWW-Authenticate"]; _logger.Warn (String.Format ("Received an authentication requirement for '{0}'.", chal)); if (chal.IsNullOrEmpty ()) { _logger.Error ("No authentication challenge is specified."); return res; } _authChallenge = AuthenticationChallenge.Parse (chal); if (_authChallenge == null) { _logger.Error ("An invalid authentication challenge is specified."); return res; } if (_credentials != null && (!_preAuth || _authChallenge.Scheme == AuthenticationSchemes.Digest)) { if (res.HasConnectionClose) { releaseClientResources (); setClientStream (); } var authRes = new AuthenticationResponse (_authChallenge, _credentials, _nonceCount); _nonceCount = authRes.NonceCount; req.Headers["Authorization"] = authRes.ToString (); res = sendHttpRequest (req, 15000); } } if (res.IsRedirect) { var url = res.Headers["Location"]; _logger.Warn (String.Format ("Received a redirection to '{0}'.", url)); if (_enableRedirection) { if (url.IsNullOrEmpty ()) { _logger.Error ("No url to redirect is located."); return res; } Uri uri; string msg; if (!url.TryCreateWebSocketUri (out uri, out msg)) { _logger.Error ("An invalid url to redirect is located: " + msg); return res; } releaseClientResources (); _uri = uri; _secure = uri.Scheme == "wss"; setClientStream (); return sendHandshakeRequest (); } } return res; }
// As client private HttpResponse SendHandshakeRequest() { var req = CreateHandshakeRequest(); var res = SendHttpRequest(req, 90000); if (res.IsUnauthorized) { #if AUTHENTICATION var chal = res.Headers["WWW-Authenticate"]; Log.Warn(String.Format("Received an authentication requirement for '{0}'.", chal)); if (chal.IsNullOrEmpty()) { Log.Error("No authentication challenge is specified."); return res; } _authChallenge = AuthenticationChallenge.Parse(chal); if (_authChallenge == null) { Log.Error("An invalid authentication challenge is specified."); return res; } if (_credentials != null && (!_preAuth || _authChallenge.Scheme == AuthenticationSchemes.Digest)) { if (res.HasConnectionClose) { releaseClientResources(); setClientStream(); } var authRes = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount); _nonceCount = authRes.NonceCount; req.Headers["Authorization"] = authRes.ToString(); res = sendHttpRequest(req, 15000); } #else throw new InvalidOperationException("Authentication is not supported"); #endif } if (res.IsRedirect) { var url = res.Headers["Location"]; #if COMPAT Log.WarnFormat("Received a redirection to '{0}'.", url); #else $"Received a redirection to '{url}'.".Warn(); #endif if (_enableRedirection) { if (string.IsNullOrEmpty(url)) { #if COMPAT Log.Error("No url to redirect is located."); #else "No url to redirect is located.".Error(); #endif return res; } Uri uri; string msg; if (!url.TryCreateWebSocketUri(out uri, out msg)) { #if COMPAT Log.Error("An invalid url to redirect is located: " + msg); #endif return res; } ReleaseClientResources(); _uri = uri; IsSecure = uri.Scheme == "wss"; SetClientStream(); return SendHandshakeRequest(); } } return res; }