Tax Parcel Viewer (10.1) and consuming secure services from arcgis server

2092
4
Jump to solution
01-24-2013 07:54 AM
KenBurcham
Occasional Contributor
Good morning!

  We're using the TPV and pointing it at map services that we need to secure for internal use only.  We only have one arcgis server and serve both public and secure services.  When I enable security on the arcgis server services that I'm using for the Tax Parcel Viewer, it stops working.

  I read up on the token feature in arcgis server and thought that looked like the way to go.  I created a token (using http://ourserver:6080/arcgis/tokens/) and used the HTTP Referrer to be the arcgis server.  Then I added that server and token to the proxy.config.  But that doesn't seem to work.  🙂 

proxy.config:
<--snip--> <ProxyConfig mustMatch="false">   <serverUrls>      <serverUrl url="http://ourserver/arcgis/rest/services/" matchAll="true" token="SECRETTOKEN"></serverUrl>   </serverUrls> </ProxyConfig>


I couldn't find any information on using TPV with secure services.  Is there a doc or what would be the steps to make this work?  Or maybe there's specific info somewhere on the javascript api in general consuming secure services?

Thanks!

ken.
0 Kudos
1 Solution

Accepted Solutions
KenBurcham
Occasional Contributor
Ah, I think I figured it out.  The proxy.config doesn't seem to be necessary.  Instead, if I use urls in my config.js that include the token in a query parameter it works:

http://ourserver/arcgis/rest/services/TaxParcelQuery/MapServer/0?token=SECRETTOKEN


So the steps are:

1) create and secure the service in arcgis server
2) go to http://ourserver/arcgis/tokens and create a token using the http referrer value of the server page (http://ourserver/taxparcelviewer/)
3) add "?token=SECRETTOKENSTRING" to the service urls in config.js of the Tax Parcel Viewer (obviously replacing with the token arcgis server generated for you).

Thanks!

ken.

View solution in original post

0 Kudos
4 Replies
KenBurcham
Occasional Contributor
Ah, I think I figured it out.  The proxy.config doesn't seem to be necessary.  Instead, if I use urls in my config.js that include the token in a query parameter it works:

http://ourserver/arcgis/rest/services/TaxParcelQuery/MapServer/0?token=SECRETTOKEN


So the steps are:

1) create and secure the service in arcgis server
2) go to http://ourserver/arcgis/tokens and create a token using the http referrer value of the server page (http://ourserver/taxparcelviewer/)
3) add "?token=SECRETTOKENSTRING" to the service urls in config.js of the Tax Parcel Viewer (obviously replacing with the token arcgis server generated for you).

Thanks!

ken.
0 Kudos
KenBurcham
Occasional Contributor
Ok I spoke a little too soon.  The basemap and the query services are working, but the layer service in the middle isn't. 

I've added a "Buildings" layer that I want to work like the "foreclosures" example.  When I turn off security it works fine, but enabling security and adding the token on the url isn't working.

When I look at the network tab in dev tools I can see that the request is being made but the token isn't accepted and so arcgis server returns a 302 redirect to the service login.  Here's a picture of the request and I think the problem is that the code might be appending its other query params directly with a "?" to the url I give that includes a "?token=" already:

[ATTACH=CONFIG]21037[/ATTACH]

I would attach code too, but as I said, it works fine if I disable security on the service and remove the token from the url, so I think that's all setup properly.

Any ideas?  Or is this maybe a bug?  I'll go dojo fishing next. 🙂

ken.
0 Kudos
KenBurcham
Occasional Contributor
I figured it out.  Had to hack on the CreateDYnamicServiceLayer in utils.js a bit.  Here's the result.  But when I click on the features they don't display their little window, so that's next!


