An ArcGIS identity, also known as named user, grants a short-lived access token giving your application permission to access the content and services authorized to your application user's existing ArcGIS Online or ArcGIS Enterprise account.
This temporary token is created using the OAuth 2.0 protocol. It authorizes your application to act on the user's behalf without revealing their secure password to your application. If your application will access your users' secure content in ArcGIS or if you plan to distribute your application through ArcGIS Marketplace, you must use ArcGIS identity authentication.
This tutorial demonstrates using the OAuth2.0 serverless web application workflow to implement the ArcGISIdentityManager class in ArcGIS REST JS and create an identity for a browser application.
Prerequisites
You need an account to register a new OAuth 2.0 application. If you do not have an ArcGIS account you can sign up for a free ArcGIS Developer account.
Update your registered application to specify the Redirect URLs to use for authentication, in the format "https://<server>[:port]" or http://my-arcgis-app:/auth. For example, if you are running your application on https://localhost:8080 add https://localhost:8080/authenticate.html, to the list of redirect URLs. You will create the authenticate.html page later in this tutorial.
Begin by creating a basic HTML page containing a button directing the user to the authorization page or pop-up. This will be the primary application page.
Create an HTML file to be used for your application and add references to the ArcGIS RestJS library.
index.html
Use dark colors for code blocks
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
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
<!DOCTYPE html><htmllang="en"><head><metacharset="utf-8" /><title>ArcGIS REST JS Browser OAuth2</title><linkrel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"crossorigin="anonymous" /><style>body {
font-family: monospace;
color: black;
font-size: 20px;
}
pre {
overflow: auto;
padding: 1rem;
}
.col-xs-12 {
margin-top: 10%;
}
#withPopupButton,
#signOutButton {
font-size: 20px;
}
</style></head><body><divid="app-wrapper"><divclass="container"><divclass="row"><divclass="col-xs-12"><!-- Event listeners planned to be added to these buttons. --><buttonclass="btn btn-primary btn-block"id="withPopupButton">Sign In</button></div></div><divclass="row"><divclass="col-xs-12 text-center"><pid="sessionInfo"class="info-panel"><!-- Information will be injected here. --></p></div></div><divclass="row"><divclass="col-xs-12 text-center"><!-- Event listeners will be added to these buttons. --><buttonclass="btn btn-primary btn-block btn-warning"id="signOutButton">Sign Out</button></div></div></div></div><scripttype="module">import { ArcGISIdentityManager } from'https://cdn.skypack.dev/@esri/arcgis-rest-request@4.0.0';
let session = null;
const clientId = "CLIENT_ID";
const redirectUri = window.location.origin + "/authenticate.html";
const serializedSession = localStorage.getItem("__ARCGIS_REST_USER_SESSION__"); // Check to see if there is a serialized session in local storage.if (serializedSession !== null && serializedSession !== "undefined") {
session = ArcGISIdentityManager.deserialize(serializedSession);
}
functionupdateSessionInfo(session) {
let sessionInfo = document.getElementById("sessionInfo");
if (session) {
sessionInfo.classList.remove("bg-info");
sessionInfo.classList.add("bg-success");
sessionInfo.innerHTML = "Logged in as " + session.username;
localStorage.setItem("__ARCGIS_REST_USER_SESSION__", session.serialize());
} else {
sessionInfo.classList.remove("bg-success");
sessionInfo.classList.add("bg-info");
sessionInfo.innerHTML = "Log in to start a session.";
}
}
updateSessionInfo(session);
document.getElementById("withPopupButton").addEventListener("click", (event) => {
// Begin an OAuth2 login using a popup. ArcGISIdentityManager.beginOAuth2({
clientId: clientId,
redirectUri: redirectUri,
popup: true })
.then((newSession) => {
// Upon a successful login, update the session with the new session. session = newSession;
console.log(session);
updateSessionInfo(session);
})
.catch((error) => {
console.log(error);
});
event.preventDefault();
});
document.getElementById("signOutButton").addEventListener("click", (event) => {
event.preventDefault();
// call the signOut method to invalidate the token. session.signOut().then(()=>{
session = null; // Clear the session from memory.localStorage.removeItem("__ARCGIS_REST_USER_SESSION__");
updateSessionInfo();
});
});
</script></body></html>
Import the Bootstrap CSS framework and add Sign in and Sign Out buttons, as well as a sessionInfo area to place user information.
Create session and clientId elements. Set the clientId with the Client ID copied from the dashboard.
Set the redirect_uri to the redirect URI you configured for your application.
index.html
Use dark colors for code blocks
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
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
<!DOCTYPE html><htmllang="en"><head><metacharset="utf-8" /><title>ArcGIS REST JS Browser OAuth2</title><linkrel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"crossorigin="anonymous" /><style>body {
font-family: monospace;
color: black;
font-size: 20px;
}
pre {
overflow: auto;
padding: 1rem;
}
.col-xs-12 {
margin-top: 10%;
}
#withPopupButton,
#signOutButton {
font-size: 20px;
}
</style></head><body><divid="app-wrapper"><divclass="container"><divclass="row"><divclass="col-xs-12"><!-- Event listeners planned to be added to these buttons. --><buttonclass="btn btn-primary btn-block"id="withPopupButton">Sign In</button></div></div><divclass="row"><divclass="col-xs-12 text-center"><pid="sessionInfo"class="info-panel"><!-- Information will be injected here. --></p></div></div><divclass="row"><divclass="col-xs-12 text-center"><!-- Event listeners will be added to these buttons. --><buttonclass="btn btn-primary btn-block btn-warning"id="signOutButton">Sign Out</button></div></div></div></div><scripttype="module">import { ArcGISIdentityManager } from'https://cdn.skypack.dev/@esri/arcgis-rest-request@4.0.0';
let session = null;
const clientId = "CLIENT_ID";
const redirectUri = window.location.origin + "/authenticate.html";
const serializedSession = localStorage.getItem("__ARCGIS_REST_USER_SESSION__"); // Check to see if there is a serialized session in local storage.if (serializedSession !== null && serializedSession !== "undefined") {
session = ArcGISIdentityManager.deserialize(serializedSession);
}
functionupdateSessionInfo(session) {
let sessionInfo = document.getElementById("sessionInfo");
if (session) {
sessionInfo.classList.remove("bg-info");
sessionInfo.classList.add("bg-success");
sessionInfo.innerHTML = "Logged in as " + session.username;
localStorage.setItem("__ARCGIS_REST_USER_SESSION__", session.serialize());
} else {
sessionInfo.classList.remove("bg-success");
sessionInfo.classList.add("bg-info");
sessionInfo.innerHTML = "Log in to start a session.";
}
}
updateSessionInfo(session);
document.getElementById("withPopupButton").addEventListener("click", (event) => {
// Begin an OAuth2 login using a popup. ArcGISIdentityManager.beginOAuth2({
clientId: clientId,
redirectUri: redirectUri,
popup: true })
.then((newSession) => {
// Upon a successful login, update the session with the new session. session = newSession;
console.log(session);
updateSessionInfo(session);
})
.catch((error) => {
console.log(error);
});
event.preventDefault();
});
document.getElementById("signOutButton").addEventListener("click", (event) => {
event.preventDefault();
// call the signOut method to invalidate the token. session.signOut().then(()=>{
session = null; // Clear the session from memory.localStorage.removeItem("__ARCGIS_REST_USER_SESSION__");
updateSessionInfo();
});
});
</script></body></html>
Create a callback page
Once the user is authorized, the access token must be retrieved and passed from the pop-up to the main application page the ArcGISIdentityManager.completeOAuth2 method will automatically handle this.
Open an editor and create an authenticate.html file with references to the ArcGIS REST JS library.
Call the ArcGISIdentityManager.completeOAuth2 method. This will get the access token, pass it back to the main application page and close the popup window.
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
<!DOCTYPE html><htmllang="en"><head><metacharset="utf-8" /><title>ArcGIS REST JS Browser OAuth2</title><linkrel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"crossorigin="anonymous" /><style>body {
font-family: monospace;
color: black;
font-size: 20px;
}
pre {
overflow: auto;
padding: 1rem;
}
.col-xs-12 {
margin-top: 10%;
}
#withPopupButton,
#signOutButton {
font-size: 20px;
}
</style></head><body><divid="app-wrapper"><divclass="container"><divclass="row"><divclass="col-xs-12"><!-- Event listeners planned to be added to these buttons. --><buttonclass="btn btn-primary btn-block"id="withPopupButton">Sign In</button></div></div><divclass="row"><divclass="col-xs-12 text-center"><pid="sessionInfo"class="info-panel"><!-- Information will be injected here. --></p></div></div><divclass="row"><divclass="col-xs-12 text-center"><!-- Event listeners will be added to these buttons. --><buttonclass="btn btn-primary btn-block btn-warning"id="signOutButton">Sign Out</button></div></div></div></div><scripttype="module">import { ArcGISIdentityManager } from'https://cdn.skypack.dev/@esri/arcgis-rest-request@4.0.0';
let session = null;
const clientId = "CLIENT_ID";
const redirectUri = window.location.origin + "/authenticate.html";
const serializedSession = localStorage.getItem("__ARCGIS_REST_USER_SESSION__"); // Check to see if there is a serialized session in local storage.if (serializedSession !== null && serializedSession !== "undefined") {
session = ArcGISIdentityManager.deserialize(serializedSession);
}
functionupdateSessionInfo(session) {
let sessionInfo = document.getElementById("sessionInfo");
if (session) {
sessionInfo.classList.remove("bg-info");
sessionInfo.classList.add("bg-success");
sessionInfo.innerHTML = "Logged in as " + session.username;
localStorage.setItem("__ARCGIS_REST_USER_SESSION__", session.serialize());
} else {
sessionInfo.classList.remove("bg-success");
sessionInfo.classList.add("bg-info");
sessionInfo.innerHTML = "Log in to start a session.";
}
}
updateSessionInfo(session);
document.getElementById("withPopupButton").addEventListener("click", (event) => {
// Begin an OAuth2 login using a popup. ArcGISIdentityManager.beginOAuth2({
clientId: clientId,
redirectUri: redirectUri,
popup: true })
.then((newSession) => {
// Upon a successful login, update the session with the new session. session = newSession;
console.log(session);
updateSessionInfo(session);
})
.catch((error) => {
console.log(error);
});
event.preventDefault();
});
document.getElementById("signOutButton").addEventListener("click", (event) => {
event.preventDefault();
// call the signOut method to invalidate the token. session.signOut().then(()=>{
session = null; // Clear the session from memory.localStorage.removeItem("__ARCGIS_REST_USER_SESSION__");
updateSessionInfo();
});
});
</script></body></html>
Create a session from local storage
ArcGIS REST JS does not include tools for persisting a session after retrieving session information. You must decide how to implement persisting the session and specify where the user goes after they authorize your application.
Create a serializedSession function that checks if there is a session in local storage. You can use the ArcGISIdentityManager.deserialize method to parse the serializedSession data.
index.html
Use dark colors for code blocks
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
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
<!DOCTYPE html><htmllang="en"><head><metacharset="utf-8" /><title>ArcGIS REST JS Browser OAuth2</title><linkrel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"crossorigin="anonymous" /><style>body {
font-family: monospace;
color: black;
font-size: 20px;
}
pre {
overflow: auto;
padding: 1rem;
}
.col-xs-12 {
margin-top: 10%;
}
#withPopupButton,
#signOutButton {
font-size: 20px;
}
</style></head><body><divid="app-wrapper"><divclass="container"><divclass="row"><divclass="col-xs-12"><!-- Event listeners planned to be added to these buttons. --><buttonclass="btn btn-primary btn-block"id="withPopupButton">Sign In</button></div></div><divclass="row"><divclass="col-xs-12 text-center"><pid="sessionInfo"class="info-panel"><!-- Information will be injected here. --></p></div></div><divclass="row"><divclass="col-xs-12 text-center"><!-- Event listeners will be added to these buttons. --><buttonclass="btn btn-primary btn-block btn-warning"id="signOutButton">Sign Out</button></div></div></div></div><scripttype="module">import { ArcGISIdentityManager } from'https://cdn.skypack.dev/@esri/arcgis-rest-request@4.0.0';
let session = null;
const clientId = "CLIENT_ID";
const redirectUri = window.location.origin + "/authenticate.html";
const serializedSession = localStorage.getItem("__ARCGIS_REST_USER_SESSION__"); // Check to see if there is a serialized session in local storage.if (serializedSession !== null && serializedSession !== "undefined") {
session = ArcGISIdentityManager.deserialize(serializedSession);
}
functionupdateSessionInfo(session) {
let sessionInfo = document.getElementById("sessionInfo");
if (session) {
sessionInfo.classList.remove("bg-info");
sessionInfo.classList.add("bg-success");
sessionInfo.innerHTML = "Logged in as " + session.username;
localStorage.setItem("__ARCGIS_REST_USER_SESSION__", session.serialize());
} else {
sessionInfo.classList.remove("bg-success");
sessionInfo.classList.add("bg-info");
sessionInfo.innerHTML = "Log in to start a session.";
}
}
updateSessionInfo(session);
document.getElementById("withPopupButton").addEventListener("click", (event) => {
// Begin an OAuth2 login using a popup. ArcGISIdentityManager.beginOAuth2({
clientId: clientId,
redirectUri: redirectUri,
popup: true })
.then((newSession) => {
// Upon a successful login, update the session with the new session. session = newSession;
console.log(session);
updateSessionInfo(session);
})
.catch((error) => {
console.log(error);
});
event.preventDefault();
});
document.getElementById("signOutButton").addEventListener("click", (event) => {
event.preventDefault();
// call the signOut method to invalidate the token. session.signOut().then(()=>{
session = null; // Clear the session from memory.localStorage.removeItem("__ARCGIS_REST_USER_SESSION__");
updateSessionInfo();
});
});
</script></body></html>
Update session info
Create an updateSessionInfo function that adds the username to sessionInfo if the user is signed in. If not, ask the user to log in with their credentials.
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
<!DOCTYPE html><htmllang="en"><head><metacharset="utf-8" /><title>ArcGIS REST JS Browser OAuth2</title><linkrel="stylesheet"href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"crossorigin="anonymous" /><style>body {
font-family: monospace;
color: black;
font-size: 20px;
}
pre {
overflow: auto;
padding: 1rem;
}
.col-xs-12 {
margin-top: 10%;
}
#withPopupButton,
#signOutButton {
font-size: 20px;
}
</style></head><body><divid="app-wrapper"><divclass="container"><divclass="row"><divclass="col-xs-12"><!-- Event listeners planned to be added to these buttons. --><buttonclass="btn btn-primary btn-block"id="withPopupButton">Sign In</button></div></div><divclass="row"><divclass="col-xs-12 text-center"><pid="sessionInfo"class="info-panel"><!-- Information will be injected here. --></p></div></div><divclass="row"><divclass="col-xs-12 text-center"><!-- Event listeners will be added to these buttons. --><buttonclass="btn btn-primary btn-block btn-warning"id="signOutButton">Sign Out</button></div></div></div></div><scripttype="module">import { ArcGISIdentityManager } from'https://cdn.skypack.dev/@esri/arcgis-rest-request@4.0.0';
let session = null;
const clientId = "CLIENT_ID";
const redirectUri = window.location.origin + "/authenticate.html";
const serializedSession = localStorage.getItem("__ARCGIS_REST_USER_SESSION__"); // Check to see if there is a serialized session in local storage.if (serializedSession !== null && serializedSession !== "undefined") {
session = ArcGISIdentityManager.deserialize(serializedSession);
}
functionupdateSessionInfo(session) {
let sessionInfo = document.getElementById("sessionInfo");
if (session) {
sessionInfo.classList.remove("bg-info");
sessionInfo.classList.add("bg-success");
sessionInfo.innerHTML = "Logged in as " + session.username;
localStorage.setItem("__ARCGIS_REST_USER_SESSION__", session.serialize());
} else {
sessionInfo.classList.remove("bg-success");
sessionInfo.classList.add("bg-info");
sessionInfo.innerHTML = "Log in to start a session.";
}
}
updateSessionInfo(session);
document.getElementById("withPopupButton").addEventListener("click", (event) => {
// Begin an OAuth2 login using a popup. ArcGISIdentityManager.beginOAuth2({
clientId: clientId,
redirectUri: redirectUri,
popup: true })
.then((newSession) => {
// Upon a successful login, update the session with the new session. session = newSession;
console.log(session);
updateSessionInfo(session);
})
.catch((error) => {
console.log(error);
});
event.preventDefault();
});
document.getElementById("signOutButton").addEventListener("click", (event) => {
event.preventDefault();
// call the signOut method to invalidate the token. session.signOut().then(()=>{
session = null; // Clear the session from memory.localStorage.removeItem("__ARCGIS_REST_USER_SESSION__");
updateSessionInfo();
});
});
</script></body></html>
Run the app
Run the application and navigate to your localhost, for example: https://localhost:8080. You will see the sign in page:
When you click Sign in, a pop-up prompts you to enter your credentials. Upon successful authorization, you are redirected to the home page where your username is displayed.