Access services with OAuth 2.0

Learn how to authenticate a user to access a secure ArcGIS service with OAuth 2.0.

access services with oauth 2

In this tutorial, you will build an app that uses named user login credentials to access a secure ArcGIS service using OAuth 2.0.

The ArcGIS Platform supports several authentication methods that you can implement to access ArcGIS premium services and secure content. To implement OAuth 2.0, you can use your ArcGIS account to register an application 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 "named user" or ArcGIS identity authentication. If the app uses premium services that consume credits, the app user's account will be charged.

You will implement OAuth 2.0 so users can sign in to ArcGIS to access the ArcGIS Traffic Layer service.

Prerequisites

The following is required for this tutorial:

  1. Your system meets the system requirements.

Steps

Configure OAuth 2.0 for your app

Use the ArcGIS Developer dashboard to register your app, generate a client ID, and set a redirect URI to access the secure service.

Use this redirect URL when creating the OAuthConfiguration when iOS returns control back to your app after OAuth 2.0 login. If you change this value, you must change it everywhere it is referenced.

  1. Sign in to your ArcGIS developer account. If you don't already have one, sign-up for free. You need to sign in so you can create an application and get a client ID for authentication.

  2. Click the OAuth 2.0 tab in the ribbon at the top.

  3. Click the New Application button in the upper-left of the page.

  4. In the Create New Application window, provide a Name and an optional Description for your app and click Create application. When the application is created, it will have a Client ID, a Client Secret, and a Temporary Token property you can view.

  5. Click the Add URI button at the bottom of the page to add a redirect URL.

  6. In the Add Allowed URI window, type my-app://auth and click Add.

    You'll use the Client ID and the redirect URL in your iOS app.

Open a Xcode project

  1. To start the tutorial, complete the Display a map tutorial or download and unzip the solution.

  2. Open the .xcodeproj file in Xcode.

  3. If you downloaded the solution project, set your API key.

    An API Key enables access to services, web maps, and web scenes hosted in ArcGIS Online.

    1. Go to your developer dashboard to get your API key. For these tutorials, use your default API key. It is scoped to include all of the services demonstrated in the tutorials.

    2. In Xcode, in the Project Navigator, click AppDelegate.swift.

    3. In the editor, set the APIKey property on the AGSArcGISRuntimeEnvironment with your API key.


      AppDelegate.swift
      Use dark colors for code blocks
                                         
      Change 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
      33
      34
      35
      // Copyright 2021 Esri
      //
      // Licensed under the Apache License, Version 2.0 (the "License");
      // you may not use this file except in compliance with the License.
      // You may obtain a copy of the License at
      //
      //   https://www.apache.org/licenses/LICENSE-2.0
      //
      // Unless required by applicable law or agreed to in writing, software
      // distributed under the License is distributed on an "AS IS" BASIS,
      // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      // See the License for the specific language governing permissions and
      // limitations under the License.
      
      
      import UIKit
      
      import ArcGIS
      
      
      @UIApplicationMain
      class AppDelegate: UIResponder, UIApplicationDelegate {
          var window: UIWindow?
      
          func application(_ application: UIApplication,
                           didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
              // Note: it is not best practice to store API keys in source code.
              // The API key is referenced here for the convenience of this tutorial.
      
              AGSArcGISRuntimeEnvironment.apiKey = "YOUR_API_KEY"
      
              return true
          }
      
      }
      

Set the app settings

Create a new Swift file and define constants you'll need in the app.

  1. Add a new Swift file to your Xcode project named AppConfiguration. You will use this file to hold configuration constants required by your app.

    • In Xcode's app menu, select File > New > File.
    • Select Swift File from the Source sub-menu.
    • Name the file AppConfiguration and ensure your app's target is checked.
    • Click create.
  2. Add the following to AppConfiguration.swift. Then, change "YOUR-APP-CLIENT-ID" to the Client ID obtained from the first step above. Update the URL scheme and path to match your Redirect URIs entry.

    AppConfiguration.swift
    Use dark colors for code blocks
                              
    Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add 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
    // Copyright 2021 Esri
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //   https://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    
    import Foundation
    
    extension String {
        static let clientID = "YOUR-APP-CLIENT-ID"
        static let urlScheme = "my-app"
        static var redirectURL: String { "\(urlScheme)://" }
        static let keychainIdentifier = "\(Bundle.main.bundleIdentifier!).keychainIdentifier"
    }
    
    extension URL {
        static let trafficLayerURL = URL(string: "https://traffic.arcgis.com/arcgis/rest/services/World/Traffic/MapServer")!
    }
    
    • Replace the client_id and redirect_url values with the values shown on the authentication tab of your application definition.

