Re: [OAUTH-WG] WRAP session fixation?

Brent Goldman <brent@facebook.com> Wed, 25 November 2009 14:57 UTC

Return-Path: <brent@facebook.com>
X-Original-To: oauth@core3.amsl.com
Delivered-To: oauth@core3.amsl.com
Received: from localhost (localhost [127.0.0.1]) by core3.amsl.com (Postfix) with ESMTP id 937983A68B4 for <oauth@core3.amsl.com>; Wed, 25 Nov 2009 06:57:37 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -6.21
X-Spam-Level:
X-Spam-Status: No, score=-6.21 tagged_above=-999 required=5 tests=[AWL=0.054, BAYES_00=-2.599, HTML_MESSAGE=0.001, IP_NOT_FRIENDLY=0.334, RCVD_IN_DNSWL_MED=-4]
Received: from mail.ietf.org ([64.170.98.32]) by localhost (core3.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id llGhhCszJwNi for <oauth@core3.amsl.com>; Wed, 25 Nov 2009 06:57:36 -0800 (PST)
Received: from mailout-sf2p.facebook.com (mailout-snc1.facebook.com [69.63.179.25]) by core3.amsl.com (Postfix) with ESMTP id 3CE153A63C9 for <oauth@ietf.org>; Wed, 25 Nov 2009 06:57:36 -0800 (PST)
Received: from mail.thefacebook.com (intlb01.snat.snc1.facebook.com [10.128.203.15] (may be forged)) by pp02.snc1.tfbnw.net (8.14.1/8.14.1) with ESMTP id nAPEv3jj017534 (version=TLSv1/SSLv3 cipher=RC4-MD5 bits=128 verify=NOT); Wed, 25 Nov 2009 06:57:03 -0800
Received: from SC-MBXC1.TheFacebook.com ([192.168.18.102]) by sc-hub01.TheFacebook.com ([192.168.18.104]) with mapi; Wed, 25 Nov 2009 06:57:19 -0800
From: Brent Goldman <brent@facebook.com>
To: Brian Eaton <beaton@google.com>
Date: Wed, 25 Nov 2009 06:57:17 -0800
Thread-Topic: WRAP session fixation?
Thread-Index: Acpt35XNH7BhjOe4Q6asZ1tapscVag==
Message-ID: <ED81D84D-0FB2-4976-8807-8724954C826A@facebook.com>
References: <daf5b9570911241758p35206df7xf7bf7f245087f726@mail.gmail.com> <C731D315.18C2C%lshepard@facebook.com> <daf5b9570911241817p3572e747gbc5e359b0bcd9df1@mail.gmail.com>
In-Reply-To: <daf5b9570911241817p3572e747gbc5e359b0bcd9df1@mail.gmail.com>
Accept-Language: en-US
Content-Language: en-US
X-MS-Has-Attach:
X-MS-TNEF-Correlator:
acceptlanguage: en-US
Content-Type: multipart/alternative; boundary="_000_ED81D84D0FB2497688078724954C826Afacebookcom_"
MIME-Version: 1.0
X-Proofpoint-Virus-Version: vendor=fsecure engine=1.12.8161:2.4.5, 1.2.40, 4.0.166 definitions=2009-11-25_10:2009-11-16, 2009-11-25, 2009-11-25 signatures=0
X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 ipscore=0 phishscore=0 bulkscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx engine=5.0.0-0908210000 definitions=main-0911250119
X-Mailman-Approved-At: Wed, 25 Nov 2009 07:43:43 -0800
Cc: Naitik Shah <naitik@facebook.com>, "oauth@ietf.org" <oauth@ietf.org>, Luke Shepard <lshepard@facebook.com>
Subject: Re: [OAUTH-WG] WRAP session fixation?
X-BeenThere: oauth@ietf.org
X-Mailman-Version: 2.1.9
Precedence: list
List-Id: OAUTH WG <oauth.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/listinfo/oauth>, <mailto:oauth-request@ietf.org?subject=unsubscribe>
List-Archive: <http://www.ietf.org/mail-archive/web/oauth>
List-Post: <mailto:oauth@ietf.org>
List-Help: <mailto:oauth-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/oauth>, <mailto:oauth-request@ietf.org?subject=subscribe>
X-List-Received-Date: Wed, 25 Nov 2009 14:57:37 -0000

Facebook Platform/Connect has some pretty interesting logic involving registered callback URLs in our proprietary auth flows. Much of this is because we hate showing error messages. Maybe OAuth could borrow some of these ideas? Here's some more info.

I'm using the terminology "specified callback URL" to refer to the callback URL specified in the request, and "registered callback URL" to refer to the callback URL configured with us in advance. There are two types of callback URLs that can be specified in a request: absolute and relative.

Case 1. Specified callback URL is absolute.
If the specified callback URL is "safe", we redirect to it. Otherwise, instead of throwing an error, we redirect to the registered callback URL, with the specified callback URL in a GET param called "next". It's up to the developer of the registered callback URL to use the "next" param, or they can just ignore it.

To determine if the specified callback URL is safe: if the registered callback URL is a directory, then the specified callback URL has to be within that subdirectory. Otherwise, the specified callback URL has to point to the same file as the registered callback URL, and any query params on the registered callback URL have to also be present in the specified callback URL

For example, if the registered callback URL is http://www.foobar.com/callback/, and the specified callback URL is http://www.foobar.com/callback/method2, we know the specified callback URL is safe and thus redirect directly there. But if the specified callback URL is http://www.facebook.com/logged-into-foobar, which is unsafe, we redirect to http://www.foobar.com/callback?next={urlencode(http://www.facebook.com/logged-into-foobar)}

Note: we also support the concept of a "base domain", which essentially whitelists every page on that domain, and every page on all subdomains of that domain, as safe.

Case 2. Specified callback URL is relative.
In this case, there's no issue of safety, since we'll always redirect to a URL constructed based on the registered callback URL, which is by definition safe.

More information about constructing the URL to redirect to:
2.1. If the registered callback URL doesn't have a question mark anywhere in it, we can just append the specified callback URL to it and redirect. For example, with a registered callback of http://www.foobar.com/callback/ and a specified callback URL of "loggedin.php?done=true", we redirect to http://www.foobar.com/callback/loggedin.php?done=true.
2.2 If the registered callback URL has a question mark, we append the specified callback URL directly, but do some munging to the params to get everything on the same level. For example, with a registered callback of "http://www.foobar.com/callback?page=" and a specified callback URL of "loggedin.php?done=true", we redirect to http://www.foobar.com/callback?page=loggedin.php&done=true (notice how the second ? changed to a &).

Case 3. Unspecified callback URL.
I lied, there's actually a third case. We support auth flows with unspecified callback URLs in the request. If there's a registered callback URL, we just redirect there. Otherwise, we show an error message. So basically the only way to get an error message is if there is no specified callback URL or registered callback URL.

-Brent


On Nov 24, 2009, at 6:17 PM, Brian Eaton wrote:

On Tue, Nov 24, 2009 at 6:14 PM, Luke Shepard <lshepard@facebook.com<mailto:lshepard@facebook.com>> wrote:
Yup, that’s basically what we do today- throw an error and don’t return. But
this is less than ideal.

We have discussed that we’d probably like to return, but with an error
message. This would be in section 5.4.4 of the spec (“Authorization server
directs user back to the client”) we would like to pass additional
parameters for the error message- something other than user_denied, but
which indicates that the application was just misconfigured.

I guess it depends on the business requirements that led to callback
URL preregistration.  Some sites require callback URL registration so
they don't need to redirect to unknown third-party sites... in which
case redirecting with an error message doesn't really fix the issue.

Other sites require callback URL registration for security reasons, in
which case an error message is just fine.

Cheers,
Brian