Select to view content in your preferred language

dynamic token in protected service with request to token service (post method)

1725
6
08-12-2010 03:57 AM
GiosiaPoma
Regular Contributor
In ESRI documentation, when we talk about token and security, their suggest to use SSL protocol for make a request to token service present in arcgis server. In the GET method the request is encrypted and the comunication between client and server is safe. The problem is when we transtimt sensitive data in the request like have to do for obtain a token. We don't want to have sensitive data (f.e. password) sitting around somewhere in cleartext. Here's a few places where request string is exposed as cleartext:
[INDENT]

  • Server side logs

  • History caches in browsers

  • Bookmarks

  • Bugs in the application/browser (f.e. HTTP referrer leakage)

[/INDENT]
The best you can do today is to POST sensitive data to a server over HTTPS.

To do this with Flex, or other languages that want to use the getToken service, I show you an idea for make this with the POST method.

I hope this help someone, the code is also attacched.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                xmlns:esri="http://www.esri.com/2008/ags"
                pageTitle="Example - ArcGIS API for Flex connecting to a protected dynamic AGS service"
                initialize="init()">

    <mx:Script>
        <![CDATA[
            import com.esri.ags.layers.ArcGISDynamicMapServiceLayer;

            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import mx.rpc.http.HTTPService;
            import mx.utils.StringUtil;

            private function init():void {
                var baseMap:ArcGISDynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(/*myBaseMapUrl*/);
                map.addLayer(baseMap);
                // user and password data can come from to a flex form
                // for my test I force it to a known user and password present in my security store (in my case ActiveDirectory)
                RequestToken('user','password');
            }

            public function RequestToken(username:String, password:String):void {
                var http:HTTPService = new HTTPService();

                http.addEventListener( ResultEvent.RESULT, tokenResultHandler );
                http.addEventListener( FaultEvent.FAULT, faultHandler );

                // constants
                var rootURL:String = Application.application.url.substr(0,Application.application.url.indexOf("/",8));
                var expir:int = 1440;

                // parameters for the request
                var param:Object = {
                    "request" : "gettoken",
                    "username": username,
                    "password": password,
                    "clientid" : "ref."+ rootURL,
                    "expiration" : expir
                };

                // prepare the httpService object for send the request
                http.url = "https://myAGSTokenService/arcgis/tokens?tokens"; // fake parameter ?tokens for start the process of token generation
                http.method = "POST";  // set POST method for not have problem in cache and logs
                http.resultFormat = "text";
                http.request = param; // set parameters for the request
                http.send();

                function faultHandler(event:FaultEvent):void  {
                    Alert.show(event.fault.toString());
                }
                function tokenResultHandler(event:ResultEvent):void {
                    var theToken:String = StringUtil.trim(event.result.toString()); // trim the generated token for surprise...
                    loadProtectedMaps(theToken);
                }
            }

            private function loadProtectedMaps(token:String):void {
                var protectedMap1:ArcGISDynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(/*urlToYourServiceRest1*/);
                protectedMap1.token = token;
                map.addLayer(protectedMap1);

                var protectedMap2:ArcGISDynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(/*urlToYourServiceRest2*/);
                protectedMap2.token = token;
                map.addLayer(protectedMap2);
            }

        ]]>
    </mx:Script>

    <mx:Label text="This is an example with a base map and two protected service with token service. The token is dinamically requested to the token service in post method and SSL connection for security issue. Have a nice day" fontSize="14"/>
    <esri:Map id="map" />
</mx:Application>
Tags (2)
0 Kudos
6 Replies
sheebaashraf
Deactivated User
Thanks for the post but what needs to be done on server side

Please send me the code
0 Kudos
GiosiaPoma
Regular Contributor
On ArcGIS Server you must enable security and set users and groups. After that you can assign user at services for protect it.
0 Kudos
sheebaashraf
Deactivated User
Do I need to run Arcgis under HTTPS.
If yes please give some reference how i can do it
0 Kudos
GiosiaPoma
Regular Contributor
If you have a .net ags it's all in the manual. If you have an ags java you must see apache documentation to activate ssl
0 Kudos
TracySchloss
Honored Contributor
I'm getting a little lost with the parameters sent with the gettoken request. 

What exactly is clientID?  The application that is calling the service?  Several examples I've seen have had the url and the clientID the same.  If my services and my application are on the same machine, is that when I would set both of these the same?

When I generate tokens through the services directory, it only worked for me when I chose the IP as the Identifier (as opposed to the Web Application URL or HTTP Referrer).  I could then paste that token hard coded into FLEX and it draws the layer I want. 

