Documentation ¶
Overview ¶
Package jwt provides an implementation of the JSON Web Token standard.
Index ¶
Examples ¶
Constants ¶
const ( // DefaultLeeway defines the default leeway for matching NotBefore/Expiry claims. DefaultLeeway = 1.0 * time.Minute )
Variables ¶
var ErrExpired = errors.New("square/go-jose/jwt: validation failed, token is expired (exp)")
ErrExpired indicates that token is used after expiry time indicated in exp claim.
var ErrInvalidAudience = errors.New("square/go-jose/jwt: validation failed, invalid audience claim (aud)")
ErrInvalidAudience indicated invalid aud claim.
var ErrInvalidClaims = errors.New("square/go-jose/jwt: expected claims to be value convertible into JSON object")
ErrInvalidClaims indicates that given claims have invalid type.
var ErrInvalidContentType = errors.New("square/go-jose/jwt: expected content type to be JWT (cty header)")
ErrInvalidContentType indicated that token requires JWT cty header.
var ErrInvalidID = errors.New("square/go-jose/jwt: validation failed, invalid ID claim (jti)")
ErrInvalidID indicates invalid jti claim.
var ErrInvalidIssuer = errors.New("square/go-jose/jwt: validation failed, invalid issuer claim (iss)")
ErrInvalidIssuer indicates invalid iss claim.
var ErrInvalidSubject = errors.New("square/go-jose/jwt: validation failed, invalid subject claim (sub)")
ErrInvalidSubject indicates invalid sub claim.
var ErrNotValidYet = errors.New("square/go-jose/jwt: validation failed, token not valid yet (nbf)")
ErrNotValidYet indicates that token is used before time indicated in nbf claim.
var ErrUnmarshalAudience = errors.New("square/go-jose/jwt: expected string or array value to unmarshal to Audience")
ErrUnmarshalAudience indicates that aud claim could not be unmarshalled.
var ErrUnmarshalNumericDate = errors.New("square/go-jose/jwt: expected number value to unmarshal NumericDate")
ErrUnmarshalNumericDate indicates that JWT NumericDate could not be unmarshalled.
Functions ¶
This section is empty.
Types ¶
type Audience ¶
type Audience []string
Audience represents the recipents that the token is intended for.
func (*Audience) UnmarshalJSON ¶
UnmarshalJSON reads an audience from its JSON representation.
type Builder ¶
type Builder interface { // Claims encodes claims into JWE/JWS form. Multiple calls will merge claims // into single JSON object. If you are passing private claims, make sure to set // struct field tags to specify the name for the JSON key to be used when // serializing. Claims(i interface{}) Builder // Token builds a JSONWebToken from provided data. Token() (*JSONWebToken, error) // FullSerialize serializes a token using the full serialization format. FullSerialize() (string, error) // CompactSerialize serializes a token using the compact serialization format. CompactSerialize() (string, error) }
Builder is a utility for making JSON Web Tokens. Calls can be chained, and errors are accumulated until the final call to CompactSerialize/FullSerialize.
func Encrypted ¶
func Encrypted(enc jose.Encrypter) Builder
Encrypted creates builder for encrypted tokens.
Example ¶
enc, err := jose.NewEncrypter( jose.A128GCM, jose.Recipient{Algorithm: jose.DIRECT, Key: sharedEncryptionKey}, (&jose.EncrypterOptions{}).WithType("JWT"), ) if err != nil { panic(err) } cl := jwt.Claims{ Subject: "subject", Issuer: "issuer", } raw, err := jwt.Encrypted(enc).Claims(cl).CompactSerialize() if err != nil { panic(err) } fmt.Println(raw)
Output:
func Signed ¶
func Signed(sig jose.Signer) Builder
Signed creates builder for signed tokens.
Example ¶
key := []byte("secret") sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: key}, (&jose.SignerOptions{}).WithType("JWT")) if err != nil { panic(err) } cl := jwt.Claims{ Subject: "subject", Issuer: "issuer", NotBefore: jwt.NewNumericDate(time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)), Audience: jwt.Audience{"leela", "fry"}, } raw, err := jwt.Signed(sig).Claims(cl).CompactSerialize() if err != nil { panic(err) } fmt.Println(raw)
Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsibGVlbGEiLCJmcnkiXSwiaXNzIjoiaXNzdWVyIiwibmJmIjoxNDUxNjA2NDAwLCJzdWIiOiJzdWJqZWN0In0.4PgCj0VO-uG_cb1mNA38NjJyp0N-NdGIDLoYelEkciw
Example (MultipleClaims) ¶
c := &jwt.Claims{ Subject: "subject", Issuer: "issuer", } c2 := struct { Scopes []string }{ []string{"foo", "bar"}, } raw, err := jwt.Signed(signer).Claims(c).Claims(c2).CompactSerialize() if err != nil { panic(err) } fmt.Println(raw)
Output: eyJhbGciOiJIUzI1NiJ9.eyJTY29wZXMiOlsiZm9vIiwiYmFyIl0sImlzcyI6Imlzc3VlciIsInN1YiI6InN1YmplY3QifQ.esKOIsmwkudr_gnfnB4SngxIr-7pspd5XzG3PImfQ6Y
Example (PrivateClaims) ¶
key := []byte("secret") sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: key}, (&jose.SignerOptions{}).WithType("JWT")) if err != nil { panic(err) } cl := jwt.Claims{ Subject: "subject", Issuer: "issuer", NotBefore: jwt.NewNumericDate(time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)), Audience: jwt.Audience{"leela", "fry"}, } // When setting private claims, make sure to add struct tags // to specify how to serialize the field. The naming behavior // should match the encoding/json package otherwise. privateCl := struct { CustomClaim string `json:"custom"` }{ "custom claim value", } raw, err := jwt.Signed(sig).Claims(cl).Claims(privateCl).CompactSerialize() if err != nil { panic(err) } fmt.Println(raw) // Ouput: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsibGVlbGEiLCJmcnkiXSwiY3VzdG9tIjoiY3VzdG9tIGNsYWltIHZhbHVlIiwiaXNzIjoiaXNzdWVyIiwibmJmIjoxNDUxNjA2NDAwLCJzdWIiOiJzdWJqZWN0In0.knXH3ReNJToS5XI7BMCkk80ugpCup3tOy53xq-ga47o
Output:
type Claims ¶
type Claims struct { Issuer string `json:"iss,omitempty"` Subject string `json:"sub,omitempty"` Audience Audience `json:"aud,omitempty"` Expiry NumericDate `json:"exp,omitempty"` NotBefore NumericDate `json:"nbf,omitempty"` IssuedAt NumericDate `json:"iat,omitempty"` ID string `json:"jti,omitempty"` }
Claims represents public claim values (as specified in RFC 7519).
func (Claims) Validate ¶
Validate checks claims in a token against expected values. A default leeway value of one minute is used to compare time values.
Example ¶
package main import ( "fmt" "time" "gopkg.in/square/go-jose.v2/jwt" ) func main() { cl := jwt.Claims{ Subject: "subject", Issuer: "issuer", NotBefore: jwt.NewNumericDate(time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)), Expiry: jwt.NewNumericDate(time.Date(2016, 1, 1, 0, 15, 0, 0, time.UTC)), Audience: jwt.Audience{"leela", "fry"}, } err := cl.Validate(jwt.Expected{ Issuer: "issuer", Time: time.Date(2016, 1, 1, 0, 10, 0, 0, time.UTC), }) if err != nil { panic(err) } fmt.Printf("valid!") }
Output: valid!
Example (WithParse) ¶
package main import ( "fmt" "gopkg.in/square/go-jose.v2/jwt" ) var sharedKey = []byte("secret") func main() { raw := `eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3N1ZXIiLCJzdWIiOiJzdWJqZWN0In0.gpHyA1B1H6X4a4Edm9wo7D3X2v3aLSDBDG2_5BzXYe0` tok, err := jwt.ParseSigned(raw) if err != nil { panic(err) } cl := jwt.Claims{} if err := tok.Claims(sharedKey, &cl); err != nil { panic(err) } err = cl.Validate(jwt.Expected{ Issuer: "issuer", Subject: "subject", }) if err != nil { panic(err) } fmt.Printf("valid!") }
Output: valid!
func (Claims) ValidateWithLeeway ¶
ValidateWithLeeway checks claims in a token against expected values. A custom leeway may be specified for comparing time values. You may pass a zero value to check time values with no leeway, but you should not that numeric date values are rounded to the nearest second and sub-second precision is not supported.
type Expected ¶
type Expected struct { // Issuer matches the "iss" claim exactly. Issuer string // Subject matches the "sub" claim exactly. Subject string // Audience matches the values in "aud" claim, regardless of their order. Audience Audience // ID matches the "jti" claim exactly. ID string // Time matches the "exp" and "nbf" claims with leeway. Time time.Time }
Expected defines values used for protected claims validation. If field has zero value then validation is skipped.
type JSONWebToken ¶
type JSONWebToken struct { Headers []jose.Header // contains filtered or unexported fields }
JSONWebToken represents a JSON Web Token (as specified in RFC7519).
func ParseEncrypted ¶
func ParseEncrypted(s string) (*JSONWebToken, error)
ParseEncrypted parses token from JWE form.
Example ¶
package main import ( "fmt" "gopkg.in/square/go-jose.v2/jwt" ) func main() { key := []byte("itsa16bytesecret") raw := `eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..jg45D9nmr6-8awml.z-zglLlEw9MVkYHi-Znd9bSwc-oRGbqKzf9WjXqZxno.kqji2DiZHZmh-1bLF6ARPw` tok, err := jwt.ParseEncrypted(raw) if err != nil { panic(err) } out := jwt.Claims{} if err := tok.Claims(key, &out); err != nil { panic(err) } fmt.Printf("iss: %s, sub: %s\n", out.Issuer, out.Subject) }
Output: iss: issuer, sub: subject
func ParseSigned ¶
func ParseSigned(s string) (*JSONWebToken, error)
ParseSigned parses token from JWS form.
Example ¶
package main import ( "fmt" "gopkg.in/square/go-jose.v2/jwt" ) var sharedKey = []byte("secret") func main() { raw := `eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3N1ZXIiLCJzdWIiOiJzdWJqZWN0In0.gpHyA1B1H6X4a4Edm9wo7D3X2v3aLSDBDG2_5BzXYe0` tok, err := jwt.ParseSigned(raw) if err != nil { panic(err) } out := jwt.Claims{} if err := tok.Claims(sharedKey, &out); err != nil { panic(err) } fmt.Printf("iss: %s, sub: %s\n", out.Issuer, out.Subject) }
Output: iss: issuer, sub: subject
func (*JSONWebToken) Claims ¶
func (t *JSONWebToken) Claims(key interface{}, dest ...interface{}) error
Claims deserializes a JSONWebToken into dest using the provided key.
Example (Map) ¶
package main import ( "fmt" "gopkg.in/square/go-jose.v2/jwt" ) var sharedKey = []byte("secret") func main() { raw := `eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJpc3N1ZXIiLCJzdWIiOiJzdWJqZWN0In0.gpHyA1B1H6X4a4Edm9wo7D3X2v3aLSDBDG2_5BzXYe0` tok, err := jwt.ParseSigned(raw) if err != nil { panic(err) } out := make(map[string]interface{}) if err := tok.Claims(sharedKey, &out); err != nil { panic(err) } fmt.Printf("iss: %s, sub: %s\n", out["iss"], out["sub"]) }
Output: iss: issuer, sub: subject
Example (Multiple) ¶
package main import ( "fmt" "strings" "gopkg.in/square/go-jose.v2/jwt" ) var sharedKey = []byte("secret") func main() { raw := `eyJhbGciOiJIUzI1NiJ9.eyJTY29wZXMiOlsiZm9vIiwiYmFyIl0sImlzcyI6Imlzc3VlciIsInN1YiI6InN1YmplY3QifQ.esKOIsmwkudr_gnfnB4SngxIr-7pspd5XzG3PImfQ6Y` tok, err := jwt.ParseSigned(raw) if err != nil { panic(err) } out := jwt.Claims{} out2 := struct { Scopes []string }{} if err := tok.Claims(sharedKey, &out, &out2); err != nil { panic(err) } fmt.Printf("iss: %s, sub: %s, scopes: %s\n", out.Issuer, out.Subject, strings.Join(out2.Scopes, ",")) }
Output: iss: issuer, sub: subject, scopes: foo,bar
func (*JSONWebToken) UnsafeClaimsWithoutVerification ¶
func (t *JSONWebToken) UnsafeClaimsWithoutVerification(dest ...interface{}) error
UnsafeClaimsWithoutVerification deserializes the claims of a JSONWebToken into the dests. For signed JWTs, the claims are not verified. This function won't work for encrypted JWTs.
type NestedBuilder ¶
type NestedBuilder interface { // Claims encodes claims into JWE/JWS form. Multiple calls will merge claims // into single JSON object. If you are passing private claims, make sure to set // struct field tags to specify the name for the JSON key to be used when // serializing. Claims(i interface{}) NestedBuilder // Token builds a NestedJSONWebToken from provided data. Token() (*NestedJSONWebToken, error) // FullSerialize serializes a token using the full serialization format. FullSerialize() (string, error) // CompactSerialize serializes a token using the compact serialization format. CompactSerialize() (string, error) }
NestedBuilder is a utility for making Signed-Then-Encrypted JSON Web Tokens. Calls can be chained, and errors are accumulated until final call to CompactSerialize/FullSerialize.
func SignedAndEncrypted ¶
func SignedAndEncrypted(sig jose.Signer, enc jose.Encrypter) NestedBuilder
SignedAndEncrypted creates builder for signed-then-encrypted tokens. ErrInvalidContentType will be returned if encrypter doesn't have JWT content type.
Example ¶
enc, err := jose.NewEncrypter( jose.A128GCM, jose.Recipient{ Algorithm: jose.DIRECT, Key: sharedEncryptionKey, }, (&jose.EncrypterOptions{}).WithType("JWT").WithContentType("JWT")) if err != nil { panic(err) } cl := jwt.Claims{ Subject: "subject", Issuer: "issuer", } raw, err := jwt.SignedAndEncrypted(rsaSigner, enc).Claims(cl).CompactSerialize() if err != nil { panic(err) } fmt.Println(raw)
Output:
type NestedJSONWebToken ¶
type NestedJSONWebToken struct { Headers []jose.Header // contains filtered or unexported fields }
func ParseSignedAndEncrypted ¶
func ParseSignedAndEncrypted(s string) (*NestedJSONWebToken, error)
ParseSignedAndEncrypted parses signed-then-encrypted token from JWE form.
Example ¶
package main import ( "fmt" "crypto/rsa" "crypto/x509" "encoding/pem" "gopkg.in/square/go-jose.v2/jwt" ) var sharedEncryptionKey = []byte("itsa16bytesecret") func main() { raw := `eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIiwiY3R5IjoiSldUIn0..-keV-9YpsxotBEHw.yC9SHWgnkjykgJqXZGlzYC5Wg_EdWKO5TgfqeqsWWJYw7fX9zXQE3NtXmA3nAiUrYOr3H2s0AgTeAhTNbELLEHQu0blfRaPa_uKOAgFgmhJwbGe2iFLn9J0U72wk56318nI-pTLCV8FijoGpXvAxQlaKrPLKkl9yDQimPhb7UiDwLWYkJeoayciAXhR5f40E8ORGjCz8oawXRvjDaSjgRElUwy4kMGzvJy_difemEh4lfMSIwUNVEqJkEYaalRttSymMYuV6NvBVU0N0Jb6omdM4tW961OySB4KPWCWH9UJUX0XSEcqbW9WLxpg3ftx5R7xNiCnaVaCx_gJZfXJ9yFLqztIrKh2N05zHM0tddSOwCOnq7_1rJtaVz0nTXjSjf1RrVaxJya59p3K-e41QutiGFiJGzXG-L2OyLETIaVSU3ptvaCz4IxCF3GzeCvOgaICvXkpBY1-bv-fk1ilyjmcTDnLp2KivWIxcnoQmpN9xj06ZjagdG09AHUhS5WixADAg8mIdGcanNblALecnCWG-otjM9Kw.RZoaHtSgnzOin2od3D9tnA` tok, err := jwt.ParseSignedAndEncrypted(raw) if err != nil { panic(err) } nested, err := tok.Decrypt(sharedEncryptionKey) if err != nil { panic(err) } out := jwt.Claims{} if err := nested.Claims(&rsaPrivKey.PublicKey, &out); err != nil { panic(err) } fmt.Printf("iss: %s, sub: %s\n", out.Issuer, out.Subject) } func mustUnmarshalRSA(data string) *rsa.PrivateKey { block, _ := pem.Decode([]byte(data)) if block == nil { panic("failed to decode PEM data") } key, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { panic("failed to parse RSA key: " + err.Error()) } if key, ok := key.(*rsa.PrivateKey); ok { return key } panic("key is not of type *rsa.PrivateKey") } var rsaPrivKey = mustUnmarshalRSA(`-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDIHBvDHAr7jh8h xaqBCl11fjI9YZtdC5b3HtXTXZW3c2dIOImNUjffT8POP6p5OpzivmC1om7iOyuZ 3nJjC9LT3zqqs3f2i5d4mImxEuqG6uWdryFfkp0uIv5VkjVO+iQWd6pDAPGP7r1Z foXCleyCtmyNH4JSkJneNPOk/4BxO8vcvRnCMT/Gv81IT6H+OQ6OovWOuJr8RX9t 1wuCjC9ezZxeI9ONffhiO5FMrVh5H9LJTl3dPOVa4aEcOvgd45hBmvxAyXqf8daE 6Kl2O7vQ4uwgnSTVXYIIjCjbepuersApIMGx/XPSgiU1K3Xtah/TBvep+S3VlwPc q/QH25S9AgMBAAECggEAe+y8XKYfPw4SxY1uPB+5JSwT3ON3nbWxtjSIYy9Pqp5z Vcx9kuFZ7JevQSk4X38m7VzM8282kC/ono+d8yy9Uayq3k/qeOqV0X9Vti1qxEbw ECkG1/MqGApfy4qSLOjINInDDV+mOWa2KJgsKgdCwuhKbVMYGB2ozG2qfYIlfvlY vLcBEpGWmswJHNmkcjTtGFIyJgPbsI6ndkkOeQbqQKAaadXtG1xUzH+vIvqaUl/l AkNf+p4qhPkHsoAWXf1qu9cYa2T8T+mEo79AwlgVC6awXQWNRTiyClDJC7cu6NBy ZHXCLFMbalzWF9qeI2OPaFX2x3IBWrbyDxcJ4TSdQQKBgQD/Fp/uQonMBh1h4Vi4 HlxZdqSOArTitXValdLFGVJ23MngTGV/St4WH6eRp4ICfPyldsfcv6MZpNwNm1Rn lB5Gtpqpby1dsrOSfvVbY7U3vpLnd8+hJ/lT5zCYt5Eor46N6iWRkYWzNe4PixiF z1puGUvFCbZdeeACVrPLmW3JKQKBgQDI0y9WTf8ezKPbtap4UEE6yBf49ftohVGz p4iD6Ng1uqePwKahwoVXKOc179CjGGtW/UUBORAoKRmxdHajHq6LJgsBxpaARz21 COPy99BUyp9ER5P8vYn63lC7Cpd/K7uyMjaz1DAzYBZIeVZHIw8O9wuGNJKjRFy9 SZyD3V0ddQKBgFMdohrWH2QVEfnUnT3Q1rJn0BJdm2bLTWOosbZ7G72TD0xAWEnz sQ1wXv88n0YER6X6YADziEdQykq8s/HT91F/KkHO8e83zP8M0xFmGaQCOoelKEgQ aFMIX3NDTM7+9OoUwwz9Z50PE3SJFAJ1n7eEEoYvNfabQXxBl+/dHEKRAoGAPEvU EaiXacrtg8EWrssB2sFLGU/ZrTciIbuybFCT4gXp22pvXXAHEvVP/kzDqsRhLhwb BNP6OuSkNziNikpjA5pngZ/7fgZly54gusmW/m5bxWdsUl0iOXVYbeAvPlqGH2me LP4Pfs1hw17S/cbT9Z1NE31jbavP4HFikeD73SUCgYEArQfuudml6ei7XZ1Emjq8 jZiD+fX6e6BD/ISatVnuyZmGj9wPFsEhY2BpLiAMQHMDIvH9nlKzsFvjkTPB86qG jCh3D67Os8eSBk5uRC6iW3Fc4DXvB5EFS0W9/15Sl+V5vXAcrNMpYS82OTSMG2Gt b9Ym/nxaqyTu0PxajXkKm5Q= -----END PRIVATE KEY-----`)
Output: iss: issuer, sub: subject
func (*NestedJSONWebToken) Decrypt ¶
func (t *NestedJSONWebToken) Decrypt(decryptionKey interface{}) (*JSONWebToken, error)
type NumericDate ¶
type NumericDate int64
NumericDate represents date and time as the number of seconds since the epoch, including leap seconds. Non-integer values can be represented in the serialized format, but we round to the nearest second.
func NewNumericDate ¶
func NewNumericDate(t time.Time) NumericDate
NewNumericDate constructs NumericDate from time.Time value.
func (NumericDate) MarshalJSON ¶
func (n NumericDate) MarshalJSON() ([]byte, error)
MarshalJSON serializes the given NumericDate into its JSON representation.
func (NumericDate) Time ¶
func (n NumericDate) Time() time.Time
Time returns time.Time representation of NumericDate.
func (*NumericDate) UnmarshalJSON ¶
func (n *NumericDate) UnmarshalJSON(b []byte) error
UnmarshalJSON reads a date from its JSON representation.