Migrate authentication from version 100.x to version 200.x

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 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 the ArcGIS Maps SDK for Kotlin. Instead, you have these two options for handling authentication challenges in your application:

  1. 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.

  2. Set up an ArcGISAuthenticationChallengeHandler and NetworkAuthenticationChallengeHandler 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 the ArcGIS Maps SDK for Kotlin, you can obtain this directly from the ArcGISEnvironment.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

ArcGISEnvironment.authenticationManager

Authentication challenge handlers

ArcGIS and network authentication challenges were previously handled using a single AuthenticationChallengeHandler. 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.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// 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 login 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 OAuthConfiguration 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.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Define OAuthConfiguration
private val oAuthConfiguration = OAuthUserConfiguration(
  "<portal URL>",
  "<ClientID>",
  "<redirectURI>"
)

// Create OAuthUserCredential by passing OAuthConfiguration and initiate OAuth login process by invoking the provided startSignIn lambda
val oAuthUserCredential = OAuthUserCredential.create(oAuthConfiguration) { oAuthUserSignIn ->
  promptForOAuthUserSignIn(oAuthUserSignIn)
}.getOrThrow()

Token

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
scope.launch {
  var tokenCredential = TokenCredential.create(requestUrl,username, password, 30).getOrNull()
}

Pregenerated token

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
var accessToken = "xxxxxxx"
val tokenInfo = TokenInfo(accessToken, Instant.now().plus(2, ChronoUnit.HOURS), true)
var pregeneratedTokenCredential = PregeneratedTokenCredential(requestUrl, tokenInfo)

Client-side certificate

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
var passwordCredential = PasswordCredential("username", "password")

Trust servers

Previously, you could avoid server trust challenges using the methods AuthenticationManager.setTrustAllSigners and AuthenticationManager.setSelfSignedCertificateListener. With the 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.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
var trustCredential = NetworkCredential.serverTrust

Store and persist credentials

ArcGIS and network credentials were previously held in a single AGSCredentialCache. 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.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
ArcGISEnvironment.authenticationManager.arcGISCredentialStore
ArcGISEnvironment.authenticationManager.networkCredentialStore

To persist the credential stores in the Android Keystore, call the function createWithPersistence() when you make the credential store.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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.

Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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()
}

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.