I can generate a token using:
http://www.myGISserver.gov/arcgis/tokens?request=gettoken&username=schlot&password=password&expirati...

and I can do something similar programmatically through an HTTP Service call.

However, only the token created ArcGIS Token Services page that comes with AGS Service Manager works. There is a token created with the the "request=gettoken" URL, which doesn't work.  I have a similar problem requesting the token programmtically.  I get one returned, but it doesn't work then either.


Here's the dumb question:  where do you specify which service you want the token on?   Should I be more specific in the URL path?

It seems like I ought to be able to use either type of Identifier and have it work, and I'm confused why one works and other doesn't.
0 Kudos
CarmenDurham
Frequent Contributor
Thank you for this post.  This was what I needed to get our public facing web app to use secure and non-secure services by dynamically getting a token for the secure services. 
Here is the site, if interested:
https://gis.greenvillesc.gov/wheresmyhouse/

The map services containing the FEMA Flood, City Flood Studies, and Fire Hydrants are secure map services (2 separate services).  Works for the query tasks and display.  Try 500 E Park Av  for testing the flood.

Thanks again,
Carmen





In ESRI documentation, when we talk about token and security, their suggest to use SSL protocol for make a request to token service present in arcgis server. In the GET method the request is encrypted and the comunication between client and server is safe. The problem is when we transtimt sensitive data in the request like have to do for obtain a token. We don't want to have sensitive data (f.e. password) sitting around somewhere in cleartext. Here's a few places where request string is exposed as cleartext:
[INDENT]

  • Server side logs

  • History caches in browsers

  • Bookmarks

  • Bugs in the application/browser (f.e. HTTP referrer leakage)

[/INDENT]
The best you can do today is to POST sensitive data to a server over HTTPS.

To do this with Flex, or other languages that want to use the getToken service, I show you an idea for make this with the POST method.

I hope this help someone, the code is also attacched.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                xmlns:esri="http://www.esri.com/2008/ags"
                pageTitle="Example - ArcGIS API for Flex connecting to a protected dynamic AGS service"
                initialize="init()">

    <mx:Script>
        <![CDATA[
            import com.esri.ags.layers.ArcGISDynamicMapServiceLayer;

            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import mx.rpc.http.HTTPService;
            import mx.utils.StringUtil;

            private function init():void {
                var baseMap:ArcGISDynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(/*myBaseMapUrl*/);
                map.addLayer(baseMap);
                // user and password data can come from to a flex form
                // for my test I force it to a known user and password present in my security store (in my case ActiveDirectory)
                RequestToken('user','password');
            }

            public function RequestToken(username:String, password:String):void {
                var http:HTTPService = new HTTPService();

                http.addEventListener( ResultEvent.RESULT, tokenResultHandler );
                http.addEventListener( FaultEvent.FAULT, faultHandler );

                // constants
                var rootURL:String = Application.application.url.substr(0,Application.application.url.indexOf("/",8));
                var expir:int = 1440;

                // parameters for the request
                var param:Object = {
                    "request" : "gettoken",
                    "username": username,
                    "password": password,
                    "clientid" : "ref."+ rootURL,
                    "expiration" : expir
                };

                // prepare the httpService object for send the request
                http.url = "https://myAGSTokenService/arcgis/tokens?tokens"; // fake parameter ?tokens for start the process of token generation
                http.method = "POST";  // set POST method for not have problem in cache and logs
                http.resultFormat = "text";
                http.request = param; // set parameters for the request
                http.send();

                function faultHandler(event:FaultEvent):void  {
                    Alert.show(event.fault.toString());
                }
                function tokenResultHandler(event:ResultEvent):void {
                    var theToken:String = StringUtil.trim(event.result.toString()); // trim the generated token for surprise...
                    loadProtectedMaps(theToken);
                }
            }

            private function loadProtectedMaps(token:String):void {
                var protectedMap1:ArcGISDynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(/*urlToYourServiceRest1*/);
                protectedMap1.token = token;
                map.addLayer(protectedMap1);

                var protectedMap2:ArcGISDynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer(/*urlToYourServiceRest2*/);
                protectedMap2.token = token;
                map.addLayer(protectedMap2);
            }

        ]]>
    </mx:Script>

    <mx:Label text="This is an example with a base map and two protected service with token service. The token is dinamically requested to the token service in post method and SSL connection for security issue. Have a nice day" fontSize="14"/>
    <esri:Map id="map" />
</mx:Application>
0 Kudos