Select to view content in your preferred language

hard code token based on referrer

4764
6
03-18-2013 10:35 AM
danbecker
Frequent Contributor
we have a client that uses a secured sharepoint site.
They want to include a link to gis.ourJSapp.com from their secured sharepoint site.

So, anyone that comes to gis.ourJSapp.com from the sharepoint site has privs to access the app; they don't want to have to login again, which is the case right now.

Could anyone shed light on some server side code/concepts that would detect http referrer, then either hard-code token or not?

I've read through this thread and it's close...
http://forums.arcgis.com/threads/73298-Possible-to-hard-code-credentials

maybe a .php script before the current proxy.ashx?
0 Kudos
6 Replies
JohnGravois
Deactivated User
if the only people that can access the app have already authenticated, why not just store your token in the proxy which is used to access the secure services and call it a day?

you could use the app itself as the http referrer, since the app spawns the requests for secure services, or use the IP address of the web server which is hosting the proxy, because that is the physical machine which will always be making the requests.
0 Kudos
danbecker
Frequent Contributor
thanks for your response

I should have explained a bit better, the sharepoint site is outside of our control and in inside the GOV firewall.
In order for users to access the sharepoint site, they have to authenticate using a GOV system, again which is out of our control.

On this sharepoint site, a link will be created to our JS app on our internal server. If users have privs to access the sharepoint site, then they also possess privs to view our JS app and the secured GIS data it consumes.

Since we have no way of accessing the user's GOV credentials, I want to grab the referrer when they arrive at our JS app, then return a token accordingly. If the referrer doesn't match the sharepoint site, continue with JS app auth. like normal challenging for username/pw. This is impt, because our JS app is also accessed from outside the sharepoint site; in which case the users should be prompted for creds.

I ended up switching to the php proxy out of familiarity w/ php. In the proxy I parsed the QUERY_STRING into assoc. array, check for ref array key, test if ref value matches sharepoint site then set cURL parameters accordingly. If the checks pass, the cURL call uses a hard coded username/password listed in the proxy; else uses the POST credentials.


this is the only way I could fig. out how to send the referrer to the proxy onLoad. The callbacks are only concept at this point, haven't got that far yet.

think this will work?

function init(){
esri.config.defaults.io.proxyUrl = "proxy.php"; 
var ref = document.referer;
var request = esri.request({
    url:window.location.href,
    content:{
        ref:ref
    },
    handleAs:"json"
},{useProxy:true});

function suc(response){
    var idString = dojo.toJson({ "serverInfos": [serverInfo],
        "credentials": [{
         "userId": rahul,
         "server": "http://myserver:8399",
         "token": this.token,
         "expires": this.expires,
         "ssl": false,
         "creationTime": creationTime,
         "resources": securedServices
         }]
    });
    // store it client side
    if (_supports_local_storage()) {
            window.localStorage.setItem(this.token._jsAPIIDManagerData, idString);
        } else {
            dojo.cookie(this.token._jsAPIIDManagerData, idString, { expires: 1 });
        }
     loadcredentials();   
}
function err(response){
    console.log('response');
}

request.then(suc,err);
}
0 Kudos
JohnGravois
Deactivated User
it makes sense to me, but i have absolutely no experience doing anything remotely like that...:)
0 Kudos
danbecker
Frequent Contributor
all of the above auto assigning a token based on referrer is because we do not have control of the sharepoint site containing the link.

Another idea is to supply the client with a simple $.ajax call to obtain a token before leaving the sharepoint site, then include it in a query string to the JS app, which would then assign a credential using the ?token= from the qs. If the token's invalid, identityManager would challenge for username/pw.

users requesting the JS app not originating from the sharepoint site would obiv. not have a token in the qs.

this better then the referrer method?
0 Kudos
danbecker
Frequent Contributor
Hopefully this helps someone in the future...

ended up using the 1st method; checking the referrer. If any referrer exists and the user doesn't have a good existing cred in storage, an esri.request is made to pass referrer to the proxy for handling. If all checks pass, return a token, which then gets stored as cred.

here's the js
var cred = "esri_jsapi_id_manager_data";
function init() {
 loadCredentials(); //see if cred. already exists for this session

 esri.config.defaults.io.proxyUrl = "proxy.php";
 esri.config.defaults.io.alwaysUseProxy = false;

 var process = function(ref) {

  var def = new dojo.Deferred();

  if (ref != "" && esri.id.credentials.length == 0) {

   var refToken = esri.request({
    url : "https://gis.ourdomain/arcgis/", //any url that's proxied in proxy
    content : {
     ref : ref
    },
    handleAs : "json"
   });

   function success(res) {
    var idObject, idJson;
    if (res.token != 'noToken') {
     var serverInfo = {
      "server" : "https://gis.ourdomain.com",
      "tokenServiceUrl" : "https://gis.ourdomain.com/arcgis/tokens/",
      "currentVersion" : 10.11
     };

     var securedServices = [];
                                        //i guess this doesn't have to be a complete list
     securedServices.push("https://gis.ourdomain.com/arcgis/folder/MapServer/0");
     var creationTime = (new Date).getTime();
     var idString = dojo.toJson({
      "serverInfos" : [serverInfo],
      "credentials" : [{
       "userId" : 'auser', //user that was hard coded
       "server" : serverInfo.server,
       "token" : res.token,
       "expires" : res.expires,
       "ssl" : false,
       "creationTime" : creationTime,
       "resources" : securedServices
      }]
     });
     if (supports_local_storage()) {
      // use local storage
      window.localStorage.setItem(cred, idString);
      idJson = window.localStorage.getItem(cred);

     } else {
      // use a cookie
      dojo.cookie(cred, idString, {
       expires : 1
      });
      idJson = dojo.cookie(cred);
     }
     if (idJson && idJson != "null" && idJson.length > 4) {
                                                //load the credential
      idObject = dojo.fromJson(idJson);
      esri.id.initialize(idObject);
     }
     def.callback("loaded");
    } 
                                else {
     def.callback("not loaded"); //proxy didn't return token for 1 reason or other
    }
   }

   refToken.then(success);

  } 
                else {
   def.callback("not loaded"); //no referrer or already logged in
  }
  return def;
 }
 
 var ref = document.referrer;

 process(ref).then(function(response) {
  //continue adding layers, ect...
 })
}


heres the pertinent parts of the proxy.php
$targetUrl = $_SERVER['QUERY_STRING'];
$parts = preg_split("/\?/", $targetUrl);
$targetPath = $parts[0];
  
$qStringArr = array();
parse_str($parts[1],$qStringArr);

// open the curl session
$session = curl_init();
  
 
if(array_key_exists('ref', $qStringArr) && $qStringArr['ref'] != ''){
   //esri.request call with referrer
   if($qStringArr['ref'] == 'https://theReferrer.com/imLookingFor.html'){
    $data = array(
   'username' => 'auser',
   'password' => 'auserpassword',
   'client' => 'ip', //for dev only, switch to http referr on production
   'ip' => '123.123.22.41',
   'expiration' => '60',
   'f' => 'json'
  );
  $postData = http_build_query($data);
  $targetUrl = "https://gis.ourdomain/arcgis/tokens/generateToken";
 }
 else{//referrer didnt match, return junk response
  echo json_encode(array('token'=>'noToken'));
  exit;
 }
}
else{
        //continue w/ normal proxy call
   $postData = file_get_contents("php://input");  
}
//omitted cURL options array
$response = curl_exec($session);
echo $response;
0 Kudos
JohnGravois
Deactivated User
nice work! thanks for taking the time to outline the approach.
0 Kudos