public static AuthScheme[] List() { AuthScheme[] tmp = new AuthScheme[registry.Count]; IList <AuthScheme> tmpValues = registry.Values.ToList(); for (int i = 0; i < registry.Count; i++) { tmp[i] = tmpValues[i]; } return(tmp); }
////////////////////////////////////////////////////////////////////////// // Open ////////////////////////////////////////////////////////////////////////// public async Task OpenAsync() { try { // send initial hello message var helloResp = await SendHelloAsync(); // first try standard authentication if (await OpenStdAsync(helloResp)) { authenticated = true; return; } // check if we have a 200 if (helloResp.StatusCode == HttpStatusCode.OK) { authenticated = true; return; } var content = ReadContent(helloResp); var schemes = AuthScheme.List(); for (var i = 0; i < schemes.Length; ++i) { if (await schemes[i].OnClientNonStdAsync(this, helloResp, content)) { authenticated = true; return; } } // give up var resCode = (int)helloResp.StatusCode; var resServer = helloResp.GetResponseHeader("Server"); if (resCode / 100 >= 4) { throw new IOException("HTTP error code: " + resCode); // 4xx or 5xx } throw new AuthException("No suitable auth scheme for: " + resCode + " " + resServer); } catch (AuthException) { throw; } catch (Exception e) { throw new AuthException("authenticate failed", e); } finally { pass = null; stash.Clear(); } }
/// <summary> /// Lookup an AuthScheme for the given case-insensitive name. /// </summary> public static AuthScheme Find(string name, bool @checked) { AuthScheme scheme = (AuthScheme)registry[name]; if (scheme != null) { return(scheme); } if (@checked) { throw new System.ArgumentException("No auth scheme found for '" + name + "'"); } return(null); }
/// <summary> /// Attempt standard authentication /// </summary> /// <param name="resp"> The response to the hello message </param> /// <returns> /// true if haystack authentciation was used, false if the /// server does not appear to implement RFC 7235. /// </returns> private bool OpenStd(HttpWebResponse resp) { // must be 401 challenge with WWW-Authenticate header if (resp.StatusCode != HttpStatusCode.Unauthorized) { return(false); } var wwwAuth = ResHeader(resp, "WWW-Authenticate"); // don't Use this mechanism for Basic which we // handle as a non-standard scheme because the headers // don't fit nicely into our restricted AuthMsg format if (string.IsNullOrEmpty(wwwAuth) || wwwAuth.ToLower().StartsWith("basic", StringComparison.Ordinal)) { return(false); } // process res/req messages until we have 200 or non-401 failure AuthScheme scheme = null; for (var loopCount = 0; ; ++loopCount) { // sanity check that we don't loop too many times if (loopCount > 5) { throw new AuthException("Loop count exceeded"); } // parse the WWW-Auth header and Use the first scheme var header = ResHeader(resp, "WWW-Authenticate"); AuthMsg[] resMsgs = AuthMsg.ListFromStr(header); var resMsg = resMsgs[0]; scheme = AuthScheme.Find(resMsg.scheme); // let scheme handle message var reqMsg = scheme.OnClient(this, resMsg); // send request back to the server resp = GetAuth(reqMsg); try { DumpRes(resp, false); } catch (Exception e) { e.ToString(); } // 200 means we are done, 401 means keep looping, // consider anything else a failure if (resp.StatusCode == HttpStatusCode.OK) { break; } if (resp.StatusCode == HttpStatusCode.Unauthorized) { continue; } throw new AuthException((int)resp.StatusCode + " " + resp.GetResponseStream()); } // init the bearer token var authInfo = ResHeader(resp, "Authentication-Info"); AuthMsg authInfoMsg = AuthMsg.FromStr("bearer " + authInfo); // callback to scheme for client Success scheme.OnClientSuccess(this, authInfoMsg); // only keep authToken parameter for Authorization header authInfoMsg = new AuthMsg("bearer", new[] { "authToken", authInfoMsg.Param("authToken") }); headers["Authorization"] = authInfoMsg.ToString(); // we did it! return(true); }
////////////////////////////////////////////////////////////////////////// // Registry ////////////////////////////////////////////////////////////////////////// public static AuthScheme Find(string name) { return(AuthScheme.Find(name, true)); }