You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

token.go 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package jwt
  2. import (
  3. "crypto"
  4. "encoding/base64"
  5. "encoding/json"
  6. )
  7. // Keyfunc will be used by the Parse methods as a callback function to supply
  8. // the key for verification. The function receives the parsed, but unverified
  9. // Token. This allows you to use properties in the Header of the token (such as
  10. // `kid`) to identify which key to use.
  11. //
  12. // The returned interface{} may be a single key or a VerificationKeySet containing
  13. // multiple keys.
  14. type Keyfunc func(*Token) (interface{}, error)
  15. // VerificationKey represents a public or secret key for verifying a token's signature.
  16. type VerificationKey interface {
  17. crypto.PublicKey | []uint8
  18. }
  19. // VerificationKeySet is a set of public or secret keys. It is used by the parser to verify a token.
  20. type VerificationKeySet struct {
  21. Keys []VerificationKey
  22. }
  23. // Token represents a JWT Token. Different fields will be used depending on
  24. // whether you're creating or parsing/verifying a token.
  25. type Token struct {
  26. Raw string // Raw contains the raw token. Populated when you [Parse] a token
  27. Method SigningMethod // Method is the signing method used or to be used
  28. Header map[string]interface{} // Header is the first segment of the token in decoded form
  29. Claims Claims // Claims is the second segment of the token in decoded form
  30. Signature []byte // Signature is the third segment of the token in decoded form. Populated when you Parse a token
  31. Valid bool // Valid specifies if the token is valid. Populated when you Parse/Verify a token
  32. }
  33. // New creates a new [Token] with the specified signing method and an empty map
  34. // of claims. Additional options can be specified, but are currently unused.
  35. func New(method SigningMethod, opts ...TokenOption) *Token {
  36. return NewWithClaims(method, MapClaims{}, opts...)
  37. }
  38. // NewWithClaims creates a new [Token] with the specified signing method and
  39. // claims. Additional options can be specified, but are currently unused.
  40. func NewWithClaims(method SigningMethod, claims Claims, opts ...TokenOption) *Token {
  41. return &Token{
  42. Header: map[string]interface{}{
  43. "typ": "JWT",
  44. "alg": method.Alg(),
  45. },
  46. Claims: claims,
  47. Method: method,
  48. }
  49. }
  50. // SignedString creates and returns a complete, signed JWT. The token is signed
  51. // using the SigningMethod specified in the token. Please refer to
  52. // https://golang-jwt.github.io/jwt/usage/signing_methods/#signing-methods-and-key-types
  53. // for an overview of the different signing methods and their respective key
  54. // types.
  55. func (t *Token) SignedString(key interface{}) (string, error) {
  56. sstr, err := t.SigningString()
  57. if err != nil {
  58. return "", err
  59. }
  60. sig, err := t.Method.Sign(sstr, key)
  61. if err != nil {
  62. return "", err
  63. }
  64. return sstr + "." + t.EncodeSegment(sig), nil
  65. }
  66. // SigningString generates the signing string. This is the most expensive part
  67. // of the whole deal. Unless you need this for something special, just go
  68. // straight for the SignedString.
  69. func (t *Token) SigningString() (string, error) {
  70. h, err := json.Marshal(t.Header)
  71. if err != nil {
  72. return "", err
  73. }
  74. c, err := json.Marshal(t.Claims)
  75. if err != nil {
  76. return "", err
  77. }
  78. return t.EncodeSegment(h) + "." + t.EncodeSegment(c), nil
  79. }
  80. // EncodeSegment encodes a JWT specific base64url encoding with padding
  81. // stripped. In the future, this function might take into account a
  82. // [TokenOption]. Therefore, this function exists as a method of [Token], rather
  83. // than a global function.
  84. func (*Token) EncodeSegment(seg []byte) string {
  85. return base64.RawURLEncoding.EncodeToString(seg)
  86. }