private IPromise <ICredentials> DefaultAuthCallback(INetCredentials netCred, string endpoint, bool async) { var promise = new Promise <ICredentials>(); if (string.IsNullOrEmpty(endpoint)) { promise.Resolve(netCred); } else { var handler = new SyncClientHandler() { Credentials = netCred.Credentials, PreAuthenticate = true }; var http = new SyncHttpClient(handler); var endpointUri = new Uri(endpoint + "?db=" + netCred.Database); var trace = new LogData(4, "Innovator: Authenticate user via mapping", Factory.LogListener) { { "database", netCred.Database }, { "user_name", netCred.Credentials.GetCredential(endpointUri, null).UserName }, { "url", endpointUri }, }; http.GetPromise(endpointUri, async, trace) .Done(r => { var res = r.AsXml().DescendantsAndSelf("Result").FirstOrDefault(); var user = res.Element("user").Value; var pwd = res.Element("password").Value; if (pwd.IsNullOrWhiteSpace()) { promise.Reject(new ArgumentException("Failed to authenticate with Innovator server '" + endpoint + "'. Original error: " + user, "credentials")); } var needHash = !string.Equals(res.Element("hash").Value, "false", StringComparison.OrdinalIgnoreCase); if (needHash) { promise.Resolve(new ExplicitCredentials(netCred.Database, user, pwd)); } else { promise.Resolve(new ExplicitHashCredentials(netCred.Database, user, pwd)); } }).Fail(ex => { // Only hard fail for problems which aren't time outs and not found issues. var webEx = ex as HttpException; if (webEx != null && webEx.Response.StatusCode == HttpStatusCode.NotFound) { promise.Resolve(netCred); } else if (webEx != null && webEx.Response.StatusCode == HttpStatusCode.Unauthorized) { promise.Reject(ElementFactory.Local.ServerException("Invalid username or password")); } else if (webEx != null) { try { var result = ElementFactory.Local.FromXml(webEx.Response.AsStream); if (result.Exception != null) { promise.Reject(result.Exception); } else { promise.Reject(ex); } } catch (Exception) { promise.Reject(ex); } } else if (ex is TaskCanceledException) { promise.Resolve(netCred); } else { promise.Reject(ex); } }).Always(trace.Dispose); } return(promise); }
private IPromise <TokenCredentials> GetCredentials(bool async) { var req = new HttpRequest { Content = new SimpleContent(new Dictionary <string, string>() { { "client_id", "IOMApp" }, { "grant_type", "password" }, { "scope", "Innovator" }, { "username", Uri.EscapeDataString(_hashCred.Username) }, { "database", Uri.EscapeDataString(_hashCred.Database) }, { "password", Uri.EscapeDataString(_hashCred.PasswordHash) }, }.Select(k => k.Key + "=" + k.Value).GroupConcat("&"), "application/x-www-form-urlencoded") }; req.Headers.Add("Accept", "application/json"); var result = new Promise <TokenCredentials>(); result.CancelTarget( _service.PostPromise(_config.TokenEndpoint, async, req, new LogData(4 , "Innovator: Get OAuth token" , Factory.LogListener) { { "database", _hashCred.Database }, { "url", _config.TokenEndpoint }, { "user_name", _hashCred.Username }, }) .Convert(r => new TokenCredentials(r.AsStream, _hashCred.Database)) .Done(result.Resolve) .Fail(e => { try { if (!(e is HttpException httpEx)) { result.Reject(e); return; } var faultCode = default(string); var faultstring = default(string); using (var reader = new Json.Embed.JsonTextReader(httpEx.Response.AsStream)) { foreach (var kvp in reader.Flatten()) { switch (kvp.Key) { case "$.error": faultCode = kvp.Value?.ToString(); break; case "$.error_description": faultstring = kvp.Value?.ToString(); break; } } } result.Reject(ElementFactory.Local.FromXml(@"<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:i18n='http://www.aras.com/I18N'> <SOAP-ENV:Body> <SOAP-ENV:Fault> <faultcode>@0</faultcode> <faultstring>@1</faultstring> <faultactor>OAuthServer</faultactor> <detail>unknown error</detail> </SOAP-ENV:Fault> </SOAP-ENV:Body> </SOAP-ENV:Envelope>", faultCode, faultstring).Exception); } catch (Exception ex) { result.Reject(ex); } })); return(result); }
public static IPromise <IAuthenticator> GetAuthenticator(Uri innovatorServerBaseUrl, HttpClient service, ICredentials creds, bool async) { var discovery = new Uri(innovatorServerBaseUrl, "OAuthServerDiscovery.aspx"); var req = new HttpRequest(); req.Headers.Add("Aras-Set-HttpSessionState-Behavior", "switch_to_initial"); var oauthBaseUri = default(Uri); var result = new Promise <IAuthenticator>(); result.CancelTarget( service.GetPromise(discovery, async, new LogData(4 , "Innovator: Get OAuth URL" , Factory.LogListener) { { "url", discovery }, }, req) .Continue(r => { if (r.StatusCode != System.Net.HttpStatusCode.OK) { throw new Exception("OAuth not found"); } var serverUrls = default(List <Uri>); using (var json = new Json.Embed.JsonTextReader(r.AsStream)) { serverUrls = json.Flatten() .Where(k => k.Key.StartsWith("$.locations[") && k.Key.EndsWith("].uri") && k.Value is string str && !string.IsNullOrEmpty(str)) .Select(k => new Uri(k.Value.ToString())) .OrderBy(u => string.Equals(u.Host, innovatorServerBaseUrl.Host, StringComparison.OrdinalIgnoreCase) ? 0 : 1) .ToList(); } if (serverUrls?.Count < 1) { throw new InvalidOperationException("OAuth server URL could not be found"); } oauthBaseUri = serverUrls[0]; var oauthUri = new Uri(oauthBaseUri, ".well-known/openid-configuration"); return(service.GetPromise(oauthUri, async, new LogData(4 , "Innovator: Get OAuth Config" , Factory.LogListener) { { "url", oauthUri }, })); }) .Progress(result.Notify) .Done(r => { try { var config = new OAuthConfig(r.AsString(), oauthBaseUri); if (config.ProtocolVersion >= new Version("1.0")) { result.Resolve(new OAuthAuthenticator(service, config, creds)); } else { result.Resolve(new LegacyAuthenticator(innovatorServerBaseUrl, creds)); } } catch (Exception ex) { result.Reject(ex); } }) .Fail(e => { result.Resolve(new LegacyAuthenticator(innovatorServerBaseUrl, creds)); })); return(result); }