Manually passing secure token info to Legend dijit

5043
3
12-23-2011 12:02 AM
BabbageOcelot
New Contributor
Hi all,

A quick query regarding the legend dijit. We're currently using SOAP to get a security token (a particular requirement of this project), and passing that over to the JS frontend. This works perfectly well with everything except the legend dijit.

The URLs it creates are malformed, because our hard-coded layer url attribute contains the "?token=mytoken" suffix:
http://myserver/ArcGIS/rest/services/folder/service/MapServer?token=mytoken./legend

Now I know this works with the IdentityManager; is there some Credential object I can create in a particular place for the legend dijit to pick it up? Any other suggestions, besides reinventing the legend dijit with some URL sanity checks?

Cheers, Ben.
0 Kudos
3 Replies
KellyHutchins
Esri Frequent Contributor
Ben,

I ran a quick test using the legend dijit along with using esri.request to get the token and the secure service displayed correctly in the legend:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <meta http-equiv="X-UA-Compatible" content="IE=7" />
  <title>Accessing secure ArcGIS Server services</title>

  <link rel="stylesheet" type="text/css" href="https://serverapi.arcgisonline.com/jsapi/arcgis/2.6/js/dojo/dijit/themes/claro/claro.css">
  <link rel="stylesheet" type="text/css" href="security.css">
  <style type="text/css">
      html, body {
        height: 98%; width: 99%;
        margin:0;
        padding-top:4px;
        padding-left:4px;
      }

      #rightPanel{
        width:140px;
        border:2px solid #617798;
        -webkit-border-top-right-radius: 4px;
        -webkit-border-bottom-right-radius: 4px;
        -moz-border-radius-topright: 4px;
        -moz-border-radius-bottomright: 4px;
        border-top-right-radius: 4px;
        border-bottom-right-radius: 4px;
      }
      #status {
        font-size: 14px;
        font-weight:bold;
      }
      #mapCanvas{
        border-top:2px solid #617798;
        border-bottom:2px solid #617798;
        border-left:2px solid #617798;
        -webkit-border-top-left-radius: 4px;
        -webkit-border-bottom-left-radius: 4px;
        -moz-border-radius-topleft: 4px;
        -moz-border-radius-bottomleft: 4px;
        border-top-left-radius: 4px;
        border-bottom-left-radius: 4px;
        padding:0px;
      }
     .submit input{
        width:auto;
        padding: 9px 15px;
        background: #617798;
        border:0;
        font-size:14px;
        color:#FFF;
        cursor:pointer;
        -webkit-border-radius: 4px;
        -moz-border-radius: 4px;
        border-radius: 4px;
     }
     input{
        padding:5px;
        border: solid 1px #E5E5E5;
        outline:0;
        font:normal 13px;
        width:120px;
        background: #FFFFFF url('bg_form.png') left top repeat-x;
        background: -webkit-gradient(linear, left top, left 25, from(#FFFFFF), color-stop(4%, #EEEEEE), to(#FFFFFF));
        background: -moz-linear-gradient(top, #FFFFFF, #EEEEEE 1px, #FFFFFF 25px);
        box-shadow: rgba(0,0,0, 0.1) 0px 0px 8px;
        -moz-box-shadow: rgba(0,0,0, 0.1) 0px 0px 8px;
        -webkit-box-shadow: rgba(0,0,0, 0.1) 0px 0px 8px;
     }
     label{
        margin-right:10px;
        color:#999;
     }
     input:hover, textarea:hover,
     input:focus, textarea:focus {
         border-color: #C9C9C9;
        -webkit-box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 8px;
     }




  </style>
  <script type="text/javascript">
    var dojoConfig = { parseOnLoad: true };
  </script>

  <script type="text/javascript" src="https://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.4"></script>

  <script type="text/javascript">
    dojo.require("dijit.layout.BorderContainer");
    dojo.require("dijit.layout.ContentPane");
    dojo.require("esri.map");
    dojo.require("esri.layers.FeatureLayer");
 dojo.require("esri.dijit.Legend");
 
 
    dojo.addOnLoad(initialize);

    // Global variables
    var map,resizeTimer;


    function initialize() {

    //check to see if browser supports placeholder text - if not enable labels for username and
    //password form.
      if(!supportsPlaceholder()){
        esri.show(dojo.byId('passwordLabel'));
        esri.show(dojo.byId('nameLabel'));
      }


      esri.config.defaults.io.proxyUrl = "proxy/proxy.php";

      // Create map
      map = new esri.Map("mapCanvas",{
        extent: new esri.geometry.Extent({"xmin":-12080521,"ymin":4472736,"xmax":-11829657,"ymax":4563023,"spatialReference":{"wkid":3857}}),
        slider: false
      });

      dojo.connect(map, "onLoad", mapLoaded);
      // Add a cached map service
      var basemap = new esri.layers.ArcGISTiledMapServiceLayer("https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer");
      map.addLayer(basemap);

      //add the map service to the map - this layer doesn't require a token

      var trailsService = new esri.layers.ArcGISDynamicMapServiceLayer("https://servicesbeta.esri.com/ArcGIS/rest/services/SanJuan/Trails/MapServer");
      map.addLayer(trailsService);
    }

    function mapLoaded() {
      esri.hide(dojo.byId("status"));

      dojo.connect(dojo.byId("username"), "onkeypress", keyPressed);
      dojo.connect(dojo.byId("password"), "onkeypress", keyPressed);


      dojo.connect(dijit.byId('mapCanvas'), 'resize', function() {
          resizeMap();
      });

    }

    function signIn() {
      // Check if the user has entered username and password
      var usr = dojo.byId("username").value, pwd = dojo.byId("password").value;
      if (!usr || !pwd) {
        return;
      }

      dojo.byId("signInStatus").innerHTML = "Creating token...";

      // Get token from the ArcGIS Server Token Service.
      //
      esri.request({
        url: "https://servicesbeta.esri.com/ArcGIS/tokens",
        content: {
          request: "getToken",
          username: usr,
          password: pwd
        },
        handleAs: "text",
        load: tokenObtained,
        error: tokenRequestFailed
      });
    }

    function tokenObtained(response) {
      dojo.byId("signInStatus").innerHTML = "Token created. Accessing the service...";

      // Add the secure feature service to the map
      // Note that the token is appended to the URL
      // when constructing the layer.

     var featureLayerURL = "https://servicesbeta.esri.com/ArcGIS/rest/services/SanJuan/TrailConditions/MapServer/0?token=" + response;

     var infoTemplate = new esri.InfoTemplate("Current Conditions", "${Condition} incident updated on ${UpdateDate:DateFormat(selector: 'date', fullYear: true)}. ${Description}");

     var conditions = new esri.layers.FeatureLayer(featureLayerURL,{
      infoTemplate:infoTemplate,
      outFields:["*"]
     });
     conditions.setDefinitionExpression("Description != ''");


      dojo.connect(conditions, "onLoad", function() {
        setTimeout(function() {
        //  closeSignInForm();
          dojo.byId("signInStatus").innerHTML = "";
        }, 1500);
      });

      dojo.connect(conditions, "onError", function(error) {
        dojo.byId("signInStatus").innerHTML = "Error: " + error.message;
      });
   
   dojo.connect(map,'onLayerAddResult',function(results){
    console.log('added');
    //add legend 
    var legendDijit = new esri.dijit.Legend({
   map:map
    },"legendDiv");
    legendDijit.startup();   
   
   });
   
      map.addLayers([conditions]);

      map.infoWindow.resize(200,120);

    }

    function tokenRequestFailed(error) {
      dojo.byId("signInStatus").innerHTML = "Unable to create token. Please check your username/password";
    }


    function keyPressed(e) {
      if (e.charOrCode === dojo.keys.ENTER) {
        signIn();
      }
    }

   //Handle resize of browser
      function resizeMap(){
        clearTimeout(resizeTimer);
        resizeTimer = setTimeout(function(){
          map.resize();
          map.reposition();
        }, 500);

     }

     function supportsPlaceholder() {
     // An alternative to this test would be to use a javascript library like
      //Modernizr that detects support for HTML5 and CSS3 functionality.
        var i = document.createElement('input');
        return 'placeholder' in i;
      }
   function disableSignInForm() {
      dojo.byId("username").value = "";
      dojo.byId("password").value = "";

      var node = dojo.byId("content"), box = dojo.contentBox(node);
      dojo.style(node, { top: 0, opacity: 1 });

      var hideAnimation = dojo.animateProperty({
        node: node,
        duration: 500,
        properties: { top: -1 * box.h, opacity: 0 }
      });

      hideAnimation.play();
    }


  </script>
</head>

<body class="claro">
  <div data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design:'headline',gutters:false" style="position:relative;width:100%;height:100%;">
   <div id="mapCanvas" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'center'" >
     <span id="status" style="position: absolute; z-index: 99; right: 5px; top: 5px;">
      Loading...
     </span>
   </div>
   <div id='centerPanel' data-dojo-type='dijit.layout.ContentPane' data-dojo-props="region:'left'" style='width:200px;'>
    <div> 
     <h3>Legend</h3>
     <div id='legendDiv'></div>
    </div>
   </div>
   <!--right content panel-->
   <div id="rightPanel" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'right'">
     <p>This sample shows how to view a secure map service using token-based authentication.</p>
      <div id="content" >
       <p>To view current trail conditions sign in with user name: <b>rick</b> and password:<b>rick@esri</b></p>
        <p class="username">
          <label style="display:none;" for="username" id="nameLabel">Name</label>
          <input placeholder="Username" type="text" name="username" id="username" />
        </p>
        <p class="password">
          <label style="display:none;" id="passwordLabel" for="password">Password</label>
          <input placeholder="Password" type="password" name="password" id="password" />
        </p>
        <p class="submit">
          <input type="submit" id="signIn" onclick="signIn();" value="Sign In" autofocus/>
        </p>
     </div>
     <span id="signInStatus"></span>
   </div>
  </div>

</body>
</html>


Can you provide more details about your scenario?
0 Kudos
KiranShakya
New Contributor
Hai guys, now I am running into the same problem.  Legend does not shows when I use token.  I used fix token (not requesting with username and password) as https://<servername>/ArcGIS/rest/services/<service>/MapServer?token=<token created by myself is kept here>.

As soon as I add token, the legend disappears :confused:.  Then I tried to check legend with token https://<servername>/ArcGIS/rest/services/<service>/MapServer/legend?token= <token string> all layers name displayed with empty legend picture.

Now, I am confused.  Do I have to do some configuration in ArcGIS Server to display legends while using token service?
0 Kudos
BabbageOcelot
New Contributor
Ben,

...

Can you provide more details about your scenario?

Kelly,

thanks for getting back to me on this. To be honest we've been doing without a legend for the moment, various other projects took priority.

The scenario is, we need to authenticate to 2 separate systems. The simplest way to do it is to run both the token request, and the other system login server-side (ajax request with params), and return an arcgis token via the ajax response. The token will authenticate against ArcGIS Server and allow the user to see a secured map service.

Note this is a map service, and not a FeatureLayer. I've tested your example & the legend is working with a FeatureLayer, and not an ArcGISDynamicMapServiceLayer. I attach an amended example to illustrate:


    dojo.require("dijit.layout.BorderContainer");
    dojo.require("dijit.layout.ContentPane");
    dojo.require("esri.map");
    dojo.require("esri.layers.FeatureLayer");
 dojo.require("esri.dijit.Legend");
 
 
    dojo.addOnLoad(initialize);

    // Global variables
    var map,resizeTimer;


    function initialize() {

    //check to see if browser supports placeholder text - if not enable labels for username and
    //password form.
      if(!supportsPlaceholder()){
        esri.show(dojo.byId('passwordLabel'));
        esri.show(dojo.byId('nameLabel'));
      }


      esri.config.defaults.io.proxyUrl = "proxy/proxy.ashx";

      // Create map
      map = new esri.Map("mapCanvas",{
        extent: new esri.geometry.Extent({"xmin":-12080521,"ymin":4472736,"xmax":-11829657,"ymax":4563023,"spatialReference":{"wkid":3857}}),
        slider: false
      });

      dojo.connect(map, "onLoad", mapLoaded);
      // Add a cached map service
      var basemap = new esri.layers.ArcGISTiledMapServiceLayer("https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer");
      map.addLayer(basemap);

      //add the map service to the map - this layer doesn't require a token

      //var trailsService = new esri.layers.ArcGISDynamicMapServiceLayer("https://servicesbeta.esri.com/ArcGIS/rest/services/SanJuan/Trails/MapServer");
      //map.addLayer(trailsService);
    }

    function mapLoaded() {
      esri.hide(dojo.byId("status"));

      dojo.connect(dojo.byId("username"), "onkeypress", keyPressed);
      dojo.connect(dojo.byId("password"), "onkeypress", keyPressed);


      dojo.connect(dijit.byId('mapCanvas'), 'resize', function() {
          resizeMap();
      });

    }

    function signIn() {
      // Check if the user has entered username and password
      var usr = dojo.byId("username").value, pwd = dojo.byId("password").value;
      if (!usr || !pwd) {
        return;
      }

      dojo.byId("signInStatus").innerHTML = "Creating token...";

      // Get token from the ArcGIS Server Token Service.
      //
      esri.request({
        url: "https://servicesbeta.esri.com/ArcGIS/tokens",
        content: {
          request: "getToken",
          username: usr,
          password: pwd
        },
        handleAs: "text",
        load: tokenObtained,
        error: tokenRequestFailed
      });
    }

    function tokenObtained(response) {
      dojo.byId("signInStatus").innerHTML = "Token created. Accessing the service...";

      // Add the secure feature service to the map
      // Note that the token is appended to the URL
      // when constructing the layer.

     
  // Block 1: Comment from here...
  /**
  
  var featureLayerURL = "https://servicesbeta.esri.com/ArcGIS/rest/services/SanJuan/TrailConditions/MapServer/0?token=" + response;

     var infoTemplate = new esri.InfoTemplate("Current Conditions", "${Condition} incident updated on ${UpdateDate:DateFormat(selector: 'date', fullYear: true)}. ${Description}");

     var conditions = new esri.layers.FeatureLayer(featureLayerURL,{
      infoTemplate:infoTemplate,
      outFields:["*"]
     });
     conditions.setDefinitionExpression("Description != ''");
  
  
  **/
  // To here.
  
  // Block 2: Comment from here...
  
  
  var dmsLayerURL = "https://servicesbeta.esri.com/ArcGIS/rest/services/SanJuan/TrailConditions/MapServer?token=" + response;

     var conditions = new esri.layers.ArcGISDynamicMapServiceLayer(dmsLayerURL);
 
 
 // To here.

      dojo.connect(conditions, "onLoad", function() {
        setTimeout(function() {
          dojo.byId("signInStatus").innerHTML = "";
        }, 1500);
      });

      dojo.connect(conditions, "onError", function(error) {
        dojo.byId("signInStatus").innerHTML = "Error: " + error.message;
      });
   
   dojo.connect(map,'onLayersAddResult',addLegend);
   
      map.addLayers([conditions]);

      map.infoWindow.resize(200,120);

    }

 function addLegend(results){
  console.log(results);
  var layerInfo = dojo.map(results, function(layer,index){
            return {layer:layer.layer,title:(layer.layer.name||"nameless")};
  });
  console.log(layerInfo);
  if(layerInfo.length > 0){
   var legendDijit = new esri.dijit.Legend({
     map:map,
     layerInfos:layerInfo
   },"legendDiv");
   legendDijit.startup();
   setTimeout(function(){
    console.log('refresh');
    legendDijit.refresh(layerInfo);
   },5000);
  }
 }
 
    function tokenRequestFailed(error) {
      dojo.byId("signInStatus").innerHTML = "Unable to create token. Please check your username/password";
    }


    function keyPressed(e) {
      if (e.charOrCode === dojo.keys.ENTER) {
        signIn();
      }
    }

   //Handle resize of browser
      function resizeMap(){
        clearTimeout(resizeTimer);
        resizeTimer = setTimeout(function(){
          map.resize();
          map.reposition();
        }, 500);

     }

     function supportsPlaceholder() {
     // An alternative to this test would be to use a javascript library like
      //Modernizr that detects support for HTML5 and CSS3 functionality.
        var i = document.createElement('input');
        return 'placeholder' in i;
      }
   function disableSignInForm() {
      dojo.byId("username").value = "";
      dojo.byId("password").value = "";

      var node = dojo.byId("content"), box = dojo.contentBox(node);
      dojo.style(node, { top: 0, opacity: 1 });

      var hideAnimation = dojo.animateProperty({
        node: node,
        duration: 500,
        properties: { top: -1 * box.h, opacity: 0 }
      });

      hideAnimation.play();
    }



So if you comment/uncomment the noted blocks you'll see this change in behaviour. I've just quoted the code, because if I include the whole page the post becomes too long!

Also note that, if you choose to omit the layerInfo from the Legend create, the legend is created, excluding the secured one.

This is probably better directed at the JS API guys, isn't it? Feel free to move the post if you like.

Thanks, Ben.
0 Kudos