Using secured asynchronous GP task fails with unauthorized access

2829
4
12-24-2010 10:55 AM
BryanBaker
Occasional Contributor
I'm using a geoprocessing task to access a secured GP service. It's an asynchronous service, so I'm calling submitJob on the task. However, in the application it returns an error with a 400-code "Unauthorized access" message. I can use the task successfully in the Services Directory.

I traced the calls with Fiddler and see that the submitJob is actually in two steps. First it calls /submitJob and includes the token=xxxx parameter. That returns a 302 redirect response with a URL for the client to call. That URL does not contain the token. The client uses that URL as-is and doesn't append the token to it. Sooo there's no surprise that the response is unauthorized access. In the Services Directory case, on the other hand, it's inserting the token into a cookie with each request, which the server accepts in lieu of a token in the query string.

I found a posting from last year along these lines: http://forums.esri.com/Thread.asp?c=158&f=2396&t=276750&mc=6#msgid855820. Apparently it only affects asynchronous GP tasks, due to this redirect behavior.

Any way to get around this? The 302 redirect may not even get to the code at all, instead being handled by the browser. If that's the case there's nothing that can be done at the client level (JS API or my application). The only possibility might be for the server itself  to append the token to the redirect URL.
0 Kudos
4 Replies
RichardWatson
Frequent Contributor
Write your own proxy that does whatever you need it to?
0 Kudos
BryanBaker
Occasional Contributor
In fact I've worked out a proxy process along these lines. It shouldn't be this hard, but it does work. The process I used was:

1) When creating the task, I set the URL to the proxy page, and passed the token and the URL of the real task as parameters, e.g.:

var gpTask = new esri.tasks.Geoprocessor("myCustomProxy.ashx?taskUrl=http://servername/arcgis/rest/services/myGpAsyncTask/GPServer&token=123456789etc");

The GP task stores the parameters and passes them when it submits the task job.

2) Created a custom proxy page (e.g., myCustomProxy.ashx), using the code from the proxy page available at the Resource Center as a base. But instead of pulling the token from a config file on the server, I grabbed the token from the request's query string. I stored that token for later use when handling the 302 redirect.

3) In the custom proxy page, I built the correct URL to send to the GP task. The JS API sends the request to the proxy page with a request URL like "myCustomProxy.ashx/SubmitJob?taskUrl=http://servername...&token=1234...&f=json&gpparam1=...". I created a name-value collection of the querystring parameters and pulled the taskUrl out, and appended the "/SubmitJob" to it. Then I added the other querystring parameters to my new URL and sent that using an HttpWebRequest, like in the standard proxy page. But I also set the HttpWebRequest.AllowAutoRedirect to false so it wouldn't automatically send a redirect response back to the server.

4) In the custom proxy page, when the response comes back from the GP server, I checked the StatusCode in the response (serverResponse cast as HttpWebResponse). If it's HttpStatusCode.Found (meaning 302/redirect), then I parsed the redirect URL from the response text. This is a pain because the response is a little HTML page, with the URL buried in an <a> link. I used an XDocument with Linq to grab that URL.

5) I then appended the token to the redirect URL (&token=1234...), and sent that URL back to the GP server. The server now likes that because it contains the token, which it doesn't if you just use a client-based GP task. The server responds with the URL as a string, so I could just use a WebClient.DownloadString when sending the URL.

6) I wrote the text from this second response into the response object for the proxy page. The client gets back the valid response with the jobId etc. and things proceed normally from there.

If anyone's interested I can probably post a sample.
0 Kudos
AntJ
by
New Contributor II
I am exactly trying the same but it doesn't work for my GP. Would you please share your sample ?
Thanks in advance
0 Kudos
BryanBaker
Occasional Contributor
I've attached a copy of the proxy page I'm using. Rename the extension to .ashx and put it in the directory of your website. As noted near the top of the file, this only works if you construct the GP task like this:

var myTask = new esri.tasks.Geoprocessor("asyncGPProxy.ashx?gpTaskUrl=http://myserver/arcgis/rest/services/myGpService/GPServer&token=1234567688")

In other words, use the proxy page as the location of the task, and include the real task URL as a parameter named gpTaskUrl. No guarantees this will work for you, but hopefully it'll help.
0 Kudos