From 9568de6b905b2a827e7e7325441e2aa83f948af0 Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Tue, 5 May 2020 11:58:48 -0500 Subject: [PATCH] command: Fix OAuth2 PKCE arguments Providers like Okta and AWS Cognito expect that the PKCE challenge uses base64 URL Encoding without any padding (base64.RawURLEncoding) Additionally, Okta strictly adheres to section 4.2 of RFC 7636 and requires that the unencoded key for the PKCE data is at least 43 characters in length. --- command/login.go | 6 ++++-- command/testdata/login-oauth-server/oauthserver.go | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/command/login.go b/command/login.go index 323dd7802c..586e9414cd 100644 --- a/command/login.go +++ b/command/login.go @@ -654,14 +654,16 @@ func (c *LoginCommand) proofKey() (key, challenge string, err error) { // UUID spec, but our go-uuid just generates totally random number sequences // formatted in the conventional UUID syntax, so that concern does not // apply here: this is just a 128-bit crypto-random number. - key, err = uuid.GenerateUUID() + uu, err := uuid.GenerateUUID() if err != nil { return "", "", err } + key = fmt.Sprintf("%s.%09d", uu, rand.Intn(999999999)) + h := sha256.New() h.Write([]byte(key)) - challenge = base64.URLEncoding.EncodeToString(h.Sum(nil)) + challenge = base64.RawURLEncoding.EncodeToString(h.Sum(nil)) return key, challenge, nil } diff --git a/command/testdata/login-oauth-server/oauthserver.go b/command/testdata/login-oauth-server/oauthserver.go index cde3477b64..5454a1d8f6 100644 --- a/command/testdata/login-oauth-server/oauthserver.go +++ b/command/testdata/login-oauth-server/oauthserver.go @@ -125,7 +125,7 @@ func (h handler) serveToken(resp http.ResponseWriter, req *http.Request) { case "S256": h := sha256.New() h.Write([]byte(codeVerifier)) - encVerifier := base64.URLEncoding.EncodeToString(h.Sum(nil)) + encVerifier := base64.RawURLEncoding.EncodeToString(h.Sum(nil)) if codeParts[1] != encVerifier { log.Printf("/token: incorrect code verifier %q; want %q", codeParts[1], encVerifier) resp.Header().Set("Content-Type", "application/json")