github.com/clerkinc/clerk-sdk-go@v1.49.1/clerk/tokens_options.go (about) 1 package clerk 2 3 import ( 4 "crypto/x509" 5 "encoding/pem" 6 "fmt" 7 "strings" 8 "time" 9 10 "github.com/go-jose/go-jose/v3" 11 ) 12 13 // VerifyTokenOption describes a functional parameter for the VerifyToken method 14 type VerifyTokenOption func(*verifyTokenOptions) error 15 16 // WithAuthorizedParty allows to set the authorized parties to check against the azp claim of the session token 17 func WithAuthorizedParty(parties ...string) VerifyTokenOption { 18 return func(o *verifyTokenOptions) error { 19 authorizedParties := make(map[string]struct{}) 20 for _, party := range parties { 21 authorizedParties[party] = struct{}{} 22 } 23 24 o.authorizedParties = authorizedParties 25 return nil 26 } 27 } 28 29 // WithLeeway allows to set a custom leeway that gives some extra time to the token to accomodate for clock skew, etc. 30 func WithLeeway(leeway time.Duration) VerifyTokenOption { 31 return func(o *verifyTokenOptions) error { 32 o.leeway = leeway 33 return nil 34 } 35 } 36 37 // WithJWTVerificationKey allows to set the JWK to use for verifying tokens without the need to download or cache any JWKs at runtime 38 func WithJWTVerificationKey(key string) VerifyTokenOption { 39 return func(o *verifyTokenOptions) error { 40 // From the Clerk docs: "Note that the JWT Verification key is not in 41 // PEM format, the header and footer are missing, in order to be shorter 42 // and single-line for easier setup." 43 if !strings.HasPrefix(key, "-----BEGIN") { 44 key = "-----BEGIN PUBLIC KEY-----\n" + key + "\n-----END PUBLIC KEY-----" 45 } 46 47 jwk, err := pemToJWK(key) 48 if err != nil { 49 return err 50 } 51 52 o.jwk = jwk 53 return nil 54 } 55 } 56 57 // WithCustomClaims allows to pass a type (e.g. struct), which will be populated with the token claims based on json tags. 58 // For this option to work you must pass a pointer. 59 func WithCustomClaims(customClaims interface{}) VerifyTokenOption { 60 return func(o *verifyTokenOptions) error { 61 o.customClaims = customClaims 62 return nil 63 } 64 } 65 66 func WithSatelliteDomain(isSatellite bool) VerifyTokenOption { 67 return func(o *verifyTokenOptions) error { 68 o.isSatellite = isSatellite 69 return nil 70 } 71 } 72 73 func WithProxyURL(proxyURL string) VerifyTokenOption { 74 return func(o *verifyTokenOptions) error { 75 o.proxyURL = proxyURL 76 return nil 77 } 78 } 79 80 func pemToJWK(key string) (*jose.JSONWebKey, error) { 81 block, _ := pem.Decode([]byte(key)) 82 if block == nil { 83 return nil, fmt.Errorf("invalid PEM-encoded block") 84 } 85 86 if block.Type != "PUBLIC KEY" { 87 return nil, fmt.Errorf("invalid key type, expected a public key") 88 } 89 90 rsaPublicKey, err := x509.ParsePKIXPublicKey(block.Bytes) 91 if err != nil { 92 return nil, fmt.Errorf("failed to parse public key: %v", err) 93 } 94 95 return &jose.JSONWebKey{Key: rsaPublicKey, Algorithm: "RS256"}, nil 96 }