function CreateDynamicServiceLayer(layerURL, layerIndex, layerId, isVisible, displayName) {
    var imageParams = new esri.layers.ImageParameters();
    var lastindex = layerURL.lastIndexOf('/');
    imageParams.layerIds = [layerIndex];
    imageParams.layerOption = esri.layers.ImageParameters.LAYER_OPTION_SHOW;
    var dynamicLayer = layerURL.substring(0, lastindex);
 
 var baseLayerURL = layerURL.substring(0,layerURL.lastIndexOf('?')); //kb - is without token.
 var token = layerURL.substring(layerURL.lastIndexOf('?')+1, layerURL.length); //kb - is "token=abcxyz"
 token = token.substring(token.lastIndexOf('=')+1,token.length);
 
 dynamicLayer = dynamicLayer + "?token="+token;
 
    var dynamicMapService = new esri.layers.ArcGISDynamicMapServiceLayer(dynamicLayer, {
        id: layerId,
        imageParameters: imageParams,
        visible: isVisible
    });

 var querySeparator = layerURL.lastIndexOf('?') ? '&' : '?'; //kb
 
    dojo.io.script.get({
  url: layerURL + querySeparator + 'f=json', //kb updated
        preventCache: true,
        callbackParamName: "callback",
        timeout: 10000,
        load: function (data) {
            layersCounter++;
            if (layersCounter == layers.length) {
                HideProgressIndicator();
            }
            var table = document.createElement("table");
            var tbody = document.createElement("tbody");
            table.appendChild(tbody);
            var tr = document.createElement("tr");
            tbody.appendChild(tr);

            var td = document.createElement("td");

            var checkbox = CreateCheckBox(layerId, layerIndex, false);

            checkbox.onclick = function () {
                if (this.getAttribute("state") == "check") {
                    this.src = "images/unchecked.png";
                    this.setAttribute("state", "uncheck");
                    dynamicMapService.hide();
                    map.infoWindow.hide();
                }
                else {
                    this.src = "images/checked.png";
                    this.setAttribute("state", "check");
                    ShowProgressIndicator();
                    dynamicMapService.show();
                    map.infoWindow.hide();
                    selectedGraphic = null;
                    map.getLayer(tempLayerId).clear();
                    map.getLayer(tempParcelLayerId).clear();
                }
                HideProgressIndicator();
            };

            td.appendChild(checkbox);
            tr.appendChild(td);

            td = document.createElement("td");
            var img = document.createElement("img");
            img.src = baseLayerURL + '/images/' + data.drawingInfo.renderer.symbol.url;
            if (isMobileDevice) {
                img.style.width = "44px";
                img.style.height = "44px";
            }
            else {
                img.style.width = "20px";
                img.style.height = "20px";
            }
            td.appendChild(img);

            tr.appendChild(td);

            td = document.createElement("td");
            td.appendChild(document.createTextNode(displayName));

            tr.appendChild(td);

            dojo.byId('divLayers').appendChild(table);
        },
        error: function (error) {
            layersCounter++;
            if (layersCounter == layers.length) {
                HideProgressIndicator();
            }
        }
    });
    return dynamicMapService;
}
0 Kudos
KenBurcham
Occasional Contributor
Ok, so clicking on my dynamic map layer ("Buildings" in my case) wouldn't show the little pop-up window and gave me an JSON error in the Response Body that said "Invalid Token"...  It was posting to the proxy.ashx file, so I found that the request being generated by that file had two problems.  1) It was not passing along the token and 2) it didn't have the Http Referer set in the request.  The latter was a problem because the token is tied to a referer.  So I edited the proxy.ashx file around line 31:

        // Get token, if applicable, and append to the request
        string token = "SUPERSECRETTOKEN"; //getTokenFromConfigFile(uri); <-- this method didn't work so I hard coded it here for now.
        if (!String.IsNullOrEmpty(token))
        {
            if (uri.Contains("?"))
                uri += "&token=" + token;
            else
                uri += "?token=" + token;
        }
          
        System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(uri);
        req.Referer="http://gisweb/TaxParcelViewerCTUIR/"; //kb:::added to make the token work!


Now it all seems to be working. Hope these notes help someone else in the future!

ken.
0 Kudos