I have an ASP.NET MVC web application that is authenticating users server-side against ArcGIS Portal successfully using Owin.Security.Providers.ArcGISPortal.
I would like to use the granted authorization client-side in the browser without requiring the user to login a second time via ArcGIS's JavaScript API. Does anyone have any pointers regarding how to obtain a relevant token and pass this through client-side to access portal secured web maps, etc.?
There is a context.AccessToken
that I obtain via ArcGISPortalAuthenticationHandler and make available as a claim in order to share the access token.
Any ideas? If you know of a working example for ArcGIS Online then this could also help me as ArcGIS Online and ArcGIS Portal seem to be identical in their mechanics.
Further investigation…
Following the linked example found through the documentation for esri.IdentityManager.registerToken(), I've tried the following method to share the access token:
var credentialsJSON = {
serverInfos: [{
server: "https://[HOST]",
tokenServiceUrl: "https://[HOST]/arcgis/tokens/",
adminTokenServiceUrl: "https://[HOST]/arcgis/admin/generateToken",
shortLivedTokenValidity: 1800,
currentVersion: 10.5,
hasServer: true
}],
oAuthInfos: [],
credentials: [{
userId: user.userId,
server: "https://[HOST]/arcgis",
token: user.userAccessToken,
expires: user.userAccessTokenExpiry,
validity: 1800,
isAdmin: false,
ssl: false,
creationTime: user.userAccessTokenIssued,
scope: "server"
}]
};
esriId.initialize(credentialsJSON);
But I'm still not getting access to the webmap. I see a html login modal over the empty map div with the title "Please sign in to access the item on https://[HOST]/arcgis (b11824af61df463586dad40d1df7abbd)".
In the console log I see the following message logged:
dojo.io.script error Error: You do not have permissions to access this resource or perform this operation.
at Object.g.load (init.js:984)
at init.js:87
at c (init.js:103)
at d (init.js:103)
at a.Deferred.resolve.callback (init.js:105)
at c (init.js:104)
at d (init.js:103)
at a.Deferred.resolve.callback (init.js:105)
at init.js:999
at n (init.js:107)
and for the network request to
I see the following response:
dojo.io.script.jsonp_dojoIoScript1._jsonpCallback({"error":{"code":403,"messageCode":"GWM_0003","message":"You do not have permissions to access this resource or perform this operation.","details":[]}});
Best Answer
A full solution detailing all the moving parts both server-side and client side...
Server Side OAuth
Download and include the Owin.Security.Providers.ArcGISPortal project in your solution.
Add supporting configuration settings to the web.config file:
Hook up the OAuth provider in OWIN Startup:
Add supporting Account Controller methods:
Add helper methods to expose OAuth tokens and provide a method to refresh the access token:
Add an API Controller to provide a method the client-side application can call to obtain a refreshed OAuth access token:
Client Side OAuth
The ArcGIS API for JavaScript has very good mechanisms supporting it's OAuth 2.0 provider for map based single-page-applications, but if there's a server-side component that needs to share the authentication then some extra effort is required.
Provide a log-off mechanism for use by both the user and that can be called through JavaScript:
Make server-side information available to the client-side application:
Use the access token with ArcGIS API for JavaScript code. The following code example includes the following:
Redirecting the user to the login form if there's an error refreshing the access token (possibly because their login has expired).
require(['dojo/ready', 'dojo/promise/all', 'esri/map', 'esri/IdentityManager', 'esri/request', 'esri/config', 'esri/arcgis/utils', 'esri/tasks/GeometryService', 'dojo/domReady!'], function (ready, all, Map, esriId, esriRequest, Config, Utils, GeometryService) { ready(function () {
});
It's worth noting that the server-side obtained access token is likely to have a longer lifespan than the client-side authentication context, obtained by registering the access token through the ArcGIS API for JavaScript esriId.registerToken(token) method. For this reason we need extra logic to check for authentication failures and force the user to re-login when problems are detected.
It's possible that a web page may show content to a user whos authentication has timed-out. The user may not be aware of the timeout, continuing to try to use single-page-application type functionality that relies on calls to an authentication-protected API. The resulting experience for the user being that the application is broken as it's no longer refreshing data. In such cases it's desirable to intercept all API call responses, checking for a 401 unauthenticated response and redirecting the user to the login form.
Angular JS example of intercepting all API call responses to check for 401 unauthenticated responses to action: