Re: [OAUTH-WG] Motivation for plain transform method in PKCE, and encrypted code_challenge in code

William Denniss <> Wed, 24 June 2015 21:03 UTC

Return-Path: <>
Received: from localhost ( []) by (Postfix) with ESMTP id F25F61B2E12 for <>; Wed, 24 Jun 2015 14:03:15 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: 0.511
X-Spam-Status: No, score=0.511 tagged_above=-999 required=5 tests=[BAYES_40=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FM_FORGED_GMAIL=0.622, HTML_MESSAGE=0.001, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01] autolearn=no
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id zq_t7gDzZ1tA for <>; Wed, 24 Jun 2015 14:03:14 -0700 (PDT)
Received: from ( [IPv6:2607:f8b0:400d:c09::22e]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by (Postfix) with ESMTPS id 0301F1B2E25 for <>; Wed, 24 Jun 2015 14:03:14 -0700 (PDT)
Received: by qkfe185 with SMTP id e185so28502767qkf.3 for <>; Wed, 24 Jun 2015 14:03:13 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; bh=RTGq7yuG+ov7NqP/Dp8HJ8dM1Pi1tLt/iLtDf4vpoHE=; b=DTOVLkcEJoO1mJEg5Tf61ygXAttZBeZQi9mdT5PSCCAXNbolWGGxadKzgnwMR69aah Pu30+3TlSKPqnilQrPDnU5sES/Sfgsw4ex1bq0bdLB1Qkw/5GkBvTYOxq20ht14MYu1/ EgyIVodJdrnBL2TSgA5cFN8WfdvqfZMewV4lRXuFveaHmEXlz0yYxlQq6yTgeZUbY1xc 3xGq9Z+9Hj57tukm2Ngq9JyJRbTwPpscN1oRZamV8QpCiBsJpCzFDFoymiNZZWoQFOBG 8YopdkjmNl9DQFJLnuyQkTbfw5XdpEHf4o+IQCuYOm7Sma0mf5Dz+5X5ZhLtqrVeQx3n 9Tzg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc:content-type; bh=RTGq7yuG+ov7NqP/Dp8HJ8dM1Pi1tLt/iLtDf4vpoHE=; b=OtgWAhgwL0Ae/pHTRZ37QBm+JTjoEYbadPogn6+xlqvxwklZgvgvvYdHwA2f085l2a 8nPeF/qlferN3Cap6G0fm6XD9MYcDXh4I0NNCmIFUy5hpjfmbunFa1j/pzHH2foljLwx kIp+NlHLKJZwZUfpPeF9lE8tBuJBZj8LR058MWZZERkao5wqOXfU11EypaCMq/dhq53Y I4MQfOWr+lNq035vTgo1EJ6XzVmJ7U6Obilb256CzJGB8zbK00+fFZdUWyji0DdtshiZ MYeX9vMxDHeaCwUEpDvDzu+A2FvF7UXb+q2jny/bck4hYMJwf1bU/Su7TxhtssusI0q8 g4VQ==
X-Gm-Message-State: ALoCoQkwHY6+7CsDAHtIKnKw+h9EpEQSpodXcwBl4aafqPRlz/7kLtkZ2jVjs44XXAObzIJQ1ZeL
X-Received: by with SMTP id 80mr88617529qkv.11.1435179793210; Wed, 24 Jun 2015 14:03:13 -0700 (PDT)
MIME-Version: 1.0
Received: by with HTTP; Wed, 24 Jun 2015 14:02:53 -0700 (PDT)
In-Reply-To: <>
References: <>
From: William Denniss <>
Date: Wed, 24 Jun 2015 14:02:53 -0700
Message-ID: <>
To: Adam Lewis <>
Content-Type: multipart/alternative; boundary=001a11473dcec39264051949d594
Archived-At: <>
Cc: "" <>
Subject: Re: [OAUTH-WG] Motivation for plain transform method in PKCE, and encrypted code_challenge in code
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 Jun 2015 21:03:16 -0000

Hi Adam,

I work with Naveen (one of the co-authors), and we support the plain
transform method with PKCE for OAuth on iOS currently. My comments are

On Wed, Jun 24, 2015 at 8:20 AM Adam Lewis <>

> Hi,
> I'm probably missing something here, but what is the use case for allowing
> the plain transform method in PKCE?  It seems to me the entire point of
> sending the hash of the code_verifier (code_challenge) rather than the
> code_verifier itself is to avoid leaking the code_verifier through
> the browser during the authorization request.

> It seems using the plain type would enable an attacker to intercept
> the code verifier and use it to exchange the code for the AT.

PKCE w/ plain protects against a specific attack where a rogue app
intercepts (or eavesdrops) the Authorization Code Grant, but not the
initial auth request.  The code interception attack vector is quite real on
mobile platforms that rely on custom URI schemes for returning the OAuth
code to the native app, and was the motivation of this spec.

PKCE w/ S256 additionally protects against the case where both the auth
request and code grant can be eavesdropped (and potentially the code grant
– but not the initial auth request – intercepted).  Due to the fact
inter-process communication tends to be less secure than HTTPS, this is the
best practice.

If the rogue app can intercept the initial auth request (which is a risk
for a native OAuth token agent), then they are executing a local MitM
attack and all bets are off (that attack isn't protected by PKCE, though we
are looking at addressing this issue separately, within the OIDF NAPPS
Working Group).

Importantly, on iOS if your auth request is initiated with a "https://" url
(i.e. a normal OAuth2 web request), the auth request can *not* be
intercepted by a rogue app, but the returning authorization code grant
*can* be (if uses a custom URI scheme to return the code to the native app
from the browser). PKCE w/ plain was designed specifically to protect
against that attack, and is why we implemented it.

> If a client is really unable to compute a S256 hash, wouldn't it just fall
> back to vanilla OAuth?

PKCE w/ plain prevents some actual attack scenarios today. S256 remains the
best practice, but it doesn't invalidate the effectiveness of "plain" in
some situations.

> Also, under security considerations, it mentions that if the code
> challenge is returned as part of the code, it needs to be encrypted. Not
> sure why since it was sent un-encrypted, where the attacker would have
> already had the opportunity to intercept/obtain it. Plus 7.3 re-enforces
> the point that the code verifier has sufficient entropy to prevent brute
> force attacks.  I suppose the motivation then for encrypting the
> code_challenge is to address the scenario whereby 1) the plain transform
> method is used, and 2) a malicious app fails to intercept the
> code_challenge, but then 3) gets the code?

There are two common ways the Authorization Server can associate the
verifier with the code to compare later when the code is redeemed on the
token endpoint. One is storing and associating the code and verifier server
side, the other avoids server storage by using symmetric encryption to
encode both the verifier and code together, and return that as the code
(this works as the client treats the authorization code as an opaque blob).
Then when the code is redeemed, the server can decrypt, and get the
verifier.  But that is unrelated to the transform method.

> Just looking for some background understanding of what went into these
> designs.

I hope the above explanations help.