Access services with OAuth credentials

Learn how to implement user authentication to access a secure ArcGIS service with OAuth credentials.

access services with oauth 2

You can use different types of authentication to access secured ArcGIS services. To implement OAuth credentials for user authentication, you can use your ArcGIS account to register an app with your portal and get a Client ID, and then configure your app to redirect users to login with their credentials when the service or content is accessed. This is known as user authentication. If the app uses premium ArcGIS Online services that consume credits, for example, the app user's account will be charged.

In this tutorial, you will build an app that implements user authentication using OAuth credentials so users can sign in and be authenticated through ArcGIS Online to access the ArcGIS World Traffic service.

Prerequisites

Before starting this tutorial:

  1. You need an ArcGIS Location Platform or ArcGIS Online account.

  2. A development and deployment environment that meets the system requirements.

  3. An IDE for Android development in Kotlin.

Steps

Create OAuth credentials

OAuth credentials are required to implement user authentication. These credentials are created as an Application item in your organization's portal.

  1. Sign in to your portal.

  2. Click Content > My content > New item and select Developer credentials.

  3. In the Create developer credentials window, select OAuth 2.0 credentials radio button and click Next.

  4. Add a Redirect URL to your OAuth credentials: my-app://auth. The remaining properties, Referrer URLs, Application environment and URL, can remain with their default values. Click Next.

  5. For Privileges, click Next. Privileges are not required for this tutorial.

  6. Click Skip to move past Grant item access as it is not required for this tutorial.

  7. Provide a Title of your choice. Optionally, stipulate a Folder to store your Application item, add Tags, and add a Summary. Click Next.

  8. Review your settings and go back to correct any errors. When you are ready, click Create. When the application item is created, Client ID, Client Secret, and Temporary Token values will also be generated. You will be redirected to the Application item's Overview page.

You'll use the Client ID and Redirect URL when implementing OAuth in your app's code. The Client ID is found on the Application item's Overview page, while the Redirect URL is found on the Settings page.

Open an Android Studio project with Gradle

  1. To start this tutorial, complete the Display a map tutorial. Or download and unzip the Display a map solution in a new folder.

  2. Modify the old project for use in this new tutorial. Expand More info for instructions.

  3. Delete the code that sets your API Key. Since your app will be using OAuth, you will not need an API Key.

    MainActivity.kt
    Expand
    Use dark colors for code blocks
    11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
    Remove lineRemove lineRemove lineRemove lineRemove lineRemove line
    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
    class MainActivity : ComponentActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            setApiKey()
    
            setContent {
                DisplayAMapTheme {
                    MainScreen()
                }
            }
    
        }
    
        private fun setApiKey() {
    
            ArcGISEnvironment.apiKey = ApiKey.create("YOUR_ACCESS_TOKEN")
    
        }
    
    }

Prepare files before coding the app

