How do I add a secured feature service using a token in 4.X?

7934
18
Jump to solution
03-25-2021 04:15 PM
MattStayner
Occasional Contributor II

I need to load a secured layer using an Esri token. In 3.X I did this:

const url = `${serviceUrl}?token=${esriToken}&f=json`
var featureLayer = new FeatureLayer({
  url: url
});

It worked great and would load the secure feature service.

I do the exact same thing in 4.X, and I get the pop-up asking me to sign in. I double-checked the URL, and it provides the JSON, so that's not the issue.

What gives? I already signed in using OAuth2. That's how I got the token. I don't want to have to sign in again. Please help. Thanks!

Tags (2)
0 Kudos
18 Replies
ZohaibUddinKhan
New Contributor II

Thanks @ReneRubalcava for the reply. I tried the change but no luck! Any clue what I'm doing wrong? I've created a separate post so that we can keep track and accept the solution later. (New post url: https://community.esri.com/t5/arcgis-api-for-javascript/how-to-access-secured-arcgis-server-map-serv...)

Following is my code for JS API v4.16:-

 

<script type="text/javascript">
        require([
            "esri/config",
            "esri/Basemap",
            "esri/Map",
            "esri/views/MapView",
            "esri/layers/VectorTileLayer",
            "esri/layers/FeatureLayer",
            "dojo/domReady!"
        ], function (esriConfig, Basemap, Map, MapView, VectorTileLayer, FeatureLayer
        ) {
            var initialLatitude = '-31.954594';
            var initialLongitude = '115.860299';
            var initialPoint = { type: "point", latitude: initialLatitude, longitude: initialLongitude };
            var vectorTileLayerID = '07a6b122323b4exxxxxxxc0a97b29';

            var wp_VectorTileLayer = new VectorTileLayer({
                portalItem: {
                    id: vectorTileLayerID
                }
            });

            var MDSbaseMap = new Basemap({
                baseLayers: [
                    wp_VectorTileLayer
                ]
            });

            var map = new Map({
                basemap: MDSbaseMap
            });

            var view = new MapView({
                container: "viewDiv",
                map: map,
                zoom: 11,
                constraints: {
                    minScale: 3000,  
                    maxScale: 30,  
                    rotationEnabled: false
                },
                center: initialPoint
            });

            view.popup.autoOpenEnabled = false;

            const featureLayerUrl = "https://services.slip.wa.gov.au/arcgis/rest/services/Landgate_v2_Subscription_Services/Cadastral/MapServer/41";
            //const featureLayerUrl = "https://token.slip.wa.gov.au/arcgis/rest/services/Landgate_v2_Subscription_Services/Cadastral/MapServer/41";

                esriConfig.request.interceptors.push({
                    urls: "https://services.slip.wa.gov.au/",
                    before: function (params) {
                        params.requestOptions.query = params.requestOptions.query || {};
                        params.requestOptions.query.token = "nXKRnEHxOLrxxxxxxxxxxxxxxtU4amjZzsrI.";//Get the token from https://token.slip.wa.gov.au/arcgis/tokens/
                    },
                });

            const layer = new FeatureLayer({
                url: featureLayerUrl
            });

            map.add(layer);

            view.ui.move(["zoom"], "bottom-left");

        });
    </script>

 

 

0 Kudos
jaykapalczynski
Frequent Contributor

I see that you are adding Query Parameters.....are there Edit parameters for editing?

0 Kudos
UndralBatsukh
Esri Regular Contributor

Hi there,

You can do couple of things. If you are using JS API version 4.18, then you can take advantage of FeatureLayer.customParameters property as it was introduced for cases like this one. You can do this:

var layer = new FeatureLayer({
  url: serviceUrl,
  customParameters: {
   "token": yourToken
  }
});

 

If you are using a version older than 4.18, then you can use interceptors to modify the request before it is sent. You can do this:

 const interceptor = {
    urls: [
    "url to the service",
  ],
  before({ url, requestOptions }) {
    requestOptions.query.token = "yourTOKEN";
  },
  after({ data, url, requestOptions }) {
    console.log("after", data, url, requestOptions);
  }
};
esriConfig.request.interceptors.push(interceptor);

const layer = new FeatureLayer({
  url: "service url"
});

 

Hope this helps,

-Undral

ZohaibUddinKhan
New Contributor II

Thanks @UndralBatsukh for the reply. We're using JS API version 4.18 and unfortunately it is still asking for the credentials. Am I doing something terribly wrong here ?  

Following is our code:-

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" />
    <title></title>
    <style>
        html,
        body,
        #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
    </style>
    <link rel="stylesheet" href="https://js.arcgis.com/4.18/esri/themes/light/main.css">
    <script src="https://js.arcgis.com/4.18/"></script>
    <script>
        require(["esri/config", "esri/Map", "esri/views/MapView", "esri/layers/FeatureLayer"], function (esriConfig, Map, MapView, FeatureLayer) {

            esriConfig.apiKey = "AAPK9c1060b46848481f85233a3e75........-......._hEZz";

            const map = new Map({
                basemap: "arcgis-topographic" // Basemap layer service
            });

            const view = new MapView({
                map: map,
                center: [115.860299, -31.954594], // Longitude, latitude
                zoom: 13, // Zoom level
                container: "viewDiv" // Div element
            });

            const featureLayerUrl = "https://services.slip.wa.gov.au/arcgis/rest/services/Landgate_v2_Subscription_Services/Cadastral/MapServer/41";
            //const featureLayerUrl = "https://token.slip.wa.gov.au/arcgis/rest/services/Landgate_v2_Subscription_Services/Cadastral/MapServer/41";

            var layer = new FeatureLayer({
                url: featureLayerUrl,                
                customParameters: {
                    "token": "nXKRnEHxOLrfCyVAs3......_....."//Get the token from https://token.slip.wa.gov.au/arcgis/tokens/
                }
            });

            map.add(layer);
        });
    </script>    
</head>
<body>
    <div id="viewDiv"></div>
</body>
</html>

and following are the results while browsing:-

4-18.JPG

0 Kudos
ReneRubalcava
Frequent Contributor

Check all the network requests to that domain and verify that the token is appended to the URL. Maybe a token source URL permission issue?

0 Kudos
ZohaibUddinKhan
New Contributor II

Thanks @ReneRubalcava for the reply and help. I can see the token is getting appended in the URL, but maybe CORS is the problem. Trying to find the solution to overcome it. If you have any suggestions then feel free to share. 

Esri-Token-Cors.PNG

0 Kudos
ReneRubalcava
Frequent Contributor

You'll need to enable CORS at the server level to fix this. How you do that can vary based on the type of server.

0 Kudos
ZohaibUddinKhan
New Contributor II

Hi @UndralBatsukh , thanks for the reply. I've created a separate post so that we can track the solution and mark it accepted later. 

Here is the Post https://community.esri.com/t5/arcgis-api-for-javascript/how-to-access-secured-arcgis-server-map-serv... 

0 Kudos
ReneRubalcava
Frequent Contributor

I don't know if this was available when this post was made, maybe, and I missed it, happens. But the layers have a property called customParameters you can use to add tokens like this.

https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-FeatureLayer.html#customPa...

In this case, you can avoid using an interceptor to add url params.