views:

694

answers:

4

Why would you do an automatic HTML post rather than a simple redirect?

Is this so developers can automatically generate a login form that posts directory to the remote server when the OpenID is known?

eg.

  1. User is not logged in and visits your login page.
  2. You detect the user's openID from a cookie.
  3. Form is generated that directly posts to remote OpenID server.
  4. Remote server redirects user back to website.
  5. Website logs in the user.

If this is the case I can see the benefit. However this assumes that you keep the user's openID in a cookie when they log out.

I can find very little information on how this spec should be best implemented.

See HTML FORM Redirection in the official specs:

http://openid.net/specs/openid-authentication-2_0.html#indirect_comm

I found this out from looking at the PHP OpenID Library (version 2.1.1).

// Redirect the user to the OpenID server for authentication.
// Store the token for this authentication so we can verify the
// response.

// For OpenID 1, send a redirect.  For OpenID 2, use a Javascript
// form to send a POST request to the server.
if ($auth_request->shouldSendRedirect()) {
    $redirect_url = $auth_request->redirectURL(getTrustRoot(),
                                               getReturnTo());

    // If the redirect URL can't be built, display an error
    // message.
    if (Auth_OpenID::isFailure($redirect_url)) {
        displayError("Could not redirect to server: " . $redirect_url->message);
    } else {
        // Send redirect.
        header("Location: ".$redirect_url);
    }
} else {
    // Generate form markup and render it.
    $form_id = 'openid_message';
    $form_html = $auth_request->htmlMarkup(getTrustRoot(), getReturnTo(),
                                           false, array('id' => $form_id));

    // Display an error if the form markup couldn't be generated;
    // otherwise, render the HTML.
    if (Auth_OpenID::isFailure($form_html)) {
        displayError("Could not redirect to server: " . $form_html->message);
    } else {
        print $form_html;
    }
}
A: 

My guess is that it is in order to reduce the number of bits flying around the internet.

Redirecting tells the client to go to the new place resulting in another round trip. Doing a POST cuts to the chase and goes directly to the new page.

Craig
The POST technique used in the example above has the same flow in terms of what data goes where as a regular redirect. POST-redirect will actually add a few *more* bytes, as the data is wrapped up in html form tags.
keturn
+4  A: 

I can think of a couple of reasons:

  • A modicum of security by obscurity - it's slightly more work to tamper with POST submissions than GET
  • Caching and resubmit rules are more restrictive for POST than GET. I'm not entirely sure this would matter for the OpenID use case, though.
  • Bots wouldn't follow the POST form, but would follow the redirect. This could impact server load.
  • Different browsers have different max lengths for GET requests - but none of them are as large as POST.
  • Some browsers will warn on redirect to another domain. They'll also warn if you're submitting POST to a non-HTTPS url.
  • By turning JavaScript off, I can have a relatively secure experience, and not be silently redirected to another domain.

I don't know that any of these are a slam-dunk reason to choose POST - unless the amount of data being sent exceeds the querystring length for some major browser.

Mark Brackett
+4  A: 

The primary motivation was, as Mark Brackett says, the limits on payload size imposed by using redirects and GET. Some implementations are smart enough to only use POST when the message goes over a certain size, as there are certainly disadvantages to the POST technique. (Chief among them being the fact that your Back button doesn't work.) Other implementations, like the example code you cited, go for simplicity and consistency and leave out that conditonal.

keturn
+1  A: 

The same approach is used for the SAML Web Browser SSO profile. The primary motivations of using HTML Post redirection are :

  • Virtually unlimited length of the payload : in SAML the payload is a XML document signed with XMLDSig and base64 encoded. It is larger than the usual 1024 characters limitation of URL (a best practice to support not only any browsers but intermediary network devices like Firewall, Reverse Proxy, Load Balancer as well).

  • W3C HTTP standard says that GET is idempotent (the same URL GET executed multiple times should always result in same response) and consequently can be cached along the way while POST is not and must reach the URL target. Response of an OpenID HTML Form POST or SAML HTML Form POST should not be cached. It must reach the target in order to initiate the authenticated session.

You could argue that using a HTTP GET redirection would work as well since the URL query always change and you would be right is practice. However, this would be a workaround of the W3C standard, and therefore, should not be a standard but an alternate implementation whenever both end agree with it.

Laurent Fournié