Modify the files from the Display a map tutorial for use in this tutorial: you will replace import statements, define strings for OAuth client ID, redirect URI scheme, redirect URI HTMLOListElement, and add an Android activity for OAuth user sign-in.

  1. In the Android tool window, open Gradle Scripts > build.gradle.kts (Module: app) and add a dependency on the authentication component defined in the ArcGIS Maps SDK for Kotlin Toolkit.

    build.gradle.kts (:app)
    Expand
    Use dark colors for code blocks
    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
        // ArcGIS Maps for Kotlin - SDK dependency
        implementation(libs.arcgis.maps.kotlin)
        // Toolkit dependencies
        implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom))
        implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose)
    
        // Additional modules from Toolkit, if needed, such as:
        implementation(libs.arcgis.maps.kotlin.toolkit.authentication)
    
    Expand
  2. From the Project tool window, open Gradle Scripts > libs.versions.toml file and add the Authentication dependency. Note that the version is specified by the arcgis-maps-kotlin-toolkit-bom dependency, which was already set in the Display a map tutorial on which the current tutorial is based.

    Gradle version catalogs are the standard Android approach to declaring dependency versions.

    gradle/libs.versions.toml
    Expand
    Use dark colors for code blocks
    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
    [libraries]
    arcgis-maps-kotlin = { group = "com.esri", name = "arcgis-maps-kotlin", version.ref = "arcgisMapsKotlin" }
    arcgis-maps-kotlin-toolkit-bom = { group = "com.esri", name = "arcgis-maps-kotlin-toolkit-bom", version.ref = "arcgisMapsKotlin" }
    arcgis-maps-kotlin-toolkit-geoview-compose = { group = "com.esri", name = "arcgis-maps-kotlin-toolkit-geoview-compose" }
    
    # Additional modules from Toolkit, if needed, such as:
    arcgis-maps-kotlin-toolkit-authentication = { group = "com.esri", name = "arcgis-maps-kotlin-toolkit-authentication" }
    
    Expand
  3. Open app > kotlin+java > com.example.app > MainScreen.kt. Replace the import statements with the imports needed for this tutorial.

    MainScreen.kt
    Use dark colors for code blocks
    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
    @file:OptIn(ExperimentalMaterial3Api::class)
    
    package com.example.app.screens
    
    import androidx.compose.foundation.layout.fillMaxSize
    import androidx.compose.foundation.layout.padding
    import androidx.compose.material3.ExperimentalMaterial3Api
    import androidx.compose.material3.Scaffold
    import androidx.compose.material3.Text
    import androidx.compose.material3.TopAppBar
    import androidx.compose.runtime.Composable
    import androidx.compose.runtime.remember
    import androidx.compose.ui.Modifier
    import androidx.compose.ui.res.stringResource
    import com.arcgismaps.httpcore.authentication.OAuthUserConfiguration
    import com.arcgismaps.mapping.ArcGISMap
    import com.arcgismaps.mapping.BasemapStyle
    import com.arcgismaps.mapping.Viewpoint
    import com.arcgismaps.mapping.layers.ArcGISMapImageLayer
    import com.arcgismaps.toolkit.authentication.Authenticator
    import com.arcgismaps.toolkit.authentication.AuthenticatorState
    import com.arcgismaps.toolkit.geoviewcompose.MapView
    import com.example.app.R
    
    
  4. Open app > res > values > strings.xml. Enter certain values that you specified while creating your OAuth credentials Create OAuth credentials above.

    In string.xml define strings for the OAuth Client ID and the Redirect URL. Values are not quoted.

    • oauth_client_id: Replace the placeholder YOUR_CLIENT_ID with the Client ID defined for your app.

    • oauth_redirect_uri_scheme: The scheme of the Redirect URL that you defined for your app. This value is my-app if you followed the suggestions in Create OAuth credentials.

    • oauth_redirect_uri_host: The host of the Redirect URL that you defined for your app. This value is auth if you followed the suggestions in Create OAuth credentials.

    strings.xml
    Use dark colors for code blocks
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <resources>
    
        <string name="app_name">Access services with OAuth 2.0</string>
    
        <string name="oauth_client_id">YOUR_CLIENT_ID</string>
        <string name="oauth_redirect_uri_scheme">my-app</string>
        <string name="oauth_redirect_uri_host">auth</string>
    
    </resources>
  5. Open app > manifests > AndroidManifest.xml. Add an <activity> tag that declares the OAuth user sign-in activity. Note the <data> element that references the Redirect URI scheme and host.

    AndroidManifest.xml
    Expand
    Use dark colors for code blocks
    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
            <activity
                android:name="com.arcgismaps.toolkit.authentication.OAuthUserSignInActivity"
                android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
                android:exported="true"
                android:launchMode="singleTop" >
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
    
                    <category android:name="android.intent.category.DEFAULT" />
                    <category android:name="android.intent.category.BROWSABLE" />
    
                    <data
                        android:scheme="@string/oauth_redirect_uri_scheme"
                        android:host="@string/oauth_redirect_uri_host" />
                </intent-filter>
            </activity>
    
    Expand

Implement user authentication using OAuth 2.0

The composable function Authenticator abstracts some details of OAuth 2.0 authentication in your app.

