Learn how to implement user authentication to access a secure ArcGIS service with OAuth credentials.
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:
-
You need an ArcGIS Location Platform or ArcGIS Online account.
-
Your system meets the system requirements.
Steps
Create OAuth credentials for user authentication
OAuth credentials are required to implement user authentication. These credentials are created as an Application item in your organization's portal.
-
Go to the Create OAuth credentials for user authentication tutorial and create OAuth credentials using your ArcGIS Location Platform or ArcGIS Online account.
-
Copy the
Client ID
andRedirect URL
as you will use them to implement user authentication in the next step. TheClient ID
is found on the Application item's Overview page, while theRedirect URL
is found on the Settings page.
The Client ID
uniquely identifies your app on the authenticating server. If the server cannot find an app with the provided Client ID, it will not proceed with authentication.
The Redirect URL
is used to identify a response from the authenticating server when the system returns control back to your app after an OAuth login. You can configure several redirect URLs in your application definition and can remove or edit them. It's important to make sure the redirect URL used in your app's code matches a redirect URL configured for the application.
Open the Xcode project
-
To start the tutorial, complete the Display a map tutorial or download and unzip the solution.
-
Open the
.xcodeproj
file in Xcode.
Remove API key
An API Key access token is not required for this app because you are implementing user authentication using OAuth 2.0 protocol.
-
Open MainApp.swift and remove the line that sets the API key access token.
MainApp.swiftUse dark colors for code blocks import SwiftUI import ArcGIS @main struct MainApp: App { init() { ArcGISEnvironment.apiKey = APIKey("<#YOUR-ACCESS-TOKEN#>") } var body: some SwiftUI.Scene { WindowGroup { ContentView() .ignoresSafeArea() } } }
Add a layer to map
Add the World Traffic layer to the map and test run the app.
-
Open ContentView.swift and update the existing
map
variable to add a traffic layer to the map's operational layers collection.The World Traffic layer is a premium service on ArcGIS Online that requires secure authentication to access.
ContentView.swiftUse dark colors for code blocks struct ContentView: View { @State private var map = { let map = Map(basemapStyle: .arcGISTopographic) map.initialViewpoint = Viewpoint(latitude: 34.02700, longitude: -118.80500, scale: 72_000) let trafficLayerURL = URL(string: "http://www.arcgis.com/home/item.html?id=bbdcd78953e5439985004023c8eda03d")! let trafficLayer = ArcGISMapImageLayer(url: trafficLayerURL) map.addOperationalLayer(trafficLayer) return map }() var body: some View { MapView(map: map) } }
-
Press Command+R to run the app.
Note that the basemap and traffic layer do not load into the map because they both require authentication. Let's integrate OAuth authentication into the app.
Integrate OAuth credentials into your app
Create an ArcGISAuthenticationChallengeHandler
that handles OAuth authentication every time a secured ArcGIS resource is accessed.
-
Create a final class named
My
of typeArcGIS Challenge Handler ArcGISAuthenticationChallengeHandler
and tag it as the@
. Initialize the challenge handler with an array ofMain Actor OAuthUserConfiguration
.ContentView.swiftUse dark colors for code blocks import SwiftUI import ArcGIS struct ContentView: View { @State private var map = { let map = Map(basemapStyle: .arcGISTopographic) map.initialViewpoint = Viewpoint(latitude: 34.02700, longitude: -118.80500, scale: 72_000) let trafficLayerURL = URL(string: "http://www.arcgis.com/home/item.html?id=bbdcd78953e5439985004023c8eda03d")! let trafficLayer = ArcGISMapImageLayer(url: trafficLayerURL) map.addOperationalLayer(trafficLayer) return map }() var body: some View { MapView(map: map) } } // Creates an ArcGIS authentication challenge handler. @MainActor final class MyArcGISChallengeHandler: ObservableObject, ArcGISAuthenticationChallengeHandler { // The OAuth configurations that this challenge handler can work with. let oAuthUserConfigurations: [OAuthUserConfiguration] public init( oAuthUserConfigurations: [OAuthUserConfiguration] = [] ) { self.oAuthUserConfigurations = oAuthUserConfigurations } }
-
Add a new function named
handle
to handle the authentication challenge. This function attempts to create anArcGIS Authentication Challenge( _:) OAuthUserCredential
using the credentials provided by the firstOAuthUserConfiguration
in the array. The credentials are stored in the in-memory credential store.ContentView.swiftUse dark colors for code blocks // Creates an ArcGIS authentication challenge handler. @MainActor final class MyArcGISChallengeHandler: ObservableObject, ArcGISAuthenticationChallengeHandler { // The OAuth configurations that this challenge handler can work with. let oAuthUserConfigurations: [OAuthUserConfiguration] public init( oAuthUserConfigurations: [OAuthUserConfiguration] = [] ) { self.oAuthUserConfigurations = oAuthUserConfigurations } // Handles the challenge to an ArcGIS secured resource that requires OAuth or ArcGIS Token authentication. func handleArcGISAuthenticationChallenge( _ challenge: ArcGISAuthenticationChallenge ) async throws -> ArcGISAuthenticationChallenge.Disposition { // If an OAuth user configuration is available for the challenge then create an `OAuthUserCredential`. if let configuration = oAuthUserConfigurations.first(where: { $0.canBeUsed(for: challenge.requestURL) }) { return .continueWithCredential( try await OAuthUserCredential.credential(for: configuration) ) } else { // If not, prompt the user for a username and password to create a `TokenCredential`. // ... return .continueWithCredential( try await TokenCredential.credential(for: challenge, username: "username", password: "password") ) } } }
-
Create a
@
variable inState Object Content
namedView my
that creates an instance of theArcGIS Challenge Handler My
class with the portal URL, client ID, and redirect URL. The client ID and redirect URL are values that you created in the previous step, Create OAuth credentials for user authentication.ArcGIS Challenge Handler ContentView.swiftUse dark colors for code blocks struct ContentView: View { /// `clientID` is a unique identifier made for a public application created by the ArcGIS Maps SDK team. /// `redirectURL` is the redirect URL registered with the clientID. /// - Note: The clientID and redirectURL values here are examples. You must register your own app, generate a client ID, and set a redirect URL to access secure services in your deployed app. @StateObject private var myArcGISChallengeHandler = MyArcGISChallengeHandler( oAuthUserConfigurations: [ OAuthUserConfiguration( portalURL: URL(string: "https://www.arcgis.com")!, clientID: "lgAdHkYZYlwwfAhC", redirectURL: URL(string: "my-ags-app://auth")! ) ] ) @State private var map = { let map = Map(basemapStyle: .arcGISTopographic) map.initialViewpoint = Viewpoint(latitude: 34.02700, longitude: -118.80500, scale: 72_000) let trafficLayerURL = URL(string: "http://www.arcgis.com/home/item.html?id=bbdcd78953e5439985004023c8eda03d")! let trafficLayer = ArcGISMapImageLayer(url: trafficLayerURL) map.addOperationalLayer(trafficLayer) return map }() var body: some View { MapView(map: map) } }
-
Lastly, add an
.on
modifier to the map view and assignAppear my
to theArcGIS Challenge Handler ArcGISAuthenticationChallengeHandler
that is provided by the app'sArcGISEnvironment.authenticationManager
.ContentView.swiftUse dark colors for code blocks struct ContentView: View { /// `clientID` is a unique identifier made for a public application created by the ArcGIS Maps SDK team. /// `redirectURL` is the redirect URL registered with the clientID. /// - Note: The clientID and redirectURL values here are examples. You must register your own app, generate a client ID, and set a redirect URL to access secure services in your deployed app. @StateObject private var myArcGISChallengeHandler = MyArcGISChallengeHandler( oAuthUserConfigurations: [ OAuthUserConfiguration( portalURL: URL(string: "https://www.arcgis.com")!, clientID: "lgAdHkYZYlwwfAhC", redirectURL: URL(string: "my-ags-app://auth")! ) ] ) @State private var map = { let map = Map(basemapStyle: .arcGISTopographic) map.initialViewpoint = Viewpoint(latitude: 34.02700, longitude: -118.80500, scale: 72_000) let trafficLayerURL = URL(string: "http://www.arcgis.com/home/item.html?id=bbdcd78953e5439985004023c8eda03d")! let trafficLayer = ArcGISMapImageLayer(url: trafficLayerURL) map.addOperationalLayer(trafficLayer) return map }() var body: some View { MapView(map: map) .onAppear { ArcGISEnvironment.authenticationManager.arcGISAuthenticationChallengeHandler = myArcGISChallengeHandler } } }
-
Press Command + R to run the app.
If you are using the Xcode simulator your system must meet these minimum requirements: macOS 14 (Sonoma), Xcode 16, iOS 18. If you are using a physical device, then refer to the system requirements.
Upon app launch, you will be prompted to log in with your ArcGIS Developer credentials. Once you authenticate successfully with ArcGIS Online, the basemap and traffic layer will appear in the map.
What's next?
Learn how to use additional API features, ArcGIS location services, and ArcGIS tools in these tutorials: