Re: [OAUTH-WG] Refresh tokens

Aaron Parecki <aaron@parecki.com> Fri, 19 July 2019 23:50 UTC

Return-Path: <aaron@parecki.com>
X-Original-To: oauth@ietfa.amsl.com
Delivered-To: oauth@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 50B171200E6 for <oauth@ietfa.amsl.com>; Fri, 19 Jul 2019 16:50:13 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.899
X-Spam-Level:
X-Spam-Status: No, score=-1.899 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=parecki-com.20150623.gappssmtp.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id NxYLRQn1MdXq for <oauth@ietfa.amsl.com>; Fri, 19 Jul 2019 16:50:10 -0700 (PDT)
Received: from mail-io1-xd2e.google.com (mail-io1-xd2e.google.com [IPv6:2607:f8b0:4864:20::d2e]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id E990F120033 for <oauth@ietf.org>; Fri, 19 Jul 2019 16:50:09 -0700 (PDT)
Received: by mail-io1-xd2e.google.com with SMTP id h6so61902147iom.7 for <oauth@ietf.org>; Fri, 19 Jul 2019 16:50:09 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=parecki-com.20150623.gappssmtp.com; s=20150623; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=kHX7JHcX/wjB8hjTfUMxTrLaPTNka6wC4v45CpwlBKc=; b=JccImfMXqhePuQbcr3PaTIWX6S/f5O/pt1+FGCXwVzRtxMC1gGwD5n1AFfu9GYrD4J k1HhWWI34gj/byQDLXmfdQRrQAnY2mo1y1cxY+L7Tx7lE1XJg/cvPajR5waARoQNdnzd QGQtRaF/w15WUMpdR+VXxHp+dSHruft/qEpz7o+Sr/OxBDG5OJgs4RBeSF3cARSPfPrC gjT/dTA9Jjm2091RHZcvTnPqHE4n9bTPYmh7yZsx/P3f2KxDAlCoY+I/DdrFQ0GXgWMm K/Pc7zFj3tZBB18Ngyl0cz9P7dluiuLQMyMVO75algJNtjqHY8PRVcA/melKiGtn05Ce XCHw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to; bh=kHX7JHcX/wjB8hjTfUMxTrLaPTNka6wC4v45CpwlBKc=; b=QoI/Wn/ULpAArvrTE3mZEHetkKbJQR2EOuUU/PxspoaYluEeclhtlX7GMh/YE60Zq8 uHedFjQoXyzRxsc40MCpVFUWpeEEuE+MsXWFMtCwc84l9GoSHPxJPAYmqBTmfeJxWBCw /dxdJdoUlhMcTWGatebyH1vU9pd5WdwxzCah1GxZDbC/792YB79Iv5W+bOCmGsA8g8V9 Yl7WwTdGuEA50k/Zksm2TBva3mz3LrRtCsjfNVzWYxCH5x0OEPX71SDOOuUGHY398WsN 0ZCeAkgl4RAu1XBtyqsPeXQZFhrIaBrrlLom7R3zZrMS6yR05wXyW/4gVW0WviBKZCJN bwkw==
X-Gm-Message-State: APjAAAWDRZUq7FrexC8rs/ShLdfAL9aLosaNc2bOiQ6m0X9/H6gbc8vq coBgvWnXn9YGHhMrESKvfZXsk1XZ
X-Google-Smtp-Source: APXvYqwl4M20tLDkm7MwfRWZ8MxA/ZYKAq4udtVDYrjpjiQn5LCRakG9I0CpEAc+JbPm+waj+cvuFA==
X-Received: by 2002:a6b:da01:: with SMTP id x1mr26980388iob.216.1563580208817; Fri, 19 Jul 2019 16:50:08 -0700 (PDT)
Received: from mail-io1-f51.google.com (mail-io1-f51.google.com. [209.85.166.51]) by smtp.gmail.com with ESMTPSA id i4sm46278844iog.31.2019.07.19.16.50.07 for <oauth@ietf.org> (version=TLS1_3 cipher=AEAD-AES128-GCM-SHA256 bits=128/128); Fri, 19 Jul 2019 16:50:07 -0700 (PDT)
Received: by mail-io1-f51.google.com with SMTP id f4so61944114ioh.6 for <oauth@ietf.org>; Fri, 19 Jul 2019 16:50:07 -0700 (PDT)
X-Received: by 2002:a6b:f816:: with SMTP id o22mr25985342ioh.166.1563580207343; Fri, 19 Jul 2019 16:50:07 -0700 (PDT)
MIME-Version: 1.0
References: <CABw+FcsH3CHmFphz5DD6aDeEqKLxbQhY14kdrXCVY0WXQN6PuQ@mail.gmail.com> <AEC7268A-D22D-41DA-8609-E7D2DD3B290C@alkaline-solutions.com> <624da319-b19c-053b-4fd0-048c0e2b8fb9@aol.com> <CAGBSGjp8m+V+i-sNnrLmu7DR_Bo1uv0iGkW2o7hiqUWw8Sc7qg@mail.gmail.com> <138cbde0-11b7-8f23-1028-3af0846b5a01@aol.com>
In-Reply-To: <138cbde0-11b7-8f23-1028-3af0846b5a01@aol.com>
From: Aaron Parecki <aaron@parecki.com>
Date: Fri, 19 Jul 2019 18:49:38 -0500
X-Gmail-Original-Message-ID: <CAGBSGjq=SFG5nfOA6nwRsEQY576dsJDAHaL9UH4Yh7AAtOMu5Q@mail.gmail.com>
Message-ID: <CAGBSGjq=SFG5nfOA6nwRsEQY576dsJDAHaL9UH4Yh7AAtOMu5Q@mail.gmail.com>
To: George Fletcher <gffletch@aol.com>, OAuth WG <oauth@ietf.org>
Content-Type: multipart/alternative; boundary="000000000000d62e3e058e11624d"
Archived-At: <https://mailarchive.ietf.org/arch/msg/oauth/LfC0MrGuxLWKiXT_hKWdRzn_8cs>
Subject: Re: [OAUTH-WG] Refresh tokens
X-BeenThere: oauth@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: OAUTH WG <oauth.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/oauth>, <mailto:oauth-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/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: Fri, 19 Jul 2019 23:50:13 -0000

So what I'm hearing in this thread is essentially that:

1) depending on how it's implemented, using a refresh token in a SPA can
provide security benefits over using only access tokens
2) it is still "dangerous" to allow refresh tokens to be used without
client authentication
3) if there is a way to do some sort of dynamic client registration or
proof of possession, then using a refresh token would in fact be more secure

