예제 #1
0
        private void LoadWebMap_GetMapCompleted(object sender, GetMapCompletedEventArgs e)
        {
            ESRI.ArcGIS.Client.WebMap.Document doc = (ESRI.ArcGIS.Client.WebMap.Document)sender;

            if (e.Error == null && e.Map != null)
            {
                attemptingReload = false;
                Map.InitializeFromWebMap(e, l_InitializationFailed);
                Map.GetMapUnitsAsync(SetScaleBarMapUnit, getMapUnitsFailed);

                doc.GetItemCompleted -= LoadWebMap_GetItemCompleted;
                doc.GetItemCompleted += LoadWebMap_GetItemCompleted;
                doc.GetItemAsync(loadWebMapID, e);
            }
            else
            {
                loadingWebMap = false;
                if (attemptingReload)
                {
                    attemptingReload = false;
                    loadWebMapCallback(e);
                    return;
                }
                initializeAgolFromDocument(doc, (agol) =>
                    {
                            // Attempt to sign in from isolated storage
                            AGOLUser user = new AGOLUser(agol);
                            user.SignInFromLocalStorage((o, a) =>
                            {
                                if (user.Token != null)
                                {
                                    // Sign in was successful - try loading web map again
                                    doc.Token = user.Token;
                                    attemptingReload = true;
                                    loadWebMap(loadWebMapID, doc, loadWebMapCallback, e.UserState);
                                }
                                else
                                {
                                    // Try signing into ArcGIS Online/Portal
                                    if (_signInCommand == null)
                                    {
                                        // Initialize sign-on command
                                        _signInCommand = new SignInToAGSOLCommand();
                                        _signInCommand.SignedIn += (o2, a2) =>
                                        {
                                            doc.Token = _signInCommand.ArcGISOnline.User.Token;
                                            attemptingReload = true;
                                            loadWebMap(loadWebMapID, doc, loadWebMapCallback, e.UserState);
                                        };

                                        _signInCommand.Cancelled += (o2, a2) =>
                                        {
                                            if (loadWebMapCallback != null)
                                                loadWebMapCallback(e);
                                        };
                                    }

                                    _signInCommand.ArcGISOnline = agol;
                                    _signInCommand.Execute(null);
                                }
                            });
                    });
            }
        }
