/// <summary> /// Asynchronously gets an HTTP connection to an innovator instance (or proxy) at the given URL /// </summary> /// <param name="preferences">Object containing preferences for the connection</param> /// <param name="async">Whether or not to return the connection asynchronously. This is important /// as an HTTP request must be issued to determine the type of connection to create</param> /// <returns>A promise to return a connection object</returns> public static IPromise <IRemoteConnection> GetConnection(ConnectionPreferences preferences, bool async) { preferences = preferences ?? new ConnectionPreferences(); var url = preferences.Url; url = (url ?? "").TrimEnd('/'); if (url.EndsWith("Server/InnovatorServer.aspx", StringComparison.OrdinalIgnoreCase)) { url = url.Substring(0, url.Length - 21); } if (!url.EndsWith("/server", StringComparison.OrdinalIgnoreCase)) { url += "/Server"; } var configUrl = url + "/mapping.xml"; var service = preferences.HttpService ?? ConnectionPreferences.GetService(); Func <ServerMapping, IRemoteConnection> connFactory = m => { var uri = (m.Url ?? "").TrimEnd('/'); if (!uri.EndsWith("/server", StringComparison.OrdinalIgnoreCase)) { url += "/Server"; } switch (m.Type) { case ServerType.Proxy: throw new NotSupportedException(); default: return(ArasConn(service, uri, preferences)); } }; var result = new Promise <IRemoteConnection>(); var req = new HttpRequest { UserAgent = preferences.Headers.UserAgent }; req.SetHeader("Accept", "text/xml"); foreach (var header in preferences.Headers.NonUserAgentHeaders()) { req.SetHeader(header.Key, header.Value); } var trace = new LogData(4, "Innovator: Try to download mapping file", Factory.LogListener) { { "url", configUrl }, }; result.CancelTarget(service.GetPromise(new Uri(configUrl), async, trace, req) .Progress((p, m) => result.Notify(p, m)) .Done(r => { var data = r.AsString(); if (string.IsNullOrEmpty(data)) { result.Resolve(ArasConn(service, url, preferences)); } else { try { var servers = ServerMapping.FromXml(data).ToArray(); if (servers.Length < 1) { result.Resolve(ArasConn(service, url, preferences)); } else if (servers.Length == 1) { result.Resolve(connFactory(servers.Single())); } else { foreach (var server in servers) { server.Factory = connFactory; } result.Resolve(new MappedConnection(servers, preferences.AuthCallback)); } } catch (XmlException) { result.Resolve(ArasConn(service, url, preferences)); } } }).Fail(ex => { result.Resolve(ArasConn(service, url, preferences)); })).Always(trace.Dispose); if (preferences.Credentials != null) { IRemoteConnection conn = null; return(result .Continue(c => { conn = c; return c.Login(preferences.Credentials, async); }) .Convert(u => conn)); } 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); }