Since these points are in conflict with each other, and depend on things
currently in flux, it seems like the best thing to do at this time is to
remove the guidance on refresh tokens in browser-based apps. Maybe leaving
the mention of rotating the refresh token on every use, but I'm inclined to
remove the "SHOULD NOT issue refresh tokens" statement in order to leave
room for DPoP or similar in the future.

Sound reasonable?

----
Aaron Parecki
aaronparecki.com
@aaronpk <http://twitter.com/aaronpk>



On Thu, Jul 11, 2019 at 2:52 PM George Fletcher <gffletch@aol.com> wrote:

> You are correct that client authentication is not required for public
> clients (which doesn't preclude the use of refresh_tokens) but from my
> perspective it weakens the security because anyone with the refresh_token
> is able to get new access_tokens without any additional proof.
>
> Now if the SPA performs some sort of Dynamic Client Registration or DPoP
> then I think it's a completely different scenario and it doesn't bother me
> as much for their to be refresh_tokens in the browser. This of course is
> just my perspective:)
>
> On 7/10/19 7:56 PM, Aaron Parecki wrote:
>
> 2. To use a refresh token at the /token endpoint, client authentication is
>> required. This is where it gets difficult for default SPAs because they are
>> public clients and the only mechanism to authenticate them is the client_id
>> which is itself public. For me, this is the real risk of exposing the
>> refresh_token in the browser.??
>
>
> RFC6749 says "If the client type is confidential or??the client was issued
> client credentials,??the client MUST authenticate..." which I take to mean
> that refresh tokens could be used without a client_secret, both for native
> an javascript apps.
>
> This discussion of offline vs online refresh tokens is interesting, but I
> worry that we may be narrowing our focus here too much.
>
> There's a use where JavaScript apps may be able to take advantage of
> offline access, which is around Service Workers. This allows a website to
> install some code from a website which can continue to run in the
> background, though sometimes only while triggered from external events. One
> useful example of this is a syncing daemon, where a push notification can
> be sent from a web server to a Service Worker, which could cause that code
> in the browser to need to make a request to an API, which then may need to
> be able to get a new access token, which is effectively offline access.
>
> ----
> Aaron Parecki
> aaronparecki.com
> @aaronpk <http://twitter.com/aaronpk>
>
>
>
> On Tue, Jul 9, 2019 at 9:16 AM George Fletcher <gffletch=
> 40aol.com@dmarc.ietf.org> wrote:
>
>> I'll just add a couple more thoughts around refresh_tokens.
>>
>> 1. I agree with David that refresh_tokens are valuable in an "online"
>> scenario and should be used there.
>>
>> 2. To use a refresh token at the /token endpoint, client authentication
>> is required. This is where it gets difficult for default SPAs because they
>> are public clients and the only mechanism to authenticate them is the
>> client_id which is itself public. For me, this is the real risk of exposing
>> the refresh_token in the browser.
>>
>> 3. If the AS supports rotation of refresh_tokens and an attacker steals
>> one and uses it, then the SPA will get an error on it's next attempt
>> because it's refresh_token will now be invalid. If the refresh_tokens are
>> bound to the user's authentication session, then the user can logout to
>> lockout the attacker. However, that is a lot of "ifs" and still provides
>> the attacker with time to leverage access via the compromised refresh_token.
>>
>> In principle, I agree with the recommendation that SPAs shouldn't have
>> refresh_tokens in the browser. If it's not possible to easily refresh the
>> access token via a hidden iframe (becoming more difficult with all the
>> browser/privacy cookie changes. e.g. ITP2.X) then I'd recommend to use a
>> simple server component such that the backend for the SPA can use
>> authorization_code flow and protect a client_secret.
>>
>> Thanks,
>> George
>>
>> On 7/8/19 11:17 PM, David Waite wrote:
>>
>>
>> On Jul 8, 2019, at 7:10 PM, Leo Tohill <leotohill@gmail.com> wrote:
>> Re 8. Refresh Tokens
>>
>> ???? "For public clients, the risk of a leaked refresh token is much
>> ?? ??greater than leaked access tokens, since an attacker can potentially
>> ?? ??continue using the stolen refresh token to obtain new access without
>> ?? ??being detectable by the authorization server.?? "
>>
>> (first, note the typo "stoken".)
>>
>> Is it always "higher risk"??? I could even argue that leakage of a
>> refresh token is lower risk. As a bearer document, a leaked access token
>> allows access to resources until it expires.?? A leaked refresh token, to
>> be useful,?? requires an exchange with the AS, and the AS would have the
>> opportunity to check whether the refresh token is still valid (has not been
>> revoked).?? (of course revocation might NOT have happened, but then again,
>> it might have.)
>>
>>
>> I agree (with caveats, of course).
>>
>> Access tokens and refresh tokens may or may not be attached (by policy)
>> to an authentication session lifetime. It is far easier to picture refresh
>> tokens which are not attached to an authentication session (sometimes
>> called ???offline??? access) being inappropriate for a browser-based app,
>> which is nearly always a client that the resource owner is interacting with.
>>
>> Variants that may want offline tokens are less easy to imagine - perhaps
>> browser extensions?
>>
>> I believe the language currently there is due to AS implementations
>> predominantly treating refresh tokens as being for offline access, and
>> access token lifetime being short enough to not outlast an authentication
>> session.
>>
>> Furthermore, since the access token is transmitted to other servers, the
>> risk of exposure is greater, due to possible vulnerabilities in those
>> called systems (e.g., logs).?? Isn't this the reason that we have refresh
>> tokens? Don't refresh tokens exist because access tokens should have short
>> TTL, because they are widely distributed?
>>
>>
>> Yes. Once you acknowledge the existence of ???online??? refresh tokens,
>> they become a strong security component:
>>
>> - Refresh tokens let you shorten the access token lifetime
>> - A shorter access token lifetime lets you have centralized policy to
>> invalidate access without needing to resort to token
>> introspection/revocation
>> - Token refresh can theoretically be used to represent other policy
>> changes by both the client (creating tokens targeting a new resource server
>> or with reduced scopes) and server (changing entitlements and
>> attributes/claims embedded within a structured token)
>> - Refresh tokens can be one-time-use, as recommenced by the security BCP.
>> A exfiltrated refresh token will result in either the attacker or the user
>> losing access on the next refresh, and a double refresh is a detectable
>> security event by the AS.
>>
>> "Additionally, browser-based applications provide many attack vectors by
>> which a refresh token can be leaked."
>>
>> The risks of leaking a refresh token from the browser are identical to
>> the risks of leaking an access token, right??? This sentence could be
>> changed to "... by which *a token* can be leaked."
>>
>> A refresh token is "higher risk" because its TTL is usually greater than
>> the access token's TTL.?? But if our advice here leads to people using
>> longer-lived access tokens (because of the problems with getting a new
>> access token without involving the user), then the advice will be counter
>> productive.???? The longer life gives more time for the usefulness of a
>> browser-side theft, and more time for the usefulness of a server-side
>> theft.??
>>
>> Which scenario is safer?
>>
>> A) using an access token with a 10 minute TTL, accompanied by a refresh
>> token with a 1 hour TTL
>> B) using an access token with a 1 hour TTL, and no refresh token.??
>>
>>
>>
>> Given tokens that track authentication lifetime, it is hard to make a
>> case that refresh tokens which last for the authentication session are a
>> greater security risk than opaque access tokens (requiring token
>> introspection) that will last the same time.??
>>
>> Typically an AS (or OP) would issue a structured access token with a
>> lifetime expected to expire before the authentication session, with new
>> tokens issued via requests made in an embedded, iframe (hidden,
>> prompt=none). There may be benefits here of user cookies (or perhaps
>> managed-device information) against an authorization endpoint being used to
>> make decisions that could not be made by a refresh against the token
>> endpoint.??
>>
>> I???d be interested in hearing how strong of an implementation issue this
>> might be for deployments - I could see a non-security argument that the BCP
>> should only have one recommended approach here, and that there are
>> deployments needing the iframe approach.
>>
>> -DW
>>
>>
>> _______________________________________________
>> OAuth mailing listOAuth@ietf.orghttps://www.ietf..org/mailman/listinfo/oauth <https://www.ietf.org/mailman/listinfo/oauth>
>>
>>
>> _______________________________________________
>> OAuth mailing list
>> OAuth@ietf.org
>> https://www.ietf.org/mailman/listinfo/oauth
>>
>
> _______________________________________________
> OAuth mailing listOAuth@ietf.orghttps://www.ietf.org/mailman/listinfo/oauth
>
>
>