예제 #2
0
        private IdentityManager.Credential cachedCredential; // Credential that was just retrieved from sign-in
        
        // Raised when an authentication challenge occurs in the application
        private async void OnChallenge(string url, Action<IdentityManager.Credential, Exception> callback,
            IdentityManager.GenerateTokenOptions options = null)
        {
            if (signedOut) // Sign-out occurred within the last two seconds.  Do not prompt for login.
            {
                callback(null, null);
                return;
            }

            var uri = new Uri(url);
            var tree = uri.AbsolutePath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
            if (tree[tree.Length - 2].ToLower() == "services" && tree[tree.Length - 3].ToLower() == "rest")
            {
                // Challenge is coming from a secure folder.  Do not prompt.
                callback(null, null);
                return;
            }

            // In some cases, multiple challenges are raised for resources at the same endpoint (e.g. tiles from 
            // hosted tile services in ArcGIS Online).  To keep the user from being prompted to login multiple times
            // in succession, each new credential is cached for a half-second.  If another challenge is raised
            // within a half second, and the domain of the current challenge matches that of the cached credential,
            // then the cached credential is used.

            // Initialize timer for clearing cached credential
            if (credentialCacheTimer == null)
            {
                credentialCacheTimer = new ThrottleTimer(2000, () => cachedCredential = null);
            }


            // If there is a credential cached, then sign-in has just occurred.  Check to see if the saved 
            // should also be used for this challenge
            if (cachedCredential != null)
            {
                try
                {
                    // check whether the domain of the currently requested URL matches that of the cached credential
                    if ((new Uri(url)).Domain().ToLower() == (new Uri(cachedCredential.Url).Domain().ToLower()))
                    {
                        // Domains match, so use the cached credential
                        callback(cachedCredential, null);
                        return;
                    }
                }
                catch { }
            }


            // Sometimes challenges are raised after sign-in is cancelled.  To avoid prompting the user after
            // cancellation, this timer will suppress challenges for two seconds.

            // Initialize timer for resetting sign-in cancellation tracking
            if (signInCancelledTimer == null)
            {
                signInCancelledTimer = new ThrottleTimer(2000, () =>
                {
                    // Two seconds has expired since sign-in was cancelled.  Reset tracking variables.
                    signInCancelled = false;
                    signInCancelUrl = null;
                });
            }

            // Check whether sign-in has been cancelled within two seconds
            if (signInCancelled && !string.IsNullOrEmpty(signInCancelUrl))
            {
                try
                {
                    // Check whether the domain of the requested URL matches that for the cancelled sign-in
                    Uri requestUri = new Uri(url);
                    Uri cancelUri = new Uri(signInCancelUrl);
                    if (requestUri.Domain().Equals(cancelUri.Domain(), StringComparison.OrdinalIgnoreCase)
                    && requestUri.AbsolutePath.Equals(cancelUri.AbsolutePath, StringComparison.OrdinalIgnoreCase))
                    {
                        // Domains match - do not prompt user
                        callback(null, null);
                        return;
                    }
                }
                catch { }
            }

            var proxyUrl = options != null ? options.ProxyUrl : null;
            // Sign in suppression checks passed.  Try to authenticate using existing credentials
            // Try existing credentials
            IdentityManager.Credential cred = await ApplicationHelper.TryExistingCredentials(url, proxyUrl);
            if (cred != null)
            {
                // The existing credentials were sufficient for authentication.

                // If the request was for a URL in the current ArcGIS Portal, sign into Portal
                if (await url.IsFederatedWithPortal())
                    await ApplicationHelper.SignInToPortal(cred);

                // If there is not already a credential in the app's credentials collection that has the
                // same URL, add this one to the collection
                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);

                // Pass the credential to the callback
                callback(cred, null);
                return;
            }

            // Try just getting a credential for the URL without specifying login info.  This can work if 
            // the browser has authenticated the user (e.g. using PKI or IWA auth)
            try
            {
                cred = await IdentityManager.Current.GenerateCredentialTaskAsyncEx(url, options);
            }
            catch { } // Swallow authorization exception

            if (cred != null)
            {
                callback(cred, null);
                return;
            }

            // Existing credentials were insufficient.  Prompt user to sign in.

            SignInCommand signInCommand = null;
            if (await url.IsFederatedWithPortal()) // Sign into ArcGIS portal
                signInCommand = new SignInToAGSOLCommand() { ProxyUrl = proxyUrl };
            else // Sign into ArcGIS Server
                signInCommand = new SignInToServerCommand() { Url = url, ProxyUrl = proxyUrl };

            signInCommand.SignedIn += (o, e) =>
            {
                // Temporarily store the credential and start the timer.  This allows this credential
                // to be re-used if there is another challenge with the same domain within a couple 
                // seconds of sign-in.
                cachedCredential = e.Credential;
                credentialCacheTimer.Invoke();

                // Pass the retrieved credential to the callback
                callback(e.Credential, null);
            };
            signInCommand.Cancelled += (o, e) =>
            {
                // Set the flags indicating that sign-in was cancelled and start the timer.  If another
                // challenge for the same resouce is raised within the next couple seconds, it is assumed
                // that the user should not be prompted because cancellation of sign-in has just occurred.
                signInCancelled = true;
                signInCancelUrl = url;
                signInCancelledTimer.Invoke();

                // Pass the retrieved credential to the callback
                callback(null, null);
            };

            // Promt user to sign-in
            signInCommand.Execute(null);
        }