Use the information in this topic to migrate authentication code and programming patterns implemented in your existing ArcGIS Runtime SDK for Android (100.x) applications to the ArcGIS Maps SDK for Kotlin (200.x). There are two approaches to handling authentication:
- Default authentication handling. If you developed applications that adopted the default authentication challenge handler, offered by the ArcGIS Runtime SDK for Android (100.x), see the Default handling of authentication challenges section.
- Custom authentication handling. If you developed your own custom authentication challenge handlers, using the ArcGIS Runtime SDK for Android, see the specific migration steps in the authentication manager, authentication challenge handlers and credentials sections.
Default handling of authentication challenges
When you built an application with ArcGIS Runtime SDK for Android (100.x) that accessed secured resources, the API used a default challenge handler that automatically displayed a login UI to the user. This UI presented information about the challenge as well as the appropriate options, such as username and password inputs. This default handler and UI are not available with ArcGIS Maps SDK for Kotlin. Instead, you have these two options for handling authentication challenges in your application:
-
Use the Authenticator component, provided by the ArcGIS Maps SDK for Kotlin toolkit, to handle authentication challenges, such as ArcGIS authentication (token and OAuth), Integrated Windows Authentication (IWA), and Client Certificate (PKI). The component provides a default UI for login prompts, certificate selection prompts, and server trust prompts. For more information about setting up the tool, persisting credential stores, revoking tokens, and clearing credentials, see the Authentication tool section in the security and authentication topic.
-
Set up an
ArcGISAuthenticationChallengeHandler
andNetworkAuthenticationChallengeHandler
to capture the authentication challenges. Write your own code to present a UI with login prompts, certificate selection prompts, or server trust prompts. Use the response to create an appropriate credential so that the application can continue with the challenge. For more information, see Handle authentication challenges in the security and authentication topic.
Authentication manager
Access to secured resources is managed using the authentication manager. With ArcGIS Maps SDK for Kotlin, you can obtain this directly from the ArcGISEnvironment
.
ArcGISEnvironment.authenticationManager
Authentication challenge handlers
ArcGIS and network authentication challenges were previously handled using a single Authentication
. With ArcGIS Maps SDK for Kotlin, you must create separate authentication challenge handlers that respond to any ArcGISAuthenticationChallenge
or NetworkAuthenticationChallenge
. Set the ArcGIS and network authentication challenge handlers on the AuthenticationManager
.
// ArcGIS authentication challenge handler
ArcGISEnvironment.authenticationManager.arcGISAuthenticationChallengeHandler =
ArcGISAuthenticationChallengeHandler { challenge ->
// If OAuth user configuration is available for the challenge then create `OAuthUserCredential`
if (oAuthConfiguration.canBeUsedForUrl(challenge.requestUrl)) {
// prompt to open browser and sign in with OAuth username and password
// ...
ArcGISAuthenticationChallengeResponse
.ContinueWithCredential(oAuthUserCredential)
} else {
// ...
// Prompt user for getting the username and password to create the `TokenCredential`
// ...
// Create TokenCredential
val tokenCredential = TokenCredential.createWithChallenge(challenge,username, password, 30).getOrNull()
tokenCredential?.let { ArcGISAuthenticationChallengeResponse.ContinueWithCredential(it) } ?: ArcGISAuthenticationChallengeResponse.ContinueAndFail
}
}
// Network authentication challenge handler
ArcGISEnvironment.authenticationManager.networkAuthenticationChallengeHandler = NetworkAuthenticationChallengeHandler { authenticationChallenge ->
when (authenticationChallenge.networkAuthenticationType) {
is NetworkAuthenticationType.UsernamePassword ->
// create the Password Credential
val credential = PasswordCredential(username, password)
NetworkAuthenticationChallengeResponse.ContinueWithCredential(credential)
is NetworkAuthenticationType.ServerTrust ->
NetworkAuthenticationChallengeResponse.ContinueWithCredential(ServerTrust)
is NetworkAuthenticationType.Certificate -> {
val selectedAlias = showCertificatePicker(activityContext)
selectedAlias?.let {
NetworkAuthenticationChallengeResponse.ContinueWithCredential(CertificateCredential(it))
} ?: NetworkAuthenticationChallengeResponse.ContinueAndFail
}
}
}
Credentials
ArcGIS Runtime SDK for Android handled a variety of credentials using the Credential
and O
classes. ArcGIS Maps SDK for Kotlin uses a range of specialized credential types to match the ArcGIS credentials (OAuthUserCredential
, TokenCredential
, and PregeneratedTokenCredential
) and network credentials (CertificateCredential
and PasswordCredential
). You can write code in an authentication challenge handler to prompt the user for credential information, create a credential, and use it to continue with the challenge. This credential will be placed in the store and used by future requests coming from the same source.
You can also create ArcGIS credentials preemptively and store them in ArcGISCredentialStore
.
OAuth
In your ArcGIS Maps SDK for Kotlin application, use OAuthUserCredential
to handle OAuth authentication challenges. Previously, these challenges were handled by adding an OAuth user configuration to the authentication manager.
// Define OAuthConfiguration
private val oAuthConfiguration = OAuthUserConfiguration(
"<portal URL>",
"<ClientID>",
"<redirectURI>"
)
// Create OAuthUserCredential by passing OAuthConfiguration and initiate OAuth sign in process by invoking the provided startSignIn lambda
val oAuthUserCredential = OAuthUserCredential.create(oAuthConfiguration) { oAuthUserSignIn ->
promptForOAuthUserSignIn(oAuthUserSignIn)
}.getOrThrow()
Token
scope.launch {
var tokenCredential = TokenCredential.create(requestUrl,username, password, 30).getOrNull()
}
Pregenerated token
var accessToken = "xxxxxxx"
val tokenInfo = TokenInfo(accessToken, Instant.now().plus(2, ChronoUnit.HOURS), true)
var pregeneratedTokenCredential = PregeneratedTokenCredential(requestUrl, tokenInfo)
Client-side certificate
private suspend fun showCertificatePicker(activityContext: Activity): String? =
suspendCancellableCoroutine { continuation ->
val aliasCallback = KeyChainAliasCallback { alias ->
continuation.resume(alias)
}
KeyChain.choosePrivateKeyAlias(
activityContext, aliasCallback, null, null, null, null
)
}
val selectedAlias = showCertificatePicker(activityContext)
var certificateCredential = selectedAlias?.let { CertificateCredential(it) } ?: null
Username and password
var passwordCredential = PasswordCredential("username", "password")
Trust servers
Previously, you could avoid server trust challenges using the methods Authentication
and Authentication
. With ArcGIS Maps SDK for Kotlin, there is no direct replacement for these methods. You now create ServerTrust
to handle server trust challenges. If you handle a trust challenge with a credential, it will be placed in the store and used by future trust challenges.
var trustCredential = NetworkCredential.serverTrust
Store and persist credentials
ArcGIS and network credentials were previously held in a single AGS
. With ArcGIS Maps SDK for Kotlin, the authentication manager has separate credential stores that exist for the lifetime of the application. These are ArcGISCredentialStore
and NetworkCredentialStore
.
ArcGISEnvironment.authenticationManager.arcGISCredentialStore
ArcGISEnvironment.authenticationManager.networkCredentialStore
To persist the credential stores in the Android Keystore, call the function create
when you make the credential store.
lifecycleScope.launch {
val arcGISCredentialStore = ArcGISCredentialStore.createWithPersistence().getOrThrow()
ArcGISEnvironment.authenticationManager.arcGISCredentialStore = arcGISCredentialStore
val networkCredentialStore = NetworkCredentialStore.createWithPersistence().getOrThrow()
ArcGISEnvironment.authenticationManager.networkCredentialStore = networkCredentialStore
}
Previously, you could create and set a credential preemptively on a specific object. With ArcGIS Maps SDK for Kotlin, you must add the credential to the store before any secure resources are loaded.
var credential = TokenCredential.create(requestUrl,username, password, 30).getOrNull()
credential?.let {
// Preemptively add the credential to the store
ArcGISEnvironment.authenticationManager.arcGISCredentialStore.add(it)
var portal = Portal(url = "https://www.arcgis.com", Portal.Connection.Authenticated)
portal.load()
}