Re: [OAUTH-WG] Fixing the Authorization Server Mix-Up: Call for Adoption

Nat Sakimura <> Wed, 24 February 2016 10:27 UTC

Return-Path: <>
Received: from localhost ( []) by (Postfix) with ESMTP id EA6091A1B11 for <>; Wed, 24 Feb 2016 02:27:51 -0800 (PST)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -1.999
X-Spam-Status: No, score=-1.999 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, SPF_PASS=-0.001] autolearn=ham
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id j9E8UaY3cTMD for <>; Wed, 24 Feb 2016 02:27:46 -0800 (PST)
Received: from ( [IPv6:2607:f8b0:400d:c04::230]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by (Postfix) with ESMTPS id D5F741A1B0B for <>; Wed, 24 Feb 2016 02:27:45 -0800 (PST)
Received: by with SMTP id y89so10102568qge.2 for <>; Wed, 24 Feb 2016 02:27:45 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20120113; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-type; bh=EF23NAyDclrUKdum8dK/PKtZVH1oeokECDVWsqpP2qE=; b=jBWsb0kptsaSTSW2YtSsfZjchTg8b4+D0egnGs/rqkH8HmlDZTa4kID42+FhcUGQJU 5nWHehvwMVmRs6YfCWTF++vJaKFGzwGwJknFEQHIbPTmJ4UoJQfQva5RFSCBfvygDz9x 6+eLnYMAafodAGpLXEHCzVAFoqMajjqvqoqZ8o4COpK0uP5ur95pUfh9I3gR31n4qEea uty5lif6SX2a09OnWoNYtwz5NtQCTUSI6NvDb59i6BffeJq5WO7VLcnoa5Oz4Fkq2k3R 0qESBuR5kbX4eBdoK/754v8j4dpKRiESArwLOskwys44VgyeLGwQMvPPP6oD0FOKAsCo SgGg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20130820; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-type; bh=EF23NAyDclrUKdum8dK/PKtZVH1oeokECDVWsqpP2qE=; b=D/6qX532H/RAA1Uf3VKGdKM4f9tUk0p7yzQRzX/TLRgZpHEjyqe/C8s/KXnAZyvHNJ 98+0dyZbP0m7DheYogiaseIJdHmj50EcVF3DlmguKogGuCUQbpp7Lm1MZ/CXrSx62see +jiTBSxuaM8dXAXA0ct56oXY90V1ALmRfbaPCJXxpNYIUnRaeTKI1SeSkdWtKJSCOD0H fRE3l046izS+vuXyOwvPGGQ72jclRgQTTu+dFhYShSr90qfnQtqQybfmVHfYaqcUGu35 W1N8yNsF6ewoy4DmVbJZR7fodmoA2AeTtJivVmi8hdMFxEGVsIKPCB6rP98hmtrdoJE4 EP8w==
X-Gm-Message-State: AG10YOQgcIyvYpiStHtQr2zb/O9dR2tU2MTZitylOUXFaOzKk8zRTKdm+K8xlYNrqADOONgnjiuuO3QfdiDvuA==
X-Received: by with SMTP id l196mr51044905qhl.58.1456309664868; Wed, 24 Feb 2016 02:27:44 -0800 (PST)
MIME-Version: 1.0
References: <> <> <> <> <> <> <05af01d16d4a$20230af0$606920d0$> <> <> <>
In-Reply-To: <>
From: Nat Sakimura <>
Date: Wed, 24 Feb 2016 10:27:34 +0000
Message-ID: <>
To: John Bradley <>, Roland Hedberg <>
Content-Type: multipart/alternative; boundary="001a1134f04c41efa8052c818422"
Archived-At: <>
Cc: "<>" <>
Subject: Re: [OAUTH-WG] Fixing the Authorization Server Mix-Up: Call for Adoption
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: OAUTH WG <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Wed, 24 Feb 2016 10:27:52 -0000

2016年2月24日(水) 8:17 John Bradley <>:

> This is not stoping the attack it is protecting code.

IMHO, this is the right approach. We should solve the problem
architecturally rather than bandaging the hols.

> I should point out that some of the attacks like man in the middling
> registration can still compromise the client secret, making it possible for
> an attacker to impersonate a client.

In case of the dyn-reg, the client really should make sure the identity of
the registration endpoint it is talking to through TLS certs checking. This
is the right way of addressing the man-in-the-middle in this case.
Manual case is hard to fix with a bearer client secret. We probably need to
do public key crypto. Instead of giving a bearer client secret, have the
client regiser the public key, just like we register ssh public key all the
time with github etc. It should not be too hard at all.

> Nat’s option B doesn’t have a solution to that ether as far as I can tell.
> I think the only option for that is to have a logical identifier for the
> AS and some sort of discovery check at registration to be certain that you
> are using the correct registration location.

How does it help with preventing the client credential theft through mitm
during the registration? Client secret is already gone by the time you do
the discovery.

> Option A plus discovery works for that and mitigates confused client but
> not cut and paste.
> We still have a problem with AT leaking.   I think that needs to be dealt
> with separately.
> Access tokens should have a audience (by value or by introspection) the
> client needs to tell the AS what resource it want s to use the token at and
> have that included as the audience or the request rejected because it is an
> invalid audience.

Is not the scope the implicit combination of the resource, the endpoint
form which you can access the resource,  and operation?

> That should happen at the token endpoint for code.

And, that's why we can send scope there.
The response can also include scope, which is good but my problem here is
that scope value in the response would be a bit too vague. Either having
the uri from which the client can get the list of the resource endpoint, or
get them as RFC5988 header would be nicer.

> For implicit it would need to be at the authoriation endpoint and the
> audience would need to be echoed back to prevent tampering.

For a javascript client that is interacting with the authorization
endpoint, getting them in the response header would be great.
For a client that is getting the response through browser redirect, the
audience value needs to be protected by PKCE response or something.

> The AT can also be protected by POP so I think that code and AT should be
> kept separate issues.

> John B.
> > On Feb 23, 2016, at 9:59 PM, Roland Hedberg <>
> wrote:
> >
> > In line !
> >
> >> 22 feb 2016 kl. 05:08 skrev John Bradley <>:
> >>
> >>> On Feb 22, 2016, at 9:22 AM, Nat Sakimura <>
> wrote:
> >>>
> >>> The risk impact of [case2] is more OAuth specific. The token is stolen
> as the token is going to be sent to a rogue resource, and the resource can
> use that to obtain the resource that was supposed to be only available to
> the proper client.
> >>>
> >>> The risk impact of [case3] is the most grave among these three. Now
> the attacker can create his own client that impersonates the compromised
> client.
> >>>
> >>> OAuth-mix-up
> >>> ---------------------------
> >>> OAuth-mix-up draft gives one way of addressing [case2] by introducing
> a new concept of “issuer” and “discovery” to RFC6749. It also returns
> client_id and verifies it in 4.2, but if the BadAS has assigned a same
> client_id to the client, it does not help.
> >>
> >> Client_id are not guaranteed to be unique.  They need to be name spaced
> by the AS.   In OAuth currently we have no name for the AS this makes that
> difficult, the client can use the authorization endpoint URI, but that
> logic may well break in multi tenant situations.   Having a clear issuer
> string makes it easier for the client.
> >
> > I stumbled over exactly this point when I made my implementation follow
> the Mix-Up draft.
> > If not discovery is involved I think an AS has to have a name which is
> different from the endpoint URIs.
> >
> >>> One of the issue with this approach is that the central notion of
> “issuer” is new to the existing servers and clients. The verification rule
> in 4.1 states “Compare the issuer URL for the authorization server that the
> client received when it registered at the authorization server”, but in
> most existing pure OAuth cases, there is no such thing, so you cannot
> compare. This means that you would have to re-register, and if you are
> doing that, the per-AS redirect_uri seems to be a much simpler solution.
> >>
> >> The client developers I have talked to really hate per AS redirect URI
> as being too awkward for deployments.
> >
> > I on the other hand found it quite easy to do per AS redirect URIs, so
> it might well be implementation
> > dependent rather then contextual.
> >
> >>>
> >>> Per AS Redirect URI
> >>> --------------------------------
> >>> This does not involve wire protocol changes. It just adds requirements
> on the redirect uri. This by far is the simplest solution for [case2] (and
> [case1]), IMHO.
> >>>
> >>> Again, it is not a general framework for finding out tainted
> communication, so it may have other holes.
> >>
> >> This is probably the hardest for the client developer and for the
> deployer.  Yes it is simplest from a spec point of view.
> >> We need more developer feedback on this.
> >
> > As I said above I found this quite simple to implement.
> >
> >>> (Extended) PKCE
> >>> ---------------------------------
> >>> To begin with, it works only with code flow. There has to be something
> else to deal with implicit flow.
> >>>
> >>> PKCE binds the authorization request/response to the token request.
> >>> If used with a confidential client, it seems to mitigate the
> vulnerability.
> >>> John points out that it is not the case. I must be missing something
> here… but my logic goes like:
> >>>
> >>>
> >>> 1.     The good client creates code_challenge-v and
> code_verifier-v=S256(code_challenge-v) and sends the client_id-v +
> code_challenge-v + state to the BadAS Authz EP.
> >>> 2.     BadAS as a client prepares a code_verifier-b and
> code_challenge-b=S256(code_verifer-b).
> >>> 3.     BadAS redirects to GoodAS with the client_id-v +
> code_challenge-b + state-v.
> >>> 4.     GoodAS stores the code_challenge-b.
> >>> 5.     GoodAS returns code-v + state-v to the client’s redirect uri.
> >>> 6.     The client finds the AS from the state and sends code-v +
> code_verifier-v + secret-b to the BadAS token endpoint. Now, code-v and
> code_verifer-v is phished.
> >>>
> >>> Now the attacker tries to use the code-v and code_verifier-v.
> >>>
> >>> ### Case A:
> >>> 7.     The BadAS as a client sends client_id-v + … but he does not
> have client secret for the good client, so it fails.
> >>>
> >>> ### Case B:
> >>> 8.     The BadAS as a client sends client_id-b + code-v +
> code_verifier-b + secret-b etc. to GoodAS.
> >>> 9.     GoodAS verifies the code_verifier-b is associated with code-v,
> but that code-v is not associated with client_id-b, so the token request
> fails.
> >>>
> >>> ### Case C: cut-n-paste
> >>> 10.  The attacker launches cut-n-paste attack by replacing the code-b
> with code-v.
> >>> 11.  The verifiers does not match, so fails.
> >>>
> >>> Please let me know what I am missing.
> >>
> >> In a step 0 the attacker has the good client create another request in
> the attackers user agent to get state-0 and code_challange-0
> >>
> >> Step 2 is not required.
> >> Step 3 Bad AS redirects to good AS with client_id_v + state-v +
> code_challenge-0
> >> Step 4 GoodAS stores code_challenge-0
> >> Step 5 GoodAS returns code-v + state-v to the clients redirect_uri
> >> Step 6 The client finds the AS from the state and sends code-v +
> code_verifier-v + secret-b to the BadAS token endpoint. Now, code-v and
> code_verifer-v is phished.
> >>
> >> Case C1 :  cut and paste
> >> 10.  The attacker launches cut-n-paste attack by inserting code-v into
> a response using state-0
> >> 11. The client sends code-v and based on state-0 it sends
> code_verifyer-0 to the good AS token endpoint.
> >> 12. The GoodAS verifies that code-verifyer-0 is correct for
> code_challange-0 that it bound to code in step 4
> >> 13. The GoodAS receives RT + AT.
> >> 14. The attacker has now used the client to bind the users resource to
> it’s account and is transferring money or looking at your data.
> >>
> >> This could be 3rd party financial app like Mint as an example or photos
> or any other PII that could then be used to escalate identity theft.
> >>
> >> This variation of the attack combining cut and paste with confused
> client was not mentioned in the research papers.
> >>
> >> I found it looking to see if PKCE could be used to mitigate the
> confused client attack.
> >>
> >> As I mentioned in a response to William, while the current PKCE
> Challenge methods only make the attack harder by forcing the attacker to
> get the client to make a step 0 request to get a code_challenge to use in
> the request,  we could define a new challenge method that would be
> effective.
> >>
> >> That would remove the need to have a separate mechanism to prevent cut
> and paste.
> >>
> >> The problem is that the PKCE challenge is independent of state so
> becomes vulnerable to the confused client.
> >>
> >> What we would need to do is include state in the challenge so that if
> the AS receives mismatched state and code_challange in step 3 the
> verification of code verifier will fail. Effectively combining the cut and
> paste mitigation with PKCE.
> >>
> >> I haven’t had time to write this up, but if the code_challenge ==
> SHA256 (SHA256(state) || token_endpoint URI || Authorization_endpoint URI
> || client_id || code-veriyer) ,  then the attacker could not change state,
> client_id, or token_endpoint  independently of code_challenge.  (note I am
> using a hash of state to make storage size deterministic for the AS on the
> grounds that the client already needs to be able to do the hash) (Some
> attacks  change the client_id in the request so I am including it in the
> hash)
> >>
> >> This is slightly more complicated than than S256, but not that much.  I
> wish I had thought of this when we were doing PKCE.   Hit me with the
> stupid stick, my fault.
> >>
> >> I don’t know if it stops all the confused client attacks though.
> >>
> >> If the client is confidential then it gives up it’s client secret
> assuming compromised registration, so we can’t really count on that for
> symmetric client authentication.
> >>
> >> By including the token endpoint in the comparison if the client is
> sending the code to the attacker the client will use a different token
> endpoint_uri in to calculate the code_challenge than the GoodAS will use to
> verify it.    This would stop both cut and paste as well as stopping the
> attacker from using the code if they get it.   The attacker can’t get
> Secret for state-0, so it can’t create code_challenge that would be valid.
> >>
> >> This stops the registration attack where the client gets a bad AS
> discovery endpoint that has all the Good AS info including dynamic
> registration endpoint but the bad AS token endpoint.   The bad AS would get
> the token, client_secret and code_verier, but will fail pkce verification
> because the token endpoint will be wrong.
> >>
> >> The attack where the client registers with the good AS but with bad
> token endpoint and Authorization endpoint gives the attacker the ability to
> change the code_challenge that the Good AS is going to see.   It would need
> to make a new challenge using state and the GoodAS token endpoint and it’s
> client_id.
> >> To do that it needs the code_verifier to use to calculate the hash to
> use as the code_challenge value.  As long as the client is not tricked into
> accepting a replay of the authentication response we should be safe.  The
> client would need to do replay protection on the code_verifier values
> before it makes a request to the token endpoint.
> >>
> >> The BadAS could however make up a new code_challenge and code_verifier
> and use that in the request. For this one the AS would need to do pull
> discovery on the client to get a key, or the AS needs to return something
> in the response.  This attack can completely proxy all the endpoints as far
> as the client is concerned and is taking advantage of the AS saying you are
> granting permission to site X based on the redirect URI.
> >>
> >> I can’t see PKCE on it’s own being able to stop a client from being
> used as a redirector back to the attacker unless you also returned the
> code_challenge in the response from the authorization endpoint.
> >>
> >> Hypothetically if we returned code_challenge in the response from the
> authorization endpoint and have a new PKCE challenge method we might find
> it covers all of the attacks.
> >>
> >> We would need to put some serious analysis into this to see if it
> really covers all the attacks.
> >>
> >> It however doesn’t address the “token” response_type or steeling the
> access token by impersonating the RS.
> >>
> >> I think the correct way to stop the problem with access tokens is by
> audience restricting them.
> >> To do that the client needs to provide an audience in it’s request and
> the AS needs to include that in the AT.
> >>
> >> I included the Authorization_endpoint URI in the hash to detect if the
> auth request may have been tampered with to change the audience for the AT.
> >>
> >> For implicit we could have a version of PKCE where the AS returns a
> parameter with S256( client_id || authorization_endpoint URI || resource
> endpoint URI) to verify the request was not tampered with, and that would
> allow the AT to be properly audience restricted.
> >>
> >>
> >> This would be a completely new approach not involving discovery,
> logical names for AS, or link relations.
> >>
> >> Effectively this code_challenge method becomes a signature over parts
> of the request and the implicit audience of the token_endpoint URI.
> >>
> >> People keep asking why PKCE doesn’t stop these attacks, and it won’t
> with the current PKCE methods,  however a new method along the lines I
> sketched out may let it work, or I could be completely wrong.
> >
> > Once you have written down something more definite I promise to
> implement it promptly such that we can do interop
> > testing early in the process.
> >
> > Before John brought up this new PKCE mode I was on the Option A side of
> the fence now I’d like to see more
> > of this PKCE idea before committing to one or the other.
> >
> > — Roland
> >
> > ”Everybody should be quiet near a little stream and listen."
> > From ’Open House for Butterflies’ by Ruth Krauss
> >
> _______________________________________________
> OAuth mailing list