Calling AuthenticatorState requires that you pass an AuthenticatorState, which has an oAuthUserConfiguration property. Use your OAuth Client ID and Redirect URL to instantiate OAuthUserConfiguration.

  1. Create oAuthClientId, oAuthRedirectUriScheme, and oAuthRedirectUriHost variables, using string resources defined in strings.xml.

    MainScreen.kt
    Expand
    Use dark colors for code blocks
    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
    @Composable
    fun MainScreen() {
    
        val oAuthClientId = stringResource(id = R.string.oauth_client_id)
        val oAuthRedirectUriScheme = stringResource(id = R.string.oauth_redirect_uri_scheme)
        val oAuthRedirectUriHost = stringResource(id = R.string.oauth_redirect_uri_host)
    
        val map = remember {
            createMap()
        }
        Scaffold(
            topBar = { TopAppBar(title = { Text(text = stringResource(id = R.string.app_name)) }) }
        ) {
            MapView(
                modifier = Modifier.fillMaxSize().padding(it),
                arcGISMap = map
            )
        }
    
    }
    
    Expand
  2. Create a variable named oAuthRedirectUri that is initialized as the string concatenation of the Redirect URL scheme, the separator ://, and the Redirect URL host.

    MainScreen.kt
    Expand
    Use dark colors for code blocks
    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
    @Composable
    fun MainScreen() {
    
        val oAuthClientId = stringResource(id = R.string.oauth_client_id)
        val oAuthRedirectUriScheme = stringResource(id = R.string.oauth_redirect_uri_scheme)
        val oAuthRedirectUriHost = stringResource(id = R.string.oauth_redirect_uri_host)
    
        val oAuthRedirectUri = oAuthRedirectUriScheme + "://" + oAuthRedirectUriHost
    
        val map = remember {
            createMap()
        }
        Scaffold(
            topBar = { TopAppBar(title = { Text(text = stringResource(id = R.string.app_name)) }) }
        ) {
            MapView(
                modifier = Modifier.fillMaxSize().padding(it),
                arcGISMap = map
            )
        }
    
    }
    
    Expand
  3. Inside a remember block, create an instance of AuthenticatorState, which is from the authentication component of ArcGIS Maps SDK for Kotlin Toolkit. Then set the oAuthUserConfiguration property by instantiating OAuthUserConfiguration and passing portalUrl, clientId, and redirectURL. Last, assign the remember { } call to a local variable named authenticatorState.

    MainScreen.kt
    Expand
    Use dark colors for code blocks
    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
    @Composable
    fun MainScreen() {
    
        val oAuthClientId = stringResource(id = R.string.oauth_client_id)
        val oAuthRedirectUriScheme = stringResource(id = R.string.oauth_redirect_uri_scheme)
        val oAuthRedirectUriHost = stringResource(id = R.string.oauth_redirect_uri_host)
    
        val oAuthRedirectUri = oAuthRedirectUriScheme + "://" + oAuthRedirectUriHost
    
        val authenticatorState = remember {
            AuthenticatorState().apply {
                oAuthUserConfiguration = OAuthUserConfiguration(
                    portalUrl = "https://www.arcgis.com",
                    clientId = oAuthClientId,
                    redirectUrl = oAuthRedirectUri
                )
            }
        }
    
        val map = remember {
            createMap()
        }
        Scaffold(
            topBar = { TopAppBar(title = { Text(text = stringResource(id = R.string.app_name)) }) }
        ) {
            MapView(
                modifier = Modifier.fillMaxSize().padding(it),
                arcGISMap = map
            )
        }
    
    }
    
    Expand
  4. Call the Authenticator composable, passing authenticatorState. The Authenticator composable function should be called from the root level of your UI, typically from you MainScreen, to ensure that authentication prompts always appear on top of any other UI of your application.

    MainScreen.kt
    Expand
    Use dark colors for code blocks
    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
    @Composable
    fun MainScreen() {
    
        val oAuthClientId = stringResource(id = R.string.oauth_client_id)
        val oAuthRedirectUriScheme = stringResource(id = R.string.oauth_redirect_uri_scheme)
        val oAuthRedirectUriHost = stringResource(id = R.string.oauth_redirect_uri_host)
    
        val oAuthRedirectUri = oAuthRedirectUriScheme + "://" + oAuthRedirectUriHost
    
        val authenticatorState = remember {
            AuthenticatorState().apply {
                oAuthUserConfiguration = OAuthUserConfiguration(
                    portalUrl = "https://www.arcgis.com",
                    clientId = oAuthClientId,
                    redirectUrl = oAuthRedirectUri
                )
            }
        }
    
        val map = remember {
            createMap()
        }
        Scaffold(
            topBar = { TopAppBar(title = { Text(text = stringResource(id = R.string.app_name)) }) }
        ) {
            MapView(
                modifier = Modifier.fillMaxSize().padding(it),
                arcGISMap = map
            )
        }
    
        Authenticator(authenticatorState = authenticatorState)
    
    }
    
    Expand

Add a traffic layer

You will add a layer to display the ArcGIS World Traffic service, a dynamic map service that presents historical and near real-time traffic information for different regions in the world. This is a secure service and requires an ArcGIS Online organizational subscription.

  1. Create an ArcGISMapImageLayer to display the traffic service.

    MainScreen.kt
    Expand
    Use dark colors for code blocks
    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
    fun createMap(): ArcGISMap {
    
        // Create a layer to display the ArcGIS World Traffic service
        val trafficLayer = ArcGISMapImageLayer("https://traffic.arcgis.com/arcgis/rest/services/World/Traffic/MapServer")
    
        return ArcGISMap(BasemapStyle.ArcGISTopographic).apply {
            initialViewpoint = Viewpoint(
                latitude = 34.02700,
                longitude = -118.80543,
                scale = 72000.0
            )
    
            operationalLayers.add(trafficLayer)
    
        }
    }
  2. Add the layer to the map's collection of data layers (operational layers).

    MainScreen.kt
    Expand
    Use dark colors for code blocks
    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
    fun createMap(): ArcGISMap {
    
        // Create a layer to display the ArcGIS World Traffic service
        val trafficLayer = ArcGISMapImageLayer("https://traffic.arcgis.com/arcgis/rest/services/World/Traffic/MapServer")
    
        return ArcGISMap(BasemapStyle.ArcGISTopographic).apply {
            initialViewpoint = Viewpoint(
                latitude = 34.02700,
                longitude = -118.80543,
                scale = 72000.0
            )
    
            operationalLayers.add(trafficLayer)
    
        }
    }
  3. Click Run > Run > app to run the app.

When running your app, you will be prompted for username and password in an Android Custom Tab.

access services with oauth 2 login browser

After successfully logging in with your ArcGIS Online credentials, you should see the map with the topographic basemap layer centered on the Santa Monica Mountains in California. You will also see the traffic layer, with its symbology of green, yellow, orange, and red roads to indicate current traffic flow. This is a secured layer, which is visible in your app because the user has entered valid ArcGIS Online username and password.

ArcGIS World Traffic service layer

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