OpenID Connect and POST bindings

One of the interesting differences between OpenID Connect and SAML is that the core OpenID Connect specification does not specify a binding that is similar to SAML POST where the IDP/OP uses HTTP POST to pass tokens to the SP/RP. There is an OAuth 2.0 extension (http://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html) that can be used to do that, by using response_mode=form_post but there’s no guarantee that your partner supports it since it is optional.

However OpenID Connect Core does use the standard OAuth 2.0 “fragment” binding for front-channel flows. That binding is primarily meant for in-browser clients because the data in the fragment is not supposed to leave the browser. Nevertheless that flow can be turned in to a POST binding for web server clients by using Javascript to extract the token from the fragment and POST it to the web server client. A Javascript example can be found in http://openid.net/specs/openid-connect-core-1_0.html#FragmentNotes. Serving this code on the redirect_uri will effectively implement a POST binding but the actual POST code/trigger is served by the RP instead of the OP as opposed to SAML POST where the IDP triggers the POST. Note also that that specific Javascript code is site-dependent.

As an improvement on that, I have developed some Javascript that is site-agnostic and does effectively the same as described above except it uses a plain old HTML form for POST-ing the data instead of a XMLHttpRequest. This very same code has the side effect that it will also make the server support the optional OAuth 2.0 form_post response mode. So by serving the Javascript code as pasted below on the redirect URI and developing the server side code to deal with the POST, you will effectively support both the form_post and fragment response modes for web server clients in one blow. How about that :-)! FWIW: I’m using this in mod_auth_openidc (https://github.com/pingidentity/mod_auth_openidc) quite successfully.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <script type="text/javascript">
      function postOnLoad() {
        encoded = location.hash.substring(1).split('&');
        for (i = 0; i < encoded.length; i++) {
          encoded[i].replace(/\+/g, " ");
          var n = encoded[i].indexOf("=");
          var input = document.createElement("input");
          input.type = "hidden";
          input.name = decodeURIComponent(encoded[i].substring(0, n));
          input.value = decodeURIComponent(encoded[i].substring(n+1));
          document.forms[0].appendChild(input);
        }
        document.forms[0].action = window.location.href.substr(0, window.location.href.indexOf('#'));
        document.forms[0].submit();
      }
    </script>
    <title>Submitting...</title>
  </head>
  <body onload="postOnLoad()">
    <p>Submitting...</p>
    <form method="post" action=""><p><input type="hidden" name="response_mode" value="fragment"></p></form>
  </body>
</html>
Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

11 Responses to OpenID Connect and POST bindings

  1. Nice post Hans! Have you by any chance done some research on the maximum length of the fragment in various browsers? What I’ve read so far appears to indicate that it is considered part of the URL total and shouldn’t exceed 2K.

  2. Tangui says:

    Hello Hans,

    Thanks for this great post! We’re trying to configure it with mod_auth_openidc. Our idea is to use the OIDC Hybrid “code id_token token” flow and fragment response mode to get the access token and refresh token (after exchanging the authz code) from javascript code (and store it in localstorage) and then post it (simulating response_mode=post) to mod_auth_openidc for authentication. We have a few questions:
    1) It is stated in mod_auth_openidc that the redirect_uri must on a protected path*. Then, how and where to serve javascript? Was thinking of:
    * redirect_uri on a public (non-protected) page that then POST the ID Token to the protected one
    * using option “OIDCUnAuthAction pass” to a specific protected directory
    2) It seems that by default mod_auth_openidc adds some tokens (access_token and id_token at least) in the URL fragment after check of ID token
    * Is this feature documented? Can it replace the aforementioned script?
    * How to prevent mod_auth_openidc from validating an authorization code, and instead adding it to the fragment like the other tokens (for consumption by javascript)?

    Regards,

    Tangui

    *
    # (Mandatory)
    # The redirect_uri for this OpenID Connect client; this is a vanity URL
    # that must ONLY point to a path on your server protected by this module
    # but it must NOT point to any actual content that needs to be served.
    # You can use a relative URL like /protected/redirect_uri if you want to
    # support multiple vhosts that belong to the same security domain in a dynamic way
    #OIDCRedirectURI https://www.example.com/protected/redirect_uri

    • I believe you’re conflating what the OpenID Connect Provider does with what mod_auth_openidc (which is a Relying Party) does.

      This is perhaps best discussed on the mailing list for mod_auth_openidc: https://groups.google.com/forum/#!forum/mod_auth_openidc
      I’d start with a description of what you’re trying to achieve.

      • Tangui says:

        Well I was trying to figure out how you managed to serve this javascript code on the RP side with mod_auth_openidc, since mod_auth_openidc redirect URIs must be protected and can’t authenticate when the ID token is in the fragment. Have I misunderstood this (i.e the javascript code isn’t hosted on the RP)?

  3. the Javascript code is hosted by the RP, mod_auth_openidc; the redirect URI is a special case handled by mod_auth_openidc

    • Tangui says:

      Thanks for your answer, but I’m still wondering how to serve that javascript on the RP side when it is protected by mod_auth_openidc (and ID token is in the fragment, therefore cannot be accessed by mod_auth_openidc)

      • as said: mod_auth_openidc treats this as a special case; the Javascript is on a fixed uri served by mod_auth_openidc

      • Tangui says:

        Just got it: it’s hardcoded in mod_auth_openidc code. Many thanks 🙂

        Since I want to keep the authorization code only on javascript side and POST only the ID token, do you see any way to do this just with configuration (meaning: without modifying the hardcoded javascript)?

        Indeed maybe I should post on the Google mailing list.

  4. gdrdabarera says:

    Hi Does authorization grant type supports form-post response mode?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s