...

Source file src/golang.org/x/oauth2/pkce.go

Documentation: golang.org/x/oauth2

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  package oauth2
     5  
     6  import (
     7  	"crypto/rand"
     8  	"crypto/sha256"
     9  	"encoding/base64"
    10  	"net/url"
    11  )
    12  
    13  const (
    14  	codeChallengeKey       = "code_challenge"
    15  	codeChallengeMethodKey = "code_challenge_method"
    16  	codeVerifierKey        = "code_verifier"
    17  )
    18  
    19  // GenerateVerifier generates a PKCE code verifier with 32 octets of randomness.
    20  // This follows recommendations in RFC 7636.
    21  //
    22  // A fresh verifier should be generated for each authorization.
    23  // S256ChallengeOption(verifier) should then be passed to Config.AuthCodeURL
    24  // (or Config.DeviceAccess) and VerifierOption(verifier) to Config.Exchange
    25  // (or Config.DeviceAccessToken).
    26  func GenerateVerifier() string {
    27  	// "RECOMMENDED that the output of a suitable random number generator be
    28  	// used to create a 32-octet sequence.  The octet sequence is then
    29  	// base64url-encoded to produce a 43-octet URL-safe string to use as the
    30  	// code verifier."
    31  	// https://datatracker.ietf.org/doc/html/rfc7636#section-4.1
    32  	data := make([]byte, 32)
    33  	if _, err := rand.Read(data); err != nil {
    34  		panic(err)
    35  	}
    36  	return base64.RawURLEncoding.EncodeToString(data)
    37  }
    38  
    39  // VerifierOption returns a PKCE code verifier AuthCodeOption. It should be
    40  // passed to Config.Exchange or Config.DeviceAccessToken only.
    41  func VerifierOption(verifier string) AuthCodeOption {
    42  	return setParam{k: codeVerifierKey, v: verifier}
    43  }
    44  
    45  // S256ChallengeFromVerifier returns a PKCE code challenge derived from verifier with method S256.
    46  //
    47  // Prefer to use S256ChallengeOption where possible.
    48  func S256ChallengeFromVerifier(verifier string) string {
    49  	sha := sha256.Sum256([]byte(verifier))
    50  	return base64.RawURLEncoding.EncodeToString(sha[:])
    51  }
    52  
    53  // S256ChallengeOption derives a PKCE code challenge derived from verifier with
    54  // method S256. It should be passed to Config.AuthCodeURL or Config.DeviceAccess
    55  // only.
    56  func S256ChallengeOption(verifier string) AuthCodeOption {
    57  	return challengeOption{
    58  		challenge_method: "S256",
    59  		challenge:        S256ChallengeFromVerifier(verifier),
    60  	}
    61  }
    62  
    63  type challengeOption struct{ challenge_method, challenge string }
    64  
    65  func (p challengeOption) setValue(m url.Values) {
    66  	m.Set(codeChallengeMethodKey, p.challenge_method)
    67  	m.Set(codeChallengeKey, p.challenge)
    68  }
    69  

View as plain text