The Authorization code flow with Proof Key for Code Exchange (PKCE) is an OAuth 2.0
This flow is an extension of the original Authorization code flow with added security measures. To learn about the base Authorization code flow, go to Authorization code flow.
This is the recommended OAuth 2.0 flow for user authentication
Proof Key for Code Exchange (PKCE)
Proof Key for Code Exchange is an extension of the OAuth 2.0code and code. This ensures that the client that requests an access tokenauthorization_code grant type.
The general steps for the authorization code flow with PKCE are:
-
Client generates a random
codeand_verifier codelocally using SHA256 encryption._challenge -
Client sends a request to the authorization endpoint
An authorization endpoint is an ArcGIS portal service endpoint that can be queried to request an authorization code. It is used to implement user authentication OAuth2.0 flows. that includes thecodeas well as a_challenge clientand_id redirectfrom OAuth credentials_uri OAuth credentials are an item that contains parameters required to implement user authentication or app authentication, including a .client_id,client_secret, and redirect URIs. They are a type of developer credential. -
The application user signs in with an ArcGIS account
An ArcGIS account is an identity with a user type and set of privileges that can access specific ArcGIS products, tools, APIs, services, and resources. The main account types that can be used for development are an ArcGIS Location Platform account, ArcGIS Online account, and ArcGIS Enterprise account. ArcGIS Location Platform and ArcGIS Online accounts are also associated with a subscription. . The authorization endpointAn authorization endpoint is an ArcGIS portal service endpoint that can be queried to request an authorization code. It is used to implement user authentication OAuth2.0 flows. verifies the user identity and returns an authorization codeAn authorization code is a string that is used to obtain an access token associated with a user account. It is required in user authentication flows that adhere to the OAuth2.0 .authorization_codegrant type. -
Client uses the
authorizationand_code code, as well as the_verifier clientand_id redirectfrom OAuth credentials_uri OAuth credentials are an item that contains parameters required to implement user authentication or app authentication, including a , to submit a request to the token endpointclient_id,client_secret, and redirect URIs. They are a type of developer credential.An token endpoint is an endpoint of a portal service that can be queried to request an access token. It is used to implement user authentication OAuth2.0 flows. . The token endpoint checks that thecodealigns with the original_verifier codeand issues an access token_challenge An access token is an authorization string that provides access to secure ArcGIS content, data, and services. Its capabilities are determined by the privileges it supports. It is obtained by implementing API key authentication, User authentication, or App authentication. . -
Client uses the access token
An access token is an authorization string that provides access to secure ArcGIS content, data, and services. Its capabilities are determined by the privileges it supports. It is obtained by implementing API key authentication, User authentication, or App authentication. to authorize requests to secure resourcesA secure resource is any item or service in an ArcGIS that requires an ArcGIS account and authentication to access. Examples include ArcGIS Location Services, and items and data services in an ArcGIS portal. .
ArcGIS APIs and SDKs
Authorization code with Proof Key for Code Exchange (PKCE) is the default authorization flow used by all ArcGIS APIs
Manual implementation
The remainder of this page shows how to manually implement user authentication
This sample is written in JavaScript, but can be implemented in any language. It adheres to the OAuth 2.0 specification for the Authorization code with Proof Key for Code Exchange (PKCE) flow.
Create OAuth credentials
User authenticationclient_id, client_secret, and redirect URIs. They are a type of developer credential.
Configure authentication variables
-
Copy your client ID and chosen redirect URL from your OAuth credentials
OAuth credentials are an item that contains parameters required to implement user authentication or app authentication, including a and include them in your app.client_id,client_secret, and redirect URIs. They are a type of developer credential.index.htmlUse dark colors for code blocks const clientId = '<YOUR_CLIENT_ID>'; const redirectUri = '<YOUR_REDIRECT_URL>'; let session = null; let map = null; const signInButton = document.getElementById('sign-in'); const signOutButton = document.getElementById('sign-out');
Generate a code verifier and challenge
-
Use language-specific libraries to generate a code verifier. This string is required in the "Authorization code with PKCE" flow, and will be sent to the token endpoint
An token endpoint is an endpoint of a portal service that can be queried to request an access token. It is used to implement user authentication OAuth2.0 flows. to request an access token.index.htmlUse dark colors for code blocks const dec2hex = (dec) => { return ('0' + dec.toString(16)).substr(-2) } const generateRandomString = () => { var array = new Uint32Array(56/2); window.crypto.getRandomValues(array); return Array.from(array, dec2hex).join(''); } const codeVerifier = generateRandomString(); -
Generate a code challenge, a base64 SHA256 encrypted version of the code verifier. This string will be sent to the authorization endpoint
An authorization endpoint is an ArcGIS portal service endpoint that can be queried to request an authorization code. It is used to implement user authentication OAuth2.0 flows. to obtain an authorization code.index.htmlUse dark colors for code blocks const dec2hex = (dec) => { return ('0' + dec.toString(16)).substr(-2) } const generateRandomString = () => { var array = new Uint32Array(56/2); window.crypto.getRandomValues(array); return Array.from(array, dec2hex).join(''); } const challengeFromVerifier = async (verifier) => { // Generate SHA256 buffer const encoder = new TextEncoder(); const data = encoder.encode(verifier); const sha256 = await window.crypto.subtle.digest('SHA-256', data); // Encode SHA256 as base 64 var str = ""; var bytes = new Uint8Array(sha256); var len = bytes.byteLength; for (var i = 0; i < len; i++) { str += String.fromCharCode(bytes[i]); } const challenge = btoa(str) .replace(/\+/g, "-") .replace(/\//g, "_") .replace(/=+$/, ""); return challenge; } const codeVerifier = generateRandomString(); const codeChallenge = await challengeFromVerifier(codeVerifier);
Request an authorization code
-
Format a GET request to the authorization endpoint
An authorization endpoint is an ArcGIS portal service endpoint that can be queried to request an authorization code. It is used to implement user authentication OAuth2.0 flows. . Include yourclient,_id redirect, and_uri code._challenge index.htmlUse dark colors for code blocks const authorizationEndpoint = 'https://www.arcgis.com/sharing/rest/oauth2/authorize'+ '?client_id=' + clientId + '&code_challenge=' + codeChallenge + '&code_challenge_method=S256' + '&redirect_uri=' + window.encodeURIComponent(redirectUri)+ '&response_type=code'+ '&expiration=20160'; -
When the user clicks 'sign in', open the authorization endpoint in a new window.
index.htmlUse dark colors for code blocks const authorizationEndpoint = 'https://www.arcgis.com/sharing/rest/oauth2/authorize'+ '?client_id=' + clientId + '&code_challenge=' + codeChallenge + '&code_challenge_method=S256' + '&redirect_uri=' + window.encodeURIComponent(redirectUri)+ '&response_type=code'+ '&expiration=20160'; signInButton.addEventListener('click', () => window.open(authorizationEndpoint, 'oauth-window', 'height=400,width=600,menubar=no,location=yes,resizable=yes,scrollbars=yes,status=yes'));
Create a callback
-
Create a callback function in
index.htmlthat will receive the authorization code.index.htmlUse dark colors for code blocks const oauthCallback = (authorizationCode) => { } window.oauthCallback = oauthCallback; //required due to the module scope of this script -
Create a new HTML page at the location of your redirect URI. When a user successfully authenticates at the authorization endpoint, they will be redirected to this page.
callback.htmlUse dark colors for code blocks <!DOCTYPE html> <head> <title>ArcGIS user authentication OAuth 2.0 callback (vanilla JS)</title> </head> <body> <script type="module"> </script> </body> </html> -
Access the authorization code returned from the endpoint. It is found in the
searchparameter of the URL. Pass the code to the callback function created inindex.html.callback.htmlUse dark colors for code blocks <!DOCTYPE html> <head> <title>ArcGIS user authentication OAuth 2.0 callback (vanilla JS)</title> </head> <body> <script type="module"> const match = (window.location.search) ? window.location.search.match(/\?code=([^&]+)/) : false; // if we found an authorization code in the URL, pass the token up to a global function in index.html if(match[1]) { window.opener.oauthCallback(match[1]); } window.close(); </script> </body> </html>
Request an access token
-
Find the URL of the token endpoint
An token endpoint is an endpoint of a portal service that can be queried to request an access token. It is used to implement user authentication OAuth2.0 flows. for your portal serviceA portal service provides the functionality to securely create, access, and manage content, data services, users, and groups in a portal. The service can be hosted by Esri or in ArcGIS Enterprise. . For ArcGIS Online users, the token endpoint ishttps.://www.arcgis.com/sharing/rest/oauth2/token index.htmlUse dark colors for code blocks const oauthCallback = (authorizationCode) => { const tokenEndpoint = 'https://www.arcgis.com/sharing/rest/oauth2/token'; } window.oauthCallback = oauthCallback; //required due to the module scope of this script -
Submit an HTTP request to the token endpoint to request an access token
An access token is an authorization string that provides access to secure ArcGIS content, data, and services. Its capabilities are determined by the privileges it supports. It is obtained by implementing API key authentication, User authentication, or App authentication. . Include yourauthorization,_code client,_id redirect, and_uri codeto create a valid request, and set the_verifier grantas_type authorization._code index.htmlUse dark colors for code blocks const oauthCallback = (authorizationCode) => { const tokenEndpoint = 'https://www.arcgis.com/sharing/rest/oauth2/token'; fetch(tokenEndpoint, { method:'POST', body: JSON.stringify({ client_id:clientId, grant_type:'authorization_code', code:authorizationCode, redirect_uri:redirectUri, code_verifier:codeVerifier }), headers: { "Content-type": "application/json; charset=UTF-8" } }) } window.oauthCallback = oauthCallback; //required due to the module scope of this script -
Access the response from the endpoint. If the request was valid, the response will contain an
access,_token refresh,_token username, and other session information.index.htmlUse dark colors for code blocks const oauthCallback = (authorizationCode) => { const tokenEndpoint = 'https://www.arcgis.com/sharing/rest/oauth2/token'; fetch(tokenEndpoint, { method:'POST', body: JSON.stringify({ client_id:clientId, grant_type:'authorization_code', code:authorizationCode, redirect_uri:redirectUri, code_verifier:codeVerifier }), headers: { "Content-type": "application/json; charset=UTF-8" } }) .then(response => response.json()).then(newSession => { updateSession(newSession); initApp(newSession); }) } window.oauthCallback = oauthCallback; //required due to the module scope of this script
Serialize session info
-
Serialize the session information from the token endpoint and add it to local storage to make the session persistent across page refreshes.
index.htmlUse dark colors for code blocks Copy const updateSession = (sessionInfo) => { const userInfo = document.getElementById('user-info'); if (!sessionInfo) { localStorage.removeItem("__ARCGIS_USER_SESSION__"); session = null; destroyApp(); // signed out sidebar state userInfo.classList.add('hide'); userInfo.innerHTML = ``; signOutButton.classList.add('hide'); signInButton.classList.remove('hide'); } else { session = sessionInfo; localStorage.setItem("__ARCGIS_USER_SESSION__", JSON.stringify(session)); // signed in sidebar state userInfo.classList.remove('hide'); userInfo.innerHTML = `Welcome, ${sessionInfo.username}.`; signOutButton.classList.remove('hide'); signInButton.classList.add('hide'); } }