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 323dd7802..586e9414c 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 cde3477b6..5454a1d8f 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")