diff --git a/authhandler/authhandler.go b/authhandler/authhandler.go index bc86531..9bc6cd7 100644 --- a/authhandler/authhandler.go +++ b/authhandler/authhandler.go @@ -24,9 +24,9 @@ const ( // PKCEParams holds parameters to support PKCE. type PKCEParams struct { - CodeChallenge string // The unpadded, base64-url-encoded string of the encrypted codeVerifier. - CodeChallengeMethod string // The encryption method (ex. S256). - CodeVerifier string // The original, non-encrypted secret. + Challenge string // The unpadded, base64-url-encoded string of the encrypted code verifier. + ChallengeMethod string // The encryption method (ex. S256). + Verifier string // The original, non-encrypted secret. } // AuthorizationHandler is a 3-legged-OAuth helper that prompts @@ -34,6 +34,15 @@ type PKCEParams struct { // and returns an auth code and state upon approval. type AuthorizationHandler func(authCodeURL string) (code string, state string, err error) +// TokenSourceWithPKCE is an enhanced version of TokenSource with PKCE support. +// +// The pkce parameter supports PKCE flow, which uses code challenge and code verifier +// to prevent CSRF attacks. A unique code challenge and code verifier should be generated +// by the caller at runtime. See https://www.oauth.com/oauth2-servers/pkce/ for more info. +func TokenSourceWithPKCE(ctx context.Context, config *oauth2.Config, state string, authHandler AuthorizationHandler, pkce *PKCEParams) oauth2.TokenSource { + return oauth2.ReuseTokenSource(nil, authHandlerSource{config: config, ctx: ctx, authHandler: authHandler, state: state, pkce: pkce}) +} + // TokenSource returns an oauth2.TokenSource that fetches access tokens // using 3-legged-OAuth flow. // @@ -48,14 +57,6 @@ type AuthorizationHandler func(authCodeURL string) (code string, state string, e // This token source will verify that the "state" is identical in the request // and response before exchanging the auth code for OAuth token to prevent CSRF // attacks. -// -// The pkce parameter supports PKCE flow. -// See https://www.oauth.com/oauth2-servers/pkce/ for more info. -func TokenSourceWithPKCE(ctx context.Context, config *oauth2.Config, state string, authHandler AuthorizationHandler, pkce *PKCEParams) oauth2.TokenSource { - return oauth2.ReuseTokenSource(nil, authHandlerSource{config: config, ctx: ctx, authHandler: authHandler, state: state, pkce: pkce}) -} - -// Deprecated: Use TokenSourceWithPKCE instead. func TokenSource(ctx context.Context, config *oauth2.Config, state string, authHandler AuthorizationHandler) oauth2.TokenSource { return TokenSourceWithPKCE(ctx, config, state, authHandler, nil) } @@ -71,9 +72,9 @@ type authHandlerSource struct { func (source authHandlerSource) Token() (*oauth2.Token, error) { // Step 1: Obtain auth code. var authCodeUrlOptions []oauth2.AuthCodeOption - if source.pkce != nil { - authCodeUrlOptions = []oauth2.AuthCodeOption{oauth2.SetAuthURLParam(codeChallengeKey, source.pkce.CodeChallenge), - oauth2.SetAuthURLParam(codeChallengeMethodKey, source.pkce.CodeChallengeMethod)} + if source.pkce != nil && source.pkce.Challenge != "" && source.pkce.ChallengeMethod != "" { + authCodeUrlOptions = []oauth2.AuthCodeOption{oauth2.SetAuthURLParam(codeChallengeKey, source.pkce.Challenge), + oauth2.SetAuthURLParam(codeChallengeMethodKey, source.pkce.ChallengeMethod)} } url := source.config.AuthCodeURL(source.state, authCodeUrlOptions...) code, state, err := source.authHandler(url) @@ -86,8 +87,8 @@ func (source authHandlerSource) Token() (*oauth2.Token, error) { // Step 2: Exchange auth code for access token. var exchangeOptions []oauth2.AuthCodeOption - if source.pkce != nil { - exchangeOptions = []oauth2.AuthCodeOption{oauth2.SetAuthURLParam(codeVerifierKey, source.pkce.CodeVerifier)} + if source.pkce != nil && source.pkce.Verifier != "" { + exchangeOptions = []oauth2.AuthCodeOption{oauth2.SetAuthURLParam(codeVerifierKey, source.pkce.Verifier)} } return source.config.Exchange(source.ctx, code, exchangeOptions...) } diff --git a/authhandler/authhandler_test.go b/authhandler/authhandler_test.go index 0e50e15..ad19804 100644 --- a/authhandler/authhandler_test.go +++ b/authhandler/authhandler_test.go @@ -129,9 +129,9 @@ func TestTokenExchangeWithPKCE_Success(t *testing.T) { }, } pkce := PKCEParams{ - CodeChallenge: "codeChallenge", - CodeChallengeMethod: "plain", - CodeVerifier: "codeChallenge", + Challenge: "codeChallenge", + ChallengeMethod: "plain", + Verifier: "codeChallenge", } tok, err := TokenSourceWithPKCE(context.Background(), conf, "testState", authhandler, &pkce).Token()