ArcGIS Online Authentication

326
7
Jump to solution
03-25-2024 02:33 AM
mmoosbac94
New Contributor

Hello everybody,

we currently have the issue that we have to avoid the use of safari services. Our goal is to use the os standard browser for authentication. Its working when the AGSAuthenticationManagerDelegates´s function is called where we handle the authentication flow manually and not with "continueWithDefaultHandling".

func authenticationManager(_ authenticationManager: AGSAuthenticationManager, didReceive challenge: AGSAuthenticationChallenge)

But if the token expires, a popup appears for login which redirects to a SafariViewController for new authentication. Is there a way to not use the SafariViewController and use the os standard browser instead for a new authentication as well? It seems that the callback function mentioned above is not triggered again for re-authentication.

So what triggers the re-authentication to show a popup and use the SafariViewController?

Thank you

0 Kudos
1 Solution

Accepted Solutions
NimeshJarecha
Esri Regular Contributor

Thanks for Marvin for information. It will be great if you can just provide a sample project which reproduce the issue so I can debug and see what is going on.

Other important thing to note, SDK is able to display OAuth login page using the SafariViewController only if  app has provided an `AGSOAuthConfiguration` instance in OAuthConfigurations property. Can you please check, comment out that code and retry?

Regards,

Nimesh

View solution in original post

0 Kudos
7 Replies
NimeshJarecha
Esri Regular Contributor

Hi @mmoosbac94 ,

Looks like you are using the 100.x version of the SDK and we encourage posting questions for it on ArcGIS Runtime SDK for iOS Questions.

 

If you have implemented the AGSAuthenticationManagerDelegates´s function then it will be called for all challenges. How are you handling the Authentication workflow manually? It will be good if you can post some relevant code.

I'm assuming you are using the  continueWithDefaultHandling on the challenge from the above delegate function. You can check the type of the challenge and if it is `AGSAuthenticationChallengeTypeOAuth` then handle it how you are handling it first time.

The SDK uses Apple recommended APIs to display the OAuth login page.

Regards,

Nimesh

0 Kudos
mmoosbac94
New Contributor

Thanks for the reply! And sorry, next time we will refer to iOS specific thread. 

Thats part of our code for authentication:

 

extension StartViewController: AGSAuthenticationManagerDelegate {

    func authenticationManager(_ authenticationManager: AGSAuthenticationManager, wantsToShow viewController: UIViewController) {
        viewController.modalPresentationStyle = .formSheet
        
        Log.debug("oAuthConfiguration show login")
        present(viewController, animated: true)
    }

    func authenticationManager(_ authenticationManager: AGSAuthenticationManager, wantsToDismiss viewController: UIViewController) {
        Log.debug("oAuthConfiguration close login")
        dismiss(animated: true)
    }

    func authenticationManager(_ authenticationManager: AGSAuthenticationManager,
                               didReceive challenge: AGSAuthenticationChallenge) {
        Log.debug("challenge: \(String(describing: challenge.type.rawValue)), host: \(challenge.authenticatingHost)")
        
        isAuthenticatingUser = true
        showLoginStatus()
        
        Utilities.authenticationChallenge = challenge
        
        if AppSettings.shared.useBrowserAuthentication {
            useBrowserAuthentication(challenge: challenge)
            return
        }

        challenge.continueWithDefaultHandling()
    }

    private func useBrowserAuthentication(challenge: AGSAuthenticationChallenge) {
        AppDelegate.shared.oauth2.authorize() { authParameters, error in
            if let params = authParameters,
               let accessToken = AppDelegate.shared.oauth2.accessToken {
                print("### Authorized! Access token is in `oauth2.accessToken`")
                print("### Authorized! Additional parameters: \(params)")
                challenge.continue(with: AGSCredential(token: accessToken, referer: nil))
                return
            }
            
            challenge.cancel()
            print("### Authorization was canceled or went wrong: \(String(describing: error))")   // error will not be nil
        }
    }
    
}

 

 

Yes we are still using the 100.x Version for that app. 

But when the token expires and we are in-app, then the SafariViewController is shown for re-authentication and no callback function you can see in our code sample is beeing triggered. So anything magical happens in background. But we dont want to use SafariViewController, so actually we want to call e.g. oauth2.authorize() again to force authentication in os standard browser again. Do you know if the SafariViewController is beeing triggered by the ArcGIS SDK when token expires and if there is any solution to that issue?

0 Kudos
NimeshJarecha
Esri Regular Contributor

Thanks for the code and sorry for the delayed response.

Since, `didReceive challenge` function is implemented, SDK should call it for all challenges. The `continueWithDefaultHandling` call is part of that function so may be get called. The OAuth2's access token generated using authorization code flow are valid for 30 minutes so you should see a challenge after 30 minutes.

I'm not sure how `isAuthenticatingUser`, `useBrowserAuthentication`, and `showLoginStatus()` are controlled. So, I would suggest changing code based on challenge type to see if that makes difference. If the challenge type is `OAuth` then call your `useBrowserAuthentication(challenge: challenge)` function.

 

Also, can you please share the result of this log? Also, you can include challenge's request in this debug log.

Log.debug("challenge: \(String(describing: challenge.type.rawValue)), host: \(challenge.authenticatingHost)")

Hope this helps narrow down the issue.

Regards,

Nimesh

0 Kudos
mmoosbac94
New Contributor

Thanks for your reply.

That´s exactly the point. The "didReveice challenge" function is not called when token expires. We can´t detect any logs to that. Just for the first regular login we get: 

authenticationManager(_:didReceive:): challenge: AGSAuthenticationChallengeType(rawValue: 1)

I think you can ignore the mentioned functions "isAuthenticatingUser" etc. because the "didReveice challenge" function is not called anyway. It is like a blackbox to us because we cannot see where the SafariViewController is beeing called and we don´t get any callback to that. Because in case the "didReveice challenge" function is would be called, the "useBrowserAuthentication" function would be executed and we do not use the SafariViewController in any way. Do you know this behaviour that the SafariViewController is beeing shown when token expires for new login?

Regards,
Marvin

0 Kudos
NimeshJarecha
Esri Regular Contributor

Thanks for Marvin for information. It will be great if you can just provide a sample project which reproduce the issue so I can debug and see what is going on.

Other important thing to note, SDK is able to display OAuth login page using the SafariViewController only if  app has provided an `AGSOAuthConfiguration` instance in OAuthConfigurations property. Can you please check, comment out that code and retry?

Regards,

Nimesh

0 Kudos
mmoosbac94
New Contributor

Thanks for the response and your help! Your information was very helpful. When we remove the "AGSOAuthConfiguration", then the SafariViewController is not be shown. Instead a small popup is shown to login to our ArcGIS Server directly. While checking your solution I discovered another strange thing in our code which leads to the issue that the "didReceive challenge" function was not called when token expires. 

Thank you very much!

Regards,
Marvin

0 Kudos
NimeshJarecha
Esri Regular Contributor

Thanks Marvin for the update. I'm glad to know that your issue is resolved!

Regards,

Nimesh

0 Kudos