how to generate correct token for a federated Enterprise service

1467
9
Jump to solution
03-22-2023 03:43 PM
DanielDormont
New Contributor III

I have a customer who has an on-premise ArcGIS Enterprise instance which uses Integrated Windows Authentication. I am trying to allow those users to display certain Feature layers on a map in my web application, using that authentication and/or OAuth.

It appears that the ArcGIS Javascript API, using some mechanism I don't understand, is able to make requests to this Enterprise instance without providing a token, directly using IWA. However, in my map I am not using ArcGIS Javascript but rather Esri Leaflet.

Experimenting a bit, and trying to compare the behavior seen in the ArcGIS Online Assistant, I was able, using the ArcGIS Javascript API, to make a successful call to generateToken. My call looks roughly like https://site.customerdomain.com/webadaptor/sharing/rest/generateToken with params of 

f=json&client=referer&expiration=60&referer=mysite.mydomain.com

This token is then able to successfully retrieve service data as configured in the web map, with URLs that look like

https://site.customerdomain.com/gisurl/rest/services/Actual_Service/MapServer/?token=<token>&f=json

But some of the services they want to use are on a federated server of some sort, and the endpoint looks like

https://site.customerdomain.com.com/webadaptor/sharing/servers/<serverid>/rest/services/Service_Name...

These endpoints are failing with a 401 Unauthorized response code, and I am unable to see the response body due to a CORS error.

What would cause this 401 Unauthorized response and how do I generate a token that will be accepted by this federated server?

0 Kudos
1 Solution

Accepted Solutions
DanielDormont
New Contributor III

In case anyone else runs across this issue, it turns out that if you are querying feature services from a server that uses Integrated Windows Authentication, you have to use the `withCredentials` setting on your client requests. It seems the ArcGIS Javascript API somehow knows to do this automatically, but if you are using, for example, Leaflet, you have to set it yourself. Thanks to @ZachBray for setting me down the right path.

View solution in original post

0 Kudos
9 Replies
ZachBray
New Contributor II

This sounds like a permissions error regarding sharing those layers in the ArcGIS Portal.  Connect to the Portal as an admin or someone that has control over the Content.  Select Content (usually across the top of the web page), then select the Feature Service or Web Map in question and check the Share permissions.

ZachBray_0-1679571270945.png

ZachBray_1-1679571343535.png

 

0 Kudos
DanielDormont
New Contributor III

Hi @ZachBray thanks for responding. This is really my first time working with Enterprise closely, and I myself don't personally have access to the system, so I'm just trying to understand how this is all supposed to work. I believe they've already configured authentication on the "registered" layer coming from this other server, but I am not very familiar with the mechanics. 

Should each server need its own token? Or even if it "shouldn't", might it in this type of case? _Is_ there a way through the REST API to call generateToken for a federated server?

0 Kudos
ZachBray
New Contributor II

If the ArcGIS Server is Federated with the Portal then you would only need one token.  In that case the Portal is the identity store for the Federated ArcGIS Servers.  If the ArcGIS Server is NOT Federated then you would need a token for each server.  Since you said this was an Enterprise deployment I am assuming they are Federated.

When requesting the token in the Federated system you would use and the authentication is just AD integrated then:

https://machinename.domain.com/PORTAL_webadapter/sharing/rest/generateToken

If they have an Open ID or OAuth login configured then you would use:

https://machinename.domain.com/PORTAL_webadapter/sharing/rest/oauth2/authorize   This is a different authentication method and it requires a postback URI that your code would have to deal with.

https://developers.arcgis.com/rest/users-groups-and-items/authorize.htm

 

0 Kudos
DanielDormont
New Contributor III

Thanks, yeah, actually I tried OAuth initially. Pretty much exactly following the documentation found in https://developers.arcgis.com/esri-leaflet/authentication/oauth2/ That was able to successfully generate a token, but that token was not accepted by any of the map service layers, even the ones hosted on the same server that the users were logging into with the Portal. And the error was the same one I'm seeing now - an HTTP 401 Unauthorized, which is different from the usual "498 Invalid Token" error I've seen in other cases where I was not passing a correct token.

That was already surprising, which sent me down this path of trying to calling generateToken, which does seem to work for the internal layers. I now confirmed from my customer see that the layers that are failing now are actually NOT federated, I misunderstood this earlier.

So I guess my new question is: given a non-federated registered layer with an address like:

https://gisweb1.customerdomain.com/customerportal/sharing/servers/someserverid/rest/services/Layer_N...

What endpoint should I be calling to generate the token, given an existing token I already got from 

https://gisweb1.customerdomain.com/customerportal/sharing/rest/generateToken

 

0 Kudos
ZachBray
New Contributor II

My system is Federated so I cannot test this.  according to the documentation it should be https://machine.domain.com/webadaptor/sharing/rest/generateToken.  So replace your customerPortal with customerserver.

I have two webadapters, one for portal, one for server on one IIS server separate from the ArcGIS Server and ArcGIS Portal.  So mine is https://IIS_server_name.domain.com/portal/sharing/rest/generateToken  If my server was unFederated it would be https://IIS_server_name.domain.com/server/sharing/rest/generateToken 

Hope this helps.

FYI I use the app POSTMAN to test these.  You can enter the URL you want to try along with what ever parameters and etc.  Then fiddle with things to get it right.  Hope that helps some.

0 Kudos
DanielDormont
New Contributor III

Thanks for your help. Unforunately that doesn't seem to quite match what I'm seeing, which are layers with addresses that look like 

https://gisweb1.domain.com/portal/sharing/servers/someserverid/rest/services/Layer_Name/FeatureServe...

I'm not familiar with this "servers/<serverid>" thing and the only documentation I can find on it seems to be specific to the ArcGIS Server Administration API, which is not what I'm trying to use here.

0 Kudos
ZachBray
New Contributor II

I hope you can access the ArcGIS Developers site, here is a link to a different generateToken: https://developers.arcgis.com/rest/services-reference/enterprise/generate-token.htm

This gets the token from a ArcGIS Server vs a ArcGIS Portal.  The call looks like https://<host>:<port>/<site>/tokens/generateToken this is POST only.  Without knowing the setup of ArcGIS Servers and Portals it is hard to say exactly what your call would be.  the <host> would refer to the fully qualified domain name, machine name and domain name of the ArcGIS Server you want to connect to.  A default install of ArcGIS Server would use port 6443.  The default site is probably arcgis.  Putting it together something like https://server_machine_name.domain.com:6443/arcgis/tokens/generateToken .

The "portal" in your example URL does not really match up with this generateToken.  I would have expected to have a federated server with "portal" in the URL.  That is the only way I am aware of to publish services to a ArcGIS Portal.

You had mentioned that you had followed the OAuth example.  One thing that tripped me up was I used a response_type=code instead of response_type=token.  When I tried to pass back the "code" I received, I got the same HTTP 401 Unauthorized you mention.  If you followed everything exactly from the link you provided this should not be the problem.

Good luck

DanielDormont
New Contributor III

Thanks, that at least gives me a direction to look in. And I had not really considered the "response_type=code" idea either. That's pretty intriguing. I might give that another try as well.

0 Kudos
DanielDormont
New Contributor III

In case anyone else runs across this issue, it turns out that if you are querying feature services from a server that uses Integrated Windows Authentication, you have to use the `withCredentials` setting on your client requests. It seems the ArcGIS Javascript API somehow knows to do this automatically, but if you are using, for example, Leaflet, you have to set it yourself. Thanks to @ZachBray for setting me down the right path.

0 Kudos