예제 #1
0
        /// <summary>
        /// Checks whether the string represents a URL for a resource within the application environment's
        /// current ArcGIS Online or Portal instance
        /// </summary>
        public async static Task <bool> IsFederatedWithPortal(this string url, string proxyUrl = null)
        {
            string portalUrl = null;

            if (MapApplication.Current != null && MapApplication.Current.Portal != null)
            {
                portalUrl = MapApplication.Current.Portal.Url;
            }

            bool isFederatedWithPortal = url.ToLower().Contains(portalUrl.ToLower());

            if (!isFederatedWithPortal)
            {
                try
                {
                    // Check the requested URL's owning system URL to see if it matches that of the current portal
                    var serverInfo = await ArcGISServerDataSource.GetServerInfo(url, proxyUrl);

                    if (serverInfo != null)
                    {
                        if (!string.IsNullOrEmpty(serverInfo.OwningSystemUrl))
                        {
                            if (!string.IsNullOrEmpty(portalUrl))
                            {
                                string owningUrl = serverInfo.OwningSystemUrl;

                                // Convert to lower case, remove http/https and "/sharing" from URLs
                                portalUrl             = portalUrl.ToLower().TrimEnd('/').Replace("http://", "").Replace("https://", "").Replace("/sharing", "");
                                owningUrl             = owningUrl.ToLower().TrimEnd('/').Replace("http://", "").Replace("https://", "").Replace("/sharing", "");
                                isFederatedWithPortal = portalUrl == owningUrl;
                            }
                        }
                    }
                }
                catch { }
            }
            return(isFederatedWithPortal);
        }
        /// <summary>
        /// Attempts to authenticate with the credentials and against the server specified by the command
        /// </summary>
        protected async override void onSignIn(object parameter)
        {
            if (viewModel == null)
            {
                return;
            }

            // Set state to busy
            viewModel.SigningIn = true;

            try
            {
                string credentialUrl = Url;

                if (viewModel.Url != null)
                {
                    // Get the token URL for the ArcGIS Server
                    credentialUrl = await ArcGISServerDataSource.GetServicesDirectoryURL(viewModel.Url, null);

                    if (credentialUrl == null)
                    {
                        onSignInFailed(new Exception(Strings.InvalidUrlUserPassword));
                    }
                }

                if (IdentityManager.Current != null)
                {
                    var options = new IdentityManager.GenerateTokenOptions()
                    {
                        ProxyUrl = ProxyUrl
                    };
                    // Authenticate against the server to retrieve user token
                    IdentityManager.Credential cred =
                        await IdentityManager.Current.GenerateCredentialTaskAsync(
                            credentialUrl, viewModel.Username, viewModel.Password, options);

                    if (cred != null)
                    {
                        // Save the credential info so it can be used to try to access other services
                        if (!UserManagement.Current.Credentials.Any(c => c.Url != null &&
                                                                    c.Url.Equals(cred.Url, StringComparison.OrdinalIgnoreCase) &&
                                                                    !string.IsNullOrEmpty(c.Token)))
                        {
                            UserManagement.Current.Credentials.Add(cred);
                        }

                        try
                        {
                            // Complete sign-in
                            viewModel.SigningIn   = false;
                            viewModel.SignInError = null;
                            closeWindow();
                            OnSignedIn(cred);
                        }
                        catch (Exception ex)
                        {
                            onSignInFailed(ex);
                        }
                    }
                    else
                    {
                        onSignInFailed(new Exception(agolStrings.Get("SignInFailed")));
                    }
                }
            }
            catch (Exception ex)
            {
                onSignInFailed(ex);
            }
        }
        /// <summary>
        /// Attempt to use application environment credentials to authenticate against the specified URL
        /// </summary>
        public static async Task <IdentityManager.Credential> TryExistingCredentials(string requestUrl, string proxyUrl = null)
        {
            if (string.IsNullOrEmpty(requestUrl) || UserManagement.Current.Credentials.Count == 0)
            {
                return(null);
            }

            bool isPortalUrl = await requestUrl.IsFederatedWithPortal();

            string credentialUrl = requestUrl;

            // Get the token auth endpoint if the requested URL is not an ArcGIS Online/Portal URL
            if (!isPortalUrl)
            {
                credentialUrl = await ArcGISServerDataSource.GetServicesDirectoryURL(requestUrl, proxyUrl);
            }

            // Check whether there's already a credential for the url
            foreach (IdentityManager.Credential cred in UserManagement.Current.Credentials)
            {
                IdentityManager.Credential newCred = null;
                if (isPortalUrl && !string.IsNullOrEmpty(cred.Url) && await cred.Url.IsFederatedWithPortal())
                {
                    try
                    {
                        // If a portal credential already exists, try simply getting a new credential for the same portal
                        newCred = await IdentityManager.Current.GetCredentialTaskAsync(requestUrl, false);
                    }
                    catch { }
                }
                else if (!string.IsNullOrEmpty(cred.Url) &&
                         cred.Url.Equals(credentialUrl, StringComparison.OrdinalIgnoreCase))
                {
                    newCred = cred; // If a credential that matches the requested URL exists, try it
                }
                else if (!string.IsNullOrEmpty(cred.UserName) && !string.IsNullOrEmpty(cred.Password))
                {
                    try
                    {
                        var options = new IdentityManager.GenerateTokenOptions()
                        {
                            ProxyUrl = proxyUrl
                        };
                        // Try authenticating with the user name and password
                        newCred = await IdentityManager.Current.GenerateCredentialTaskAsync(credentialUrl, cred.UserName, cred.Password, options);
                    }
                    catch { } // Intentionally trying credentials that may not work, so swallow exceptions
                }

                if (newCred != null)
                {
                    // Try the original request URL with the new credential's token
                    string testUrl = requestUrl;

                    // Construct the URL with the token
                    if (testUrl.Contains("?"))
                    {
                        testUrl += string.Format("&token={0}&f=json", newCred.Token);
                    }
                    else
                    {
                        testUrl += string.Format("?token={0}&f=json", newCred.Token);
                    }
                    var wc = new ArcGISWebClient()
                    {
                        ProxyUrl = proxyUrl
                    };
                    string result = null;
                    try
                    {
                        // Issue the request
                        result = await wc.DownloadStringTaskAsync(new Uri(testUrl));
                    }
                    catch
                    {
                        continue;
                    }

                    if (result != null)
                    {
                        try
                        {
                            // Check whether the response contains a JSON error
                            JsonObject o = (JsonObject)JsonObject.Parse(result);
                            if (o.ContainsKey("error"))
                            {
                                o = (JsonObject)o["error"];

                                // Check the error code
                                if (o.ContainsKey("code"))
                                {
                                    int statusCode = o["code"];
                                    // Server should return 401 Unauthorized, 403 Forbidden, 498 Invalid Token, or 499
                                    // Token Required if the token was insufficient authorization.  Other errors should
                                    // mean that the resource was accessible with the token, but was just not used
                                    // properly.
                                    if (statusCode == 401 || statusCode == 403 || statusCode == 498 || statusCode == 499)
                                    {
                                        continue;
                                    }
                                }
                            }
                        }
                        catch
                        {
                            // could not parse response, so it's probably HTML or an image.  Assume the
                            // credential is valid since these types of responses are generally not returned
                            // by Portal/Server if there is an error.
                            return(newCred);
                        }
                        return(newCred);
                    }
                }
            }
            return(null);
        }