I am trying to autologin sending a JSONObject. Im gettign the reposnse as 302 Moved Temporarily which means I should redirect to another url. But my response.toString() shows "Location: /". Below is the code.
String input_text = "https://www.hautelook.com/v3/credential";
HttpPost httpost = new HttpPost(input_text);
String data = "{\"screen_resolution\":{\"height\":1080,\"width\":1920}}";
JSONObject jo=new JSONObject();
jo.put("email","sfhgfjk");
jo.put("passsword","dfjhsdkj");
jo.put("meta",data);
StringEntity se = new StringEntity( "JSON: " + json.toString());
se.setContentEncoding("UTF-8");
se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
httpost.setEntity(se);
HttpResponse response = httpclient.execute(httpost);
entity = response.getEntity();
What would be wrong?
This is the response.
response HTTP/1.1 302 Moved Temporarily [Server: nginx, Content-Type: text/html,
Location: /, Content-Encoding: gzip, Content-Length: 20, Expires: Thu, 16 Feb 2
012 19:07:55 GMT, Cache-Control: max-age=0, no-cache, no-store, Pragma: no-cache
, Date: Thu, 16 Feb 2012 19:07:55 GMT, Connection: keep-alive, Set-Cookie: PHPSE
SSID=vmoqeksits8ccukvnf7k4rdv75; path=/]
You can always verify if this is correct manually by issuing the request via CURL, or even your browser. For example, typing https://www.hautelook.com/v3/credential into a browser location bar causes a redirect to https://www.hautelook.com (with a nice little login dialog being shown by jQuery). So you know at least, that the behavior is consistent.
This can mean one of several things:
The endpoint you are using is incorrect (this is probably not the
case)
The authentication information you are supplying is incorrect (also
unlikely, because we would expect a 401 unauthorized in that case)
The way you are passing the authentication information is incorrect.
Without knowing more about the API its hard to say, but you should consult the docs again to ensure you are making the call correctly.
* EDIT*
Ok, tested with REST client and there are some things to correct in your code:
Change 'passsword' to 'password'
Change the line:
Original:
new StringEntity( "JSON: " + json.toString())
To:
new StringEntity(json.toString())
This should allow the request through, though I'm still not sure this is the correct endpoint, since I get back an HTML page. One last thing, its always good to remove your API credentials before posting your code to SO. I'm including a screenshot of the request below:
The default redirect strategy used by HttpClient 4.x honors restrictions on automatic redirection of entity enclosing methods such as POST and PUT imposed by the HTTP specification. Per requirements of the HTTP specification 302 Moved Temporarily, 301 Moved Permanently and 307 Temporary Redirect status codes may not be handled automatically for POST and PUT methods without an explicit confirmation by the user.
HttpClient 4.2 can be configured to use LaxRedirectStrategy that handles all types of redirects automatically regardless of the restrictions imposed by the specification. With earlier versions one can implement a custom redirect strategy as described here: Httpclient 4, error 302. How to redirect? (as suggested by Bob Kuhar).
At the same time I have to say that 'Location: /' header looks somewhat suspicious and even automatic redirect to that location may not necessarily produce the desired effect.
response HTTP/1.1 302 Moved Temporarily means, some redirection happened.
One of the example case is, Single sign on (or) Authorization required. Without authorization cookie when you try to access the resource using URL you may be redirected for Authorization with response as 302.
You could just configure your HTTPClient to follow redirects. Prior to 4.x, it was just a method on the HTTPMethod. Add...
HttpPost httpost = new HttpPost(input_text);
httpost.setFollowRedirect( true );
...but this wasn't pure enough or something and they changed it in 4.x. I haven't tried it since, so am reluctant to post code. But this question has come up and been answered here before. Maybe this helps you? Httpclient 4, error 302. How to redirect?
Related
I have a problem with Google HTTP Client Library for Java (1.22.0).
This is my code
String url = "http://gazetapraca.pl/ogl/2502758";
GenericUrl genericUrl = new GenericUrl(url);
ApacheHttpTransport apacheHttpTransport = new ApacheHttpTransport();
HttpRequest httpRequest = apacheHttpTransport.createRequestFactory().buildGetRequest(genericUrl);
httpRequest.setFollowRedirects(true);
HttpResponse httpResponse = httpRequest.execute();
and httpRequest.execute() throws
com.google.api.client.http.HttpResponseException: 301 Moved Permanently
Below is follow from Wireshark
GET /ogl/2502758 HTTP/1.1
Accept-Encoding: gzip
User-Agent: Google-HTTP-Java-Client/1.22.0 (gzip)
Host: gazetapraca.pl
Connection: Keep-Alive
HTTP/1.1 301 Moved Permanently
Date: Sat, 26 Nov 2016 22:15:52 GMT
Server: Apache
Location: /ogl/2502758/pakowacz+-+mile+widziane+panie
Content-Length: 0
Set-Cookie: JSESSIONID_JOBS=2f1TffY6JYcb6zvBSrQ72fds7rfdsSnHM3sefw6D31Lfr434bnkDmdLQJLvLFZ6zkYBF!-12116034235597; path=/; HttpOnly
Content-Language: pl
P3P: CP="NOI DSP COR NID PSAo OUR IND"
Vary: User-Agent
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
GET /ogl/2502758/pakowacz%20-%20mile%20widziane%20panie HTTP/1.1
Accept-Encoding: gzip
User-Agent: Google-HTTP-Java-Client/1.22.0 (gzip)
Host: gazetapraca.pl
Connection: Keep-Alive
Cookie: JSESSIONID_JOBS=2f1TffY6JYcb6zvBSrQ72fds7rfdsSnHM3sefw6D31Lfr434bnkDmdLQJLvLFZ6zkYBF!-12116034235597
HTTP/1.1 301 Moved Permanently
Date: Sat, 26 Nov 2016 22:15:52 GMT
Server: Apache
Location: /ogl/2502758/pakowacz+-+mile+widziane+panie
Content-Length: 0
Content-Language: pl
P3P: CP="NOI DSP COR NID PSAo OUR IND"
Vary: User-Agent
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
and repeat a few times.
Maybe the problem is with url, because location is /ogl/2502758/pakowacz+-+mile+widziane+panie and next request method get is /ogl/2502758/pakowacz%20-%20mile%20widziane%20panie.
In other software and library everything is working (google chrome browser, postman - addon to chrome, JSOUP - java library).
Does anyone have an idea how to solve the problem?
This is not your library's fault.
To understand why this problem is occurring, we must first understand the "error" message associated with your problem:
com.google.api.client.http.HttpResponseException: 301 Moved Permanently
So, what does this mean? Well, the last part of the error message, the description says "301 Moved Permanently". What that is referring to is an HTTP Status Code. An HTTP Status Code indicates what the outcome of a specific request is. In this case, the status code was 301, which according to RFC protocol means:
The requested resource has been assigned a new permanent URI and any future references to this resource SHOULD use one of the returned URIs.
So, this means that the URL that you are using is no longer valid, and that you have to use the new URL given to you by the Location response header. Now, it seems that the library that you're using is smart enough to detect this, and initializes a new request to the new URL. That's great and all, but your library that you are using, is incorrectly escaping the url provided by the Location header, and using that for the new request (turning /ogl/2502758/pakowacz+-+mile+widziane+panie into /ogl/2502758/pakowacz%20-%20mile%20widziane%20panie), and the server receiving this request recognizes that those to paths are not the same (even though they should be. So, the server sends another 301 response, telling the client (the library in this case) to use the un-escaped URL instead of the escaped one, even though they should be the same.
Now, why is your library doing this? It turns out that, according to RFC spec, the '+' character is reserved for URIs. That means that that character, along with other characters are only intended for use in URIs for their intended purpose. Therefore, it is not standard to include the '+' character in URIs, unless it is used for a very specific purpose, which it looks like is not the case.
So, this all means that you cannot blame the library for this error, you can only blame the people who developed this site.
The reason that this works in your browser and other places is because those clients do not seem to be escaping the requested URL for you before sending it to the server.
This is my first question. I love stackOverflow but I've always been a reader, not a writer. Now here goes nothing:
So I've seen a LOT of different questions like this, believe me, I looked... but none of them seemed to answer my question exactly. I'm designing a test harness to test an API, and it involves sending HTTP requests using HttpClient (in Java). For some of the requests, such as POST requests, a JSON string or an XML string must be sent with the request. (I'm only asking about JSON here, if anyone had the answer of how to do the XML as well, I'd love that, but I'll save it for another question.)
Anyways, I have the following code so far which seems like it SHOULD do what I want... but I'm getting 400 error. I'm going to assume that I've properly created an instance of an HttpClient and an HttpPost, applied appropriate headers, etc... the pertinent part is below:
JSONObject JSONpayload = new JSONObject();
JSONpayload.put("quantity", 1);
JSONpayload.put("sku", "21-53429");
String JSONstring = JSONpayload.toString();
System.out.println("JSON PAYLOAD BEING SENT: " + JSONstring);
request.setEntity(new StringEntity(JSONstring));
response = client.execute(request);
System.out.println("SERVER RESPONSE STRING: " + response.toString());
And I receive the following output:
JSON PAYLOAD BEING SENT: {"quantity":1,"sku":"21-53429"}
SERVER RESPONSE STRING: HTTP/1.1 401 Unauthorized
[Date: Thu, 27 Jun 2013 19:57:29 GMT,
Server: Mule Core/3.3.1,
Set-Cookie: sid=h8jumUyMxMztmB1AHtbvmUzzc9WchbiR9dQahD6Q; Version=1;
Domain=192.168.235.9;
Path=/,
http.status: 401,
X-MULE_SESSION: rO0ABXNyACNvcmcubXVsZS5zZXNzaW9uLkRlZmF1bHRNdWxlU2Vzc2lvbi7rdtEW7GGKAwAEWgAFdmFsaWRMAA1mbG93Q29uc3RydWN0dAAmTG9yZy9tdWxlL2FwaS9jb25zdHJ1Y3QvRmxvd0NvbnN0cnVjdDtMAAJpZHQAEkxqYXZhL2xhbmcvU3RyaW5nO0wAD3NlY3VyaXR5Q29udGV4dHQAJ0xvcmcvbXVsZS9hcGkvc2VjdXJpdHkvU2VjdXJpdHlDb250ZXh0O3hwAXB0ACRjYzQwMmMwNy1kZjYzLTExZTItOGY1Yi1kOTk2MTM2MzZkZjJwc3IAJWphdmEudXRpbC5Db2xsZWN0aW9ucyRTeW5jaHJvbml6ZWRNYXAbc/kJS0s5ewMAAkwAAW10AA9MamF2YS91dGlsL01hcDtMAAVtdXRleHQAEkxqYXZhL2xhbmcvT2JqZWN0O3hwc3IAJG9yZy5tdWxlLnV0aWwuQ2FzZUluc2Vuc2l0aXZlSGFzaE1hcJ3R2e9nRc4AAwAAeHB3DD9AAAAAAAAQAAAAB3QABWR1bW15dAAYOU9WX0FBQUJHQmdBQUFFX0lTQVFBNGMydAAJUm91dGVkVVJMdABhaHR0cDovLzE5Mi4xNjguMjM1Ljk6MzA4MC9nc2kvcmVzdC9XRlMvVE1TTkEtVE1TVVMtU2l0ZS9yZXN0L2NhcnRzLzlPVl9BQUFCR0JnQUFBRV9JU0FRQTRjMi9pdGVtc3QAC0NvbnRleHRQYXRodAATZ3NpLWV3cy1zZXJ2aWNlL3N2Y3QAC291dHB1dC10eXBldAAQYXBwbGljYXRpb24vanNvbnQAClJlcXVlc3RVUkx0AEsvZ3NpLWV3cy1zZXJ2aWNlL3N2Yy92MS4wL3N0b3Jlcy9UTVNVUy9jYXJ0cy85T1ZfQUFBQkdCZ0FBQUVfSVNBUUE0YzIvaXRlbXN0AAdTdG9yZUlEdAAMc3RvcmVzL1RNU1VTdAAKaW5wdXQtdHlwZXEAfgATeHEAfgAJeHg=,
X-MULE_ENCODING: UTF-8,
Content-Type: text/plain,
Transfer-Encoding: chunked]
Now, I know the basic things and I'm pretty sure I've taken care of them... like setting the headers Accept application/json, Content-Type application/json, etc..
Any advice would be greatly appreciated. I'm new to using HttpClient and I'm a little lost haha. Thanks guys!
The problem is that this server requires authentication and you're not providing it (or using invalid credentials). I can tell that because the response code was 401 (Unauthorized).
401: Similar to 403 Forbidden, but specifically for use when authentication
is required and has failed or has not yet been provided [...]
HTTPClient's home page has a lot of information regarding authentication. You can check how to do that here also check some code examples here.
I have a rule like:
RewriteCond %{HTTP_HOST}:%{QUERY_STRING} ^(\w+)\.t(.*)\.(\w+)?\.sprawk\.com:(.*)$
RewriteRule ^(.*) /api/translateHtmlPublic?tl=%1&su=%2&p=$1&q=%4 [B,PT,L]
which works great for GET requests.
However, for POST requests, the q parameter is null (which I expected) but inside my Java servlet, both the HttpServletRequest.getReader() and HttpServletRequest.getInputStream() give no data.
Using Firefox Live headers, I see that I am sending:
POST /uid/contactSend.cfm HTTP/1.1
Host: fr.t51940.local.sprawk.com
Connection: keep-alive
Referer: http://fr.t51940.local.sprawk.com/uid/contact.cfm?country=137
Cache-Control: max-age=0
Content-Type: application/x-www-form-urlencoded
Content-Length: 146
userName=Nic&queryCountry=Libya&queryCode=137&userEmail=n.cottrell%40idea.int&Comment=Just+testing&captcha=Quotas&Submit=--+Envoyer+Commentaire+--
I know that the servlet is receiving it as a POST since the doPost method is triggered. I understand that Apache 2.x should automatically preserve POST data during a simple rewrite, but maybe the addition of parameters is wiping the content data?
Update: I just realised (by dumping out all parameters) that the userName, queryCountry, queryCode parameters are getting correct values via the request.getParameter(String) method. The problem is that I need to be able to separate the original form parameter names from the ones I introduction in the RewriteRule.
The parameters of a POST are in the body, not the header. You can rewrite the URL as much as you like without affecting them.
The body of a POST request whose content type is application/x-www-form-urlencoded consists only of parameters that are retrieved via request.getParameter(). Reading the body via request.getInputStream() and request.getReader() will deliver nothing. (Servlet Specification 3, #3.1.1)
According to Servlet Specifcation #3, the parameters you add to the URL should be retrievable via getParameter().
There is no way to distinguish POST parameters in the body from URL parameters in the header. There is probably therefore something wrong with your solution, or your problem.
I'm trying to send a simple string as the contents of a HttpPost message.
The problem is, the body of the HttpPost message never makes it to the wire. (Says the Wireshark capture). The header looks just fine though (including the correctly calculated Content-Length.
Here's what the code looks like:
String url = "http://1.2.3.4/resource";
HttpClient client = new DefaultHttpClient();
String cmd = "AT+AVLPOS\r\n";
StringEntity se = new StringEntity(cmd);
se.setContentType("text/plain");
HttpPost request = new HttpPost(url);
request.setHeader("Content-Type","text/plain");
request.setEntity(se);
HttpResponse response = client.execute(request);
[...]
The string should be ASCII-encoded, but that's a detail at this point.
This is what shows up in WireShark:
-> note that lines marked with + are what's sent, and - is what's received.
+POST /resource HTTP/1.1
+Content-Type: text/plain
+Content-Length: 11
+Host: 1.2.3.4
+Connection: Keep-Alive
+User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
+Expect: 100-Continue
-HTTP/1.1 200 OK
-Content-Type: text/plain
-Transfer-Encoding: chunked
-4
-OK
This is what should show up (wrote a very simple console app in C# to do this, it just works):
+POST /resource HTTP/1.1
+Content-Type: text/plain
+Host: 1.2.3.4
+Content-Length: 11
+Expect: 100-continue
+Connection: Keep-Alive
+
-HTTP/1.1 200 OK
-Content-Type: text/plain
-Transfer-Encoding: chunked
-
+AT+AVLPOS
+
-4
-OK
-
-48
-$AVTMR,99999999,204810,A,1234.2218,N,0123.1051,E,0,20,150811,0,REQ*69
-
-0
-
Any suggestions?
I've figured it out, AND I've learned something today.
Long story short: disable the HttpClient's HTTP Post expect-continue handshake, by setting one of its parameters, this will send the whole request message in one chunk.
//set up HttpPost request as before
HttpClient client = new DefaultHttpClient();
client.getParams().setBooleanParameter("http.protocol.expect-continue", false);
HttpResponse response = client.execute(request);
[...]
Now here's how I got there, maybe this will help someone someday.
First I derived from a HttpEntityWrapper and used that as my request entity to see what gets called when, and found out that the Entity's writeTo(OutputStream) method was never called at all.
Then I started to look at why, in the case of the "correct" behaviour, the POST request wasn't sent all at once, and instead, the request headers were sent, then the response header is received, THEN the request body is sent.
IT's all got to do with the HTTP Post expect-continue handshake. Read more about it on Haacked.
If the expect-continue header is sent in a request, the Http server SHOULD reply with a 100 Continue message signifying "OK, I will accept your message", or with an error, stopping the possibly long POST message in its tracks.
Unfortunately, the web server I run against is a bare bones implementation that runs on a chip, and it sends the wrong reply (200 OK instead of 100 Continue).
The default implementation of the .NET Http Client seems to be more forgiving here: it treats the 200 message as 100 Continue, shrugs, and gets on its way to send the request body.
Not so with the Http client implementation of Android (API level 7).
Next thing I tried was to disable the expect-continue handshake completely, in order to make the HttpClient send the whole request. To my surprise and joy, this was handled fine by the web server, which replied with the information I wanted. Yay!
I've searched and searched but can't seem to find the answer to what seems like a straightforward authentication scenario.
We have an existing Java web application that uses form-based authorization provided by Spring. We are attempting to access this application via our portal site without challenging the user to enter their credentials (SSO).
The portal has a credential vault and we can successfully access the secrets for the remote web application on the server side. We are using Apache's HTTP Components utility to post the login request to the j_spring_security_check and are successfully authenticating. The response to this post sends back a 302 redirect to the application home page and sets a cookie with a session id.
Now we have to somehow send this authenticated session back to the browser and this is where we are having trouble. Simply redirecting the browser to the home page doesn't work - it redirects us to the login page. Forwarding all of the response headers back to the browser exactly as received on the server-side doesn't work either - still returned to the login page.
So, how do we authenticate server-side and still be able to load the target page client-side?
I am relatively new to this so I apologize if this is a silly question. Any help or advice regarding an alternative approach is appreciated.
Notes:
HttpComponent Client code:
DefaultHttpClient httpclient = new DefaultHttpClient();
try {
// try to get the home page
HttpGet httpget = new HttpGet("http://<host>/<root>/home.action");
HttpResponse httpClientResponse = httpclient.execute(httpget);
HttpEntity entity = httpClientResponse.getEntity();
// check status and close entity stream
System.out.println("Login form get: " + httpClientResponse.getStatusLine());
EntityUtils.consume(entity);
// check cookies
System.out.println("Initial set of cookies:");
List<Cookie> cookies = httpclient.getCookieStore().getCookies();
printCookies(cookies);
/*** Login ***/
HttpPost httppost = new HttpPost("http://<host>/<root>/j_spring_security_check");
// Prepare post parameters
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("j_username", getUserFromVault()));
nvps.add(new BasicNameValuePair("j_password", getPasswordFromVault()));
httppost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
httpClientResponse = httpclient.execute(httppost);
// copy response headers and determine redirect location
Header[] allHeaders = httpClientResponse.getAllHeaders();
System.out.println("Headers: ");
String location = "";
for (Header header : allHeaders) {
System.out.println(header);
if("location".equalsIgnoreCase(header.getName())) location = header.getValue();
response.addHeader(header.getName(), header.getValue());
}
// check response body
entity = httpClientResponse.getEntity();
System.out.println("Response content: " + httpClientResponse.getStatusLine());
System.out.println(EntityUtils.toString(entity)); // always empty
EntityUtils.consume(entity);
// check cookies
System.out.println("Post logon cookies:");
cookies = httpclient.getCookieStore().getCookies();
printCookies(cookies);
// populate redirect information in response
System.out.println("Redirecting to: " + locationHeaderValue);
response.setStatus(httpClientResponse.getStatusLine().getStatusCode()); // 302
// test if server-side get works for home page at this point (it does)
httpget = new HttpGet(location);
httpClientResponse = httpclient.execute(httpget);
entity = httpClientResponse.getEntity();
// print response body (all home content is loaded)
System.out.println("home get: " + httpClientResponse.getStatusLine());
System.out.println("Response content: " + httpClientResponse.getStatusLine());
System.out.println(EntityUtils.toString(entity));
EntityUtils.consume(entity);
} finally {
httpclient.getConnectionManager().shutdown();
}
Headers returned from the successful login on the server side:
HTTP/1.1 302 Found
Date: Wed, 23 Feb 2011 22:09:03 GMT
Server: Apache/2.2.3 (CentOS)
Set-Cookie: JSESSIONID=6F98B0B9A65BA6AFA0472714A4C816E5; Path=<root>
Location: http://<host>/<root>/home.action
Content-Type: text/plain; charset=UTF-8
Content-Length: 0
Via: 1.1 PPWebFilter.<host>:80 (IronPort-WSA/7.0.0-825)
Connection: keep-alive
Headers from the client side request and response:
Request:
GET /<root>/home.action HTTP/1.1
Host: <host>
Connection: keep-alive
Referer: http://localhost:10039/SCMViewer/TestLoginServlet?launchScm=Launch+SCM+servlet
Accept:application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.98 Safari/534.13
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: JSESSIONID=FC8E823AB1A1545BE8518DB4D097E665
Response (redirect to login):
HTTP/1.1 302 Found
Date: Wed, 23 Feb 2011 22:09:03 GMT
Server: Apache/2.2.3 (CentOS)
Location: http://<host>/<root>/security/login.action
Content-Type: text/plain; charset=UTF-8
Content-Length: 0
Via: 1.1 PPWebFilter.<host>:80 (IronPort-WSA/7.0.0-825)
Connection: keep-alive
As a test, we wrote a bit of a hack that seems to work, but is too insecure to be viable:
Embedded a form on the jsp which will post the login credentials directly to the remote site's j_spring_security_check.
Wrote a servlet method to retrieve the credentials from the vault.
Filled the credentials on the client side into hidden form fields and submitted the form via javascript.
It is a bit hard to understand what your application is trying to do, but my best guess is that your 'portal' sits between the user's browser and the application, and you are trying to use the some stored credentials for the application to authenticate on behalf of the users.
There are two things you need to watch for / deal with.
The responses from the application will contain SetCookie headers of some sort. The cookies need to be handled carefully. Depending on the security model you are using:
They could be saved in the portal and used for future requests to the application.
They could be relayed to the user's browser. The portal would also need to pass the cookies through in future requests to the application. (This approach needs to be handled carefully to deal with possible issues with session token leakage.)
Also, be aware that SpringSecurity changes the session cookie when login succeeds. If you don't capture the new session cookie and use them in follow on requests to the application, those requests won't be authenticated.
The application's login mechanism is clearly trying to redirect you (the portal) to the "default" place after logging in, and this is inappropriate. There are two simple fixes for this:
Have the portal detect the final redirect and treat it as an indication that you've successfully logged in. Then have the portal repeat the request for the page you were originally requesting from the application using the new cookie (see above).
IIRC, there's an extra parameter you can add to a j_spring_security_check request that tells the application where to return on successful login. I can't recall the details ...
I thought that forwarding the setCookie response header from the RA into the portal's response to the browser would be all that is needed to transfer the cookie/session id to the user's new browser window. Is that not correct?
That will cause the browser to set the RA's cookie for the portal context. That won't work unless the RA and portal are in the cookie's "scope" (for the want of a better word).
Question is, how do I display this on/through the portal? Do I just have to copy all the content over and map all the relative links accordingly? And, as you state, continue to proxy all requests to the app through the portal, passing the cookie each time? Is there any way to avoid copying/modifying the markup?
You do need to massage the markup. But exactly what massaging is required is not entirely clear. I think you'll need to map the relative links so that when the user's browser sees them they point to the portal. Then, arrange that the portal relays requests to the RA with the appropriate cookies.
One tool that you can use to deal with relative links is the HTML <base> element. In fact, this potentially easier to deal with than absolute links ... if you map everything via the portal.
But beware that there are all sorts of things that can cause grief in this process. For example, you've got to beware of the "same source" restriction, and with javascript with embedded URLs for the RA.
In case anyone is interested, here's how everything turned out.
Once we realized the issue with setting foreign cookies, we decided we had a few options:
Proxy - Tunnel through the portal to the
remote application, using the portal
as a proxy. This option is the most
straightforward logically, but it
has complications as mentioned above
(i.e. you have to modify each
request and each response - adding
cookies and markup as necessary).
This method turned out to be a pain
point for us, not unrelated to our
use of IBM WebSphere Portal 7.
3rd party SSO solution - Use CAS or Tivoli or some other enterprise solution. This is our
ideal final solution, but it is
still being researched to determine
compatibility with our environment.
Cookie Monster - Our interim solution, in order to
get IBM portal out of the way as the
middle man, was to deploy a small
new remote application on the same
server as our target app that simply
accepts a cookie in JSON format and
spits it back to the browser in a
302 redirect response.
The cookie monster solution works as follows: when the
user clicks on the link in the
portal, our portlet will internally
lookup the user's credentials,
authenticate to the remote
application, and return the
authentication cookie/token. We
convert that (as well as the
destination URL) to JSON and return
it to the browser. The browser then
posts this JSON to the remote cookie
application in a new window. The
cookie is reconstituted and placed
in the response along with the 302
and the target location. Voila, the
page redirects to the application
homepage and the user is logged in. Yay!
Some notes for anyone using IBM WebSphere Portal:
We handled the authentication via
resource-serving portlet.
Make sure the response from the resource-serving portlet is not cached (we made the cache expire immediately as we could not return no-cache)
Make sure you ping the portal before making the ajax call as the session may be expired.
I'm sure there are other, more elegant solutions, but this is working for us until we get CAS/Tivoli up and running.