Subject: Re: [ietf-http-auth] [whatwg] Solving the login/logout problem in HTML
From: "Thomas Broyer" <[email-masked]>
To: [email-masked], [email-masked], [email-masked]
Date: Thu, 11 Dec 2008 10:54:40 +0100
List-Id: <ietf-http-auth.osafoundation.org>

[ CC: ietf-http-wg, ietf-http-auth; please follow up to ietf-http-auth only ]
See http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2008-November/017569.html
The thread started at
http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2008-November/017413.html

On Wed, Nov 26, 2008 at 12:47 PM, Thomas Broyer wrote:
> On Tue, Nov 25, 2008 at 6:26 AM, Ian Hickson wrote:
>>
>> It seems to me that the first limitation of form authentication could be
>> removed by inventing a new WWW-Authenticate challenge that means "reply to
>> the form in the page". I have now specified such a value in HTML5 (since
>> it is specific to entity bodies that contain HTML forms):
>
> I came to the same conclusion [...]

On Thu, Nov 27, 2008 at 9:38 PM, Ian Hickson wrote:
>
> On Thu, 27 Nov 2008, Julian Reschke wrote:
>>
>> The specification of this scheme (which essentially is a no-op to
>> implement for browser vendors and which already works "almost
>> everywhere") could either happen in the W3C or in the IETF. I'm happy to
>> assist in case the latter alternative is chosen.
>
> I've removed the text from HTML5. If anyone wants to run with this and
> specify it in a separate document, please let me know.
[...]
> Thanks everyone for the feedback on this idea. I recommend that interested
> parties get together and come up with a simple RFC for a better solution.

For the record, my initial thoughts (a year or two ago) was about a
"Cookie" auth scheme:

   challenge        =  "Cookie" cookie-challenge

   cookie-challenge  = 1#( realm | [ form-action ] | cookie-name |
                       [ test-cookie-name ] | [auth-param] )

   form-action       = "form-action" "=" <"> URI <">
   URI               = absoluteURI | abs_path
   cookie-name       = "cookie-name" "=" token
   test-cookie-name  = "test-cookie-name" "=" token

Where "form-action" is the HTML/XForms/whatever form's action URL (so
that you know that a form in the document submitting data to this URL
is (potentially) a "login form"). "form-action" must resolve to an
HTTP/HTTPS URL where the "authority" contains no "userinfo", the
"host" has the same contraints as the "Domain" of a Set-Cookie, and
the "asb_path" has the same constraints as the "Path" of a Set-Cookie.
The "cookie-name" param gives the name of the cookie that will be set
after a submission to "form-action" to maintain the "authenticated
session"; an UA could then accept such a cookie even if configured to
reject cookies or ask the user, because it then knows it's kind of
"credentials" for subsequent requests.
The "test-cookie-name" param names a cookie set within the same HTTP
response that will be checked by "form-action" as a mean to detect if
the UA accepts cookies. An UA could then silently, temporarily accept
such a cookie, even if configured to reject cookies or ask the user,
and send it with the submission to "form-action".

The "path" of the cookie set in the response from "form-action"
defines the protection space.

I also had the idea of somehow relaxing how an UA have to manage those
cookies, and therefore set constraints for servers on how they set
their values. For example, the UA could be allowed to ignore changes
in value: once the cookie has been set, its value is fixed until
expiration; this is to prevent servers using this cookie to store
"session info", particularly in the case the user has configured the
UA to reject cookies altogether; the cookie value is considered an
"authentication token" that does not change over time for a given
"authenticated session" (life time of the cookie).
Also (eventually), when contacting "form-action", the UA shouldn't
(mustn't?) react to authentication challenges (apart from a Cookie
challenge identical to the one received in the previous request).

Example (simplified messages):

  1.  User Agent -> Server

      GET http://www.example.com/acme/ HTTP/1.1

  2.  Server -> User Agent

      HTTP/1.1 401 Unauthorized
      WWW-Authenticate: Cookie realm="Acme"
              form-action="https://secure.example.com/acme/login"
              cookie-name=ACME_TICKET
              test-cookie-name=TEST_ACME
      Set-Cookie: TEST_ACME="test"; Version="1"; Path="/acme";
              Secure; Domain=".example.com"
      Content-Type: text/html

      <title>Unauthorized</title>
      <form action="https://secure.example.com/acme/login" method=POST>
      <input type=hidden name=referer
              value="http://www.example.com/acme/">
      <p><label>Username: <input name=user></label>
      <p><label>Password: <input name=pwd type=password></label>
      <p><button type=submit>Sign in</button>
      <p><a href="/acme/register">Register for an account</a>
      </form>

  3. User Agent -> Server

      POST https://secure.example.com/acme/login HTTP/1.1
      Cookie: $Version="1"; TEST_ACME="test"; $Path="/acme";
              $Domain=".example.com"
      Content-Type: application/x-www-form-urlencoded

      referer=http%3A%2F%2Fwww.example.com%2Facme%2F
      &user= Aladdin&password=open%20sesame

  4.  Server -> User Agent

      HTTP/1.1 303 See Other
      Location: http://www.example.com/acme/
      Set-Cookie: TEST_ACME="test"; Version="1"; Path="/acme";
              Domain=".example.com"; Max-Age=0
      Set-Cookie: ACME_TICKET="sdf354s5c1s8e1s"; Version="1";
              Path="/acme"; Domain=".example.com"

  5.  User Agent -> Server

      GET http://www.example.com/acme/ HTTP/1.1
      Cookie: $Version="1"; ACME_TICKET="sdf354s5c1s8e1s";
              $Path="/acme"; $Domain=".example.com"

  6. Server -> User Agent

      HTTP/1.1 200 OK

-- 
Thomas Broyer