{ Community }
  • Academy
  • Docs
  • Developers
  • Resources
    • Community Articles
    • Apigee on GitHub
    • Code Samples
    • Videos & eBooks
    • Accelerator Methodology
  • Support
  • Ask a Question
  • Spaces
    • Product Announcements
    • General
    • Edge/API Management
    • Developer Portal (Drupal-based)
    • Developer Portal (Integrated)
    • API Design
    • APIM on Istio
    • Extensions
    • Business of APIs
    • Academy/Certification
    • Adapter for Envoy
    • Analytics
    • Events
    • Hybrid
    • Integration (AWS, PCF, Etc.)
    • Microgateway
    • Monetization
    • Private Cloud Deployment
    • 日本語コミュニティ
    • Insights
    • IoT Apigee Link
    • BaaS/Usergrid
    • BaaS Transition/Migration
    • Apigee-127
    • New Customers
    • Topics
    • Questions
    • Articles
    • Ideas
    • Leaderboard
    • Badges
  • Log in
  • Sign up

Get answers, ideas, and support from the Apigee Community

  • Home /
  • General /
avatar image
1

Dispensing tokens via OAuthV2 with PKCE (RFC 7636)  

  • Export to PDF
Dino-at-Google   created · Nov 28, 2018 at 10:06 PM · 2.1k Views · edited · Dec 04, 2018 at 04:41 PM

Let's talk about OAuth, shall we?

Authorization Code grants

The authorization code grant, as described in the OAuth V2 spec (RFC 6749), is intended for use with 3rd-party client apps. "3rd party" means, an app that is not written by the same party that produces the API. The app is therefore not implicitly trusted, and OAuth says that a user should grant consent to the app, to allow it interact with the APIs on behalf of the user. This consent is embodied in the access token issued to the app, via the authorization code grant.

With the authorization code grant, both the user and the app credentials must be verified before the authorization server issues a token. In the Apigee Edge model, an external Identity Provider verifies the user credentials, and Apigee Edge itself verifies the application (client) credentials.

Beyond authenticating the user, the authorization grant should also check the user consent. In a typical login-and-consent user experience, the user first authenticates, and then consents to the app (client) receiving a token with the stated scopes. Some login-and-consent experiences may collapse those two steps into one interaction). Login-and-consent is almost always performed via a trusted user agent, in other words the web browser builtin to the client platform. In some cases a different interaction model can be used to grant consent, like an SMS exchange. Eg, "Do you consent to App X obtaining scope Y? Reply YES to allow this."

After consent, login-and-consent returns the code to the client (app) via a 302 redirect, sent to the redirect address registered for that client. The client POSTs that code to the /token endpoint to receive an access token.

PKCE

All of that is just standard authorization code grant. aka "The 3-legged OAuth dance." Proof Key for Code Exchange, also known as PKCE (RFC 7636) extends that basic model to add a code challenge and code verifier to the protocol, in this way:

In the GET /authorize call, the client passes the CHALLENGE.

When exchanging the code for a token (POST /token), the client passes the VERIFIER.

The Authorization server (Apigee Edge in this case) is responsible for retaining the challenge, and during exchange-code-for-token, checking that the verifier matches the challenge. The idea is to eliminate the possibility for a malefactor to intercept the code, and then be able to obtain a bonafide token with it. You can look at the write-up by Okta for a more detailed description of the motivation for PKCE.

Can Apigee Edge be used for PKCE grants?

PKCE is on the standards track from IETF. It's an open protocol at this point. Can Apigee Edge dispense tokens using the PKCE extension to OAuth2 3-legged grants?

YES. Out of the box, the OAuthV2 policy (and the GenerateAccessToken Operation) does not include support for PKCE. But, it's really straightforward to add this into your own token dispensing proxy, if you want it.

The way to do it:

  1. in the handler for the GET /authorize call, Apigee Edge creates a session which stores the CHALLENGE
  2. In the handler for the POST /token call, Apigee Edge checks the VERIFIER against the CHALLENGE.

It's that simple.

OK, it's not absolutely simple, because OAuthV2 authorization code grants are not simple. There are numerous interactions to handle and you need to consider all of them in the design of the token dispensing proxy. But Apigee Edge handles those grants quite easily. Adding PKCE to the mix requires a very simple enhancement to the normal token dispensing proxy that uses authorization code grant.

AND, the good news is that I have put together s a screencast showing how PKCE works in Apigee Edge:

And here is a repo that contains all the proxy configuration, as well as some tools, so you can use the same thing in your own Apigee Edge organization.

https://github.com/DinoChiesa/Edge-OAuthV2-PKCE-Proxy

I'd love to hear your comments on this.

hqdefault.jpg (7.5 kB)
thub.nodes.view.add-new-comment
oauth 2.0oauthoauthv2pkce
Add comment Show 8
10 |5000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by Apigeeks only
  • Viewable by the original poster
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Anand Gururaja · Feb 10, 2020 at 07:29 PM 0
Link

Instead of using Cache policy, can we use custom attributes like code challenge, code challenge type etc embbeded into the auth code and then checking them back during the POST request to generate the token using auth code, code verifier?

Thanks,

Anand

avatar image Sartaj Singh Sisodiya Anand Gururaja · Apr 01, 2020 at 03:32 PM 0
Link

@Dino @Dino-at-Google Can we use the above approach, highlighted by @Anand Gururaja , where code_challenge store as a custom attribute in code flow and later /token flow just use attribute (code_challenge) to verify ?
Please suggest

avatar image Dino-at-Google ♦♦ Sartaj Singh Sisodiya   · Apr 01, 2020 at 05:01 PM 0
Link