Add layer to map

Add an operational layer to the map and test run the app.

  1. Open ViewController.swift and update the existing setupMap() method to add the World Traffic layer to the map.

    The World Traffic layer is a premium service on ArcGIS Online that requires authentication for access.

    ViewController.swift
    Use dark colors for code blocks
                                                 
    Add line.Add 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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    // Copyright 2021 Esri
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //   https://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    
    import UIKit
    import ArcGIS
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var mapView: AGSMapView!
    
        private func setupMap() {
            let map = AGSMap(
                basemapStyle: .arcGISTopographic
            )
            mapView.map = map
            mapView.setViewpoint(
                AGSViewpoint(
                    latitude: 34.02700,
                    longitude: -118.80500,
                    scale: 72_000
                )
            )
    
            let trafficLayer = AGSArcGISMapImageLayer(url: .trafficLayerURL)
            map.operationalLayers.add(trafficLayer)
    
        }
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
            setupMap()
        }
    }
    
  2. Press <Command+R> to run the app.

Only the basemap displays in the map. The traffic layer will not load until you use the AGSAuthenticationManager to log in with an authorized account.

Integrate OAuth 2.0 into your app

Add OAuth components to your app, including adding the redirect URL to the app's plist file, and setting up AGSAuthenticationManager.

  1. Configure a redirect URL scheme for your app. Right-click on info.plist file in the Project Navigator and then select Open As > / Source Code. Edit the file just after the opening top-level <dict> tag and add the following XML:

    Be sure to use your exact bundle identifier for your app.

    Use the scheme part of the Redirect URI you configured in the application definition, but without the path (everything before the ://). This is how OAuth 2.0 in iOS is able to return information about the authentication process back to your app. Note these strings must match exactly.

    Info.plist
    Use dark colors for code blocks
                                                                 
    Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add 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
    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
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
    	<key>CFBundleDevelopmentRegion</key>
    	<string>en</string>
    	<key>CFBundleExecutable</key>
    	<string>$(EXECUTABLE_NAME)</string>
    	<key>CFBundleIdentifier</key>
    	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    	<key>CFBundleInfoDictionaryVersion</key>
    	<string>6.0</string>
    	<key>CFBundleName</key>
    	<string>$(PRODUCT_NAME)</string>
    	<key>CFBundlePackageType</key>
    	<string>APPL</string>
    	<key>CFBundleShortVersionString</key>
    	<string>1.0</string>
    
    	<key>CFBundleURLTypes</key>
    	<array>
    		<dict>
    			<key>CFBundleTypeRole</key>
    			<string>Editor</string>
    			<key>CFBundleURLName</key>
    			<string>com.esri.access-services-with-oauth</string>
    			<key>CFBundleURLSchemes</key>
    			<array>
    				<string>my-app</string>
    			</array>
    		</dict>
    	</array>
    
    	<key>CFBundleVersion</key>
    	<string>1</string>
    	<key>LSRequiresIPhoneOS</key>
    	<true/>
    	<key>UILaunchStoryboardName</key>
    	<string>LaunchScreen</string>
    	<key>UIMainStoryboardFile</key>
    	<string>Main</string>
    	<key>UIRequiredDeviceCapabilities</key>
    	<array>
    		<string>armv7</string>
    	</array>
    	<key>UISupportedInterfaceOrientations</key>
    	<array>
    		<string>UIInterfaceOrientationPortrait</string>
    		<string>UIInterfaceOrientationLandscapeLeft</string>
    		<string>UIInterfaceOrientationLandscapeRight</string>
    		<string>UIInterfaceOrientationPortraitUpsideDown</string>
    	</array>
    	<key>UISupportedInterfaceOrientations~ipad</key>
    	<array>
    		<string>UIInterfaceOrientationPortrait</string>
    		<string>UIInterfaceOrientationPortraitUpsideDown</string>
    		<string>UIInterfaceOrientationLandscapeLeft</string>
    		<string>UIInterfaceOrientationLandscapeRight</string>
    	</array>
    </dict>
    </plist>
  2. Open AppDelegate.swift to setup the AGSAuthenticationManager in your AppDelegate. Import the ArcGIS library.

    AppDelegate.swift
    Use dark colors for code blocks
                                                           
    Add 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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    // Copyright 2021 Esri
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //   https://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    
    
    import UIKit
    
    import ArcGIS
    
    
    @UIApplicationMain
    
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
        func application(_ application: UIApplication,
                         didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
            setupOAuthManager()
    
            return true
        }
    
    }
    
    // MARK: - OAuth
    extension AppDelegate {
        private func setupOAuthManager() {
            // Initialize OAuth configuration with client ID and redirect URL.
            let config = AGSOAuthConfiguration(portalURL: nil,
                                               clientID: .clientID,
                                               redirectURL: .redirectURL)
            // Add OAuth configuration to authentication manager.
            AGSAuthenticationManager.shared()
                .oAuthConfigurations
                .add(config)
            // Enable auto-sync to keychain on the auth manager's credential cache.
            AGSAuthenticationManager.shared()
                .credentialCache
                .enableAutoSyncToKeychain(withIdentifier: .keychainIdentifier,
                                          accessGroup: nil,
                                          acrossDevices: false)
        }
    }
    
  3. Add a new method to setup the authentication manager in AppDelegate.swift. This code creates a configuration with the parameters you assigned to your app in AppConfiguration and then assigns that configuration to the AGSAuthenticationManager. The credentials are also saved in the device's keychain.

    To construct the required redirectURL, combine the urlScheme and urlAuthPath from your AppConfiguration separated with ://.

    AppDelegate.swift
    Use dark colors for code blocks
                                                           
    Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add line.Add 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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    // Copyright 2021 Esri
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //   https://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    
    
    import UIKit
    
    import ArcGIS
    
    
    @UIApplicationMain
    
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
        func application(_ application: UIApplication,
                         didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
            setupOAuthManager()
    
            return true
        }
    
    }
    
    // MARK: - OAuth
    extension AppDelegate {
        private func setupOAuthManager() {
            // Initialize OAuth configuration with client ID and redirect URL.
            let config = AGSOAuthConfiguration(portalURL: nil,
                                               clientID: .clientID,
                                               redirectURL: .redirectURL)
            // Add OAuth configuration to authentication manager.
            AGSAuthenticationManager.shared()
                .oAuthConfigurations
                .add(config)
            // Enable auto-sync to keychain on the auth manager's credential cache.
            AGSAuthenticationManager.shared()
                .credentialCache
                .enableAutoSyncToKeychain(withIdentifier: .keychainIdentifier,
                                          accessGroup: nil,
                                          acrossDevices: false)
        }
    }
    
  4. Add a call to setupOAuthManager() from the application launch.

    AppDelegate.swift
    Use dark colors for code blocks
                                                           
    Add 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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    // Copyright 2021 Esri
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //   https://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    
    
    import UIKit
    
    import ArcGIS
    
    
    @UIApplicationMain
    
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
        func application(_ application: UIApplication,
                         didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
            setupOAuthManager()
    
            return true
        }
    
    }
    
    // MARK: - OAuth
    extension AppDelegate {
        private func setupOAuthManager() {
            // Initialize OAuth configuration with client ID and redirect URL.
            let config = AGSOAuthConfiguration(portalURL: nil,
                                               clientID: .clientID,
                                               redirectURL: .redirectURL)
            // Add OAuth configuration to authentication manager.
            AGSAuthenticationManager.shared()
                .oAuthConfigurations
                .add(config)
            // Enable auto-sync to keychain on the auth manager's credential cache.
            AGSAuthenticationManager.shared()
                .credentialCache
                .enableAutoSyncToKeychain(withIdentifier: .keychainIdentifier,
                                          accessGroup: nil,
                                          acrossDevices: false)
        }
    }
    
  5. Press <Command+R> to run the app in the iOS Simulator.

    Other ways to run the project in Xcode:

    • In Xcode's app menu, select Product > Run.
    • Press the Run button at the top-left of the Xcode project window.

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