Yes, I think that is a good idea. ...

avatar image dominiksommer · Jun 26, 2020 at 02:30 PM 0
Link

@Dino-at-Google I just browsed through the repo implementation, and stumbled over:

    <Flow name="token">
              <!--
                  The app uses this request to exchange the code for a token.
                  Example:
      
                  POST /devjam3/oauth2-ac/token?
                    grant_type=authorization_code
                    &client_id=wlq93FiqTw1si09wsocM7AjOBSbyi4
                    &client_secret=78djdkdjdkjd<br>

And indeed, I can't get it to work if I don't pass a client_secret. However, if I get RFC 7636 correctly, the whole point of PKCE is to avoid distributing client secrets to public clients (where PKCE provides means to protect specific attacks).

Hence, I tried setting ExternalAuthorization to true in the OAuth2 policy (following the docs) in order to avoid the client secret (that I don't want to include in the request) being checked. Due to some magic that still seems to happen, I keep ending up with HTTP 500 and the following error:

{"fault":{"faultstring":"Invalid client identifier {0}","detail":{"errorcode":"oauth.v2.InvalidClientIdentifier"}}}<br>

I double-checked that the client_id parameter is still passed and a valid API key. If I set oauth_external_authorization_status to true, the error I'm receiving is upgraded to:

{"fault":{"faultstring":"Invalid access token","detail":{"errorcode":"oauth.v2.InvalidAccessToken"}}}

Is there any specific setting that skips client authentication (using client_secret), but still generates an access token? I think that would be a plausible addition to the example repo.

Br,
Dominik

avatar image Dino-at-Google ♦♦ dominiksommer   · Jun 26, 2020 at 02:49 PM 1
Link

Yes, good point.

PKCE attempts to avoid the requirement to pass secrets. And in fact the client_secret here need not be secret. It's redundant.

Unfortunately, The Apigee OAuthV2 policy requires a client_secret when Operation=GenerateAccessToken. There is no way, currently, to configure the Apigee policy to use PKCE which does not require the client_secret.

In the non-PKCE flow, the client app passes the client_secret and the policy within the API Proxy just references it through a context variable. In the PKCE flow, we don't NEED it. My implementation was ... ok, let me just say it... sloppy.

The way to correct this in the implementation is, within the API Proxy, to use an AccessEntity policy to retrieve the client_secret for the client_id that is passed in. Then reference THAT client_secret.

I'll modify the repo. and post-back when it's ready.

avatar image dominiksommer Dino-at-Google ♦♦ · Jun 26, 2020 at 03:55 PM 0
Link

Thanks for the quick reply! I worked around it meanwhile by setting the oauth_external_authorization_status variable to true in an AssignMessage policy, and the

ExternalAuthorizationCode element to request.formparam.code in the OAuthV2 policy. Since the auth code is dumped anyway (as opposed to ExternalAccessToken), it doesn't really hurt.

Using AccessEntity to fetch the client_secret would have been my fallback solution :-)

Show more comments
avatar image Dino-at-Google ♦♦ Dino-at-Google ♦♦   · Jun 26, 2020 at 05:41 PM 1
Link

OK, I've updated the repo so that redemption of code-for-token does not require the client_secret. Check it out.

(I have not updated the screencast)

Article

Contributors

avatar image

Follow this article

88 People are following this .

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Navigation

Dispensing tokens via OAuthV2 with PKCE (RFC 7636)

Related Articles

Apigee as OAuth Resource Server - PingFederate as OAuth Authorization Server with synchronized client IDs.

Configuring Apigee to dispense OAuth tokens - either opaque or JWT

Apigee as OAuth Resource Server - PingFederate as OAuth Authorization Server with dynamic client id mapping.

Apigee as OAuth Provider - PingFederate as IdentityProvider : using OpenID Connect Flow

Screencast: Issuing OAuth tokens in Apigee Edge using Password Grant, and verifying same

Auth0 with Apigee

Calling the Apigee Management APIs before and after enabling SSO

Automating Access to the Apigee Management APIs using Machine User Credentials

POP - Using JWT to prove possession of a key

Oauth2.0 Access Token Verification throws “Invalid API call as no apiproduct match found” error

  • Products
    • Edge - APIs
    • Insights - Big Data
    • Plans
  • Developers
    • Overview
    • Documentation
  • Resources
    • Overview
    • Blog
    • Apigee Institute
    • Academy
    • Documentation
  • Company
    • Overview
    • Press
    • Customers
    • Partners
    • Team
    • Events
    • Careers
    • Contact Us
  • Support
    • Support Overview
    • Documentation
    • Status
    • Edge Support Portal
    • Privacy Policy
    • Terms & Conditions
© 2021 Apigee Corp. All rights reserved. - Apigee Community Terms of Use - Powered by AnswerHub
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Create an article
  • Post an idea
  • Spaces
  • Product Announcements
  • General
  • Edge/API Management
  • Developer Portal (Drupal-based)
  • Developer Portal (Integrated)
  • API Design
  • APIM on Istio
  • Extensions
  • Business of APIs
  • Academy/Certification
  • Adapter for Envoy
  • Analytics
  • Events
  • Hybrid
  • Integration (AWS, PCF, Etc.)
  • Microgateway
  • Monetization
  • Private Cloud Deployment
  • 日本語コミュニティ
  • Insights
  • IoT Apigee Link
  • BaaS/Usergrid
  • BaaS Transition/Migration
  • Apigee-127
  • New Customers
  • Explore
  • Topics
  • Questions
  • Articles
  • Ideas
  • Badges