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("go-jose/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("go-jose/go-jose/jwt: validation failed, invalid audience claim (aud)")
ErrInvalidAudience indicated invalid aud claim.
var ErrInvalidClaims = errors.New("go-jose/go-jose/jwt: expected claims to be value convertible into JSON object")
ErrInvalidClaims indicates that given claims have invalid type.
var ErrInvalidContentType = errors.New("go-jose/go-jose/jwt: expected content type to be JWT (cty header)")
ErrInvalidContentType indicates that token requires JWT cty header.
var ErrInvalidID = errors.New("go-jose/go-jose/jwt: validation failed, invalid ID claim (jti)")
ErrInvalidID indicates invalid jti claim.
var ErrInvalidIssuer = errors.New("go-jose/go-jose/jwt: validation failed, invalid issuer claim (iss)")
ErrInvalidIssuer indicates invalid iss claim.
var ErrInvalidSubject = errors.New("go-jose/go-jose/jwt: validation failed, invalid subject claim (sub)")
ErrInvalidSubject indicates invalid sub claim.
var ErrIssuedInTheFuture = errors.New("go-jose/go-jose/jwt: validation field, token issued in the future (iat)")
ErrIssuedInTheFuture indicates that the iat field is in the future.
var ErrNotValidYet = errors.New("go-jose/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("go-jose/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("go-jose/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 recipients that the token is intended for.
func (Audience) MarshalJSON ¶
MarshalJSON converts audience to json representation.
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) // Serialize serializes a token. Serialize() (string, error) }
Builder is a utility for making JSON Web Tokens. Calls can be chained, and errors are accumulated until the final call to Serialize.
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 { fmt.Printf("making encrypter: %s\n", err) return } cl := jwt.Claims{ Subject: "subject", Issuer: "issuer", } raw, err := jwt.Encrypted(enc).Claims(cl).Serialize() if err != nil { fmt.Printf("encrypting JWT: %s\n", err) return } fmt.Println(raw)
Output:
func Signed ¶
func Signed(sig jose.Signer) Builder
Signed creates builder for signed tokens.
Example ¶
key := []byte("0102030405060708090A0B0C0D0E0F10") sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: key}, (&jose.SignerOptions{}).WithType("JWT")) if err != nil { fmt.Printf("making signer: %s\n", err) return } 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).Serialize() if err != nil { fmt.Printf("signing JWT: %s\n", err) return } fmt.Println(raw)
Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsibGVlbGEiLCJmcnkiXSwiaXNzIjoiaXNzdWVyIiwibmJmIjoxNDUxNjA2NDAwLCJzdWIiOiJzdWJqZWN0In0.qEmW0Ehle1yO9XE7xZooC3AUVDF2NnJFDSgn4_6QzUo
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).Serialize() if err != nil { fmt.Printf("validating claims: %s\n", err) return } fmt.Println(raw)
Output: eyJhbGciOiJIUzI1NiJ9.eyJTY29wZXMiOlsiZm9vIiwiYmFyIl0sImlzcyI6Imlzc3VlciIsInN1YiI6InN1YmplY3QifQ.9VjIUvZ8VPFg1mMPq0kTbN7CpVOfn-WChY9RAVu-I6o
Example (PrivateClaims) ¶
key := []byte("0102030405060708090A0B0C0D0E0F10") sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: key}, (&jose.SignerOptions{}).WithType("JWT")) if err != nil { fmt.Printf("making signer: %s\n", err) return } 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).Serialize() if err != nil { fmt.Printf("signing JWT: %s\n", err) return } fmt.Println(raw)
Output: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsibGVlbGEiLCJmcnkiXSwiY3VzdG9tIjoiY3VzdG9tIGNsYWltIHZhbHVlIiwiaXNzIjoiaXNzdWVyIiwibmJmIjoxNDUxNjA2NDAwLCJzdWIiOiJzdWJqZWN0In0.m6GDh-23MdwYKmzGHuWLMUcx874cGbyMG7nv-5J1ifk
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.
The default leeway will cause the token to be deemed valid until one minute after the expiration time. If you're a server application that wants to give an extra minute to client tokens, use this function. If you're a client application wondering if the server will accept your token, use ValidateWithLeeway with a leeway <=0, otherwise this function might make you think a token is valid when it is not.
Example ¶
package main import ( "fmt" "time" "github.com/simontol/go-jose/v4/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 { fmt.Printf("validating claims: %s\n", err) return } fmt.Printf("valid!") }
Output: valid!
Example (WithParse) ¶
raw := `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJpc3N1ZXIiLCJzdWIiOiJzdWJqZWN0In0.OFD0iVfPczqWBA_TRi1jGB5PF699eekcHt4D6qNoimc` tok, err := jwt.ParseSigned(raw, []jose.SignatureAlgorithm{jose.HS256}) if err != nil { fmt.Printf("parsing JWT: %s\n", err) return } cl := jwt.Claims{} if err := tok.Claims(sharedKey, &cl); err != nil { fmt.Printf("validating claims: %s\n", err) return } err = cl.Validate(jwt.Expected{ Issuer: "issuer", Subject: "subject", }) if err != nil { fmt.Printf("validating claims: %s\n", err) return } 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 note that numeric date values are rounded to the nearest second and sub-second precision is not supported.
The leeway gives some extra time to the token from the server's point of view. That is, if the token is expired, ValidateWithLeeway will still accept the token for 'leeway' amount of time. This fails if you're using this function to check if a server will accept your token, because it will think the token is valid even after it expires. So if you're a client validating if the token is valid to be submitted to a server, use leeway <=0, if you're a server validation a token, use leeway >=0.
type Expected ¶
type Expected struct { // Issuer matches the "iss" claim exactly. Issuer string // Subject matches the "sub" claim exactly. Subject string // AnyAudience matches if there is a non-empty intersection between // its values and the values in the "aud" claim. AnyAudience Audience // ID matches the "jti" claim exactly. ID string // Time matches the "exp", "nbf" and "iat" claims with leeway. Time time.Time }
Expected defines values used for protected claims validation. If field has zero value then validation is skipped, with the exception of Time, where the zero value means "now." To skip validating them, set the corresponding field in the Claims struct to nil.
type JSONWebToken ¶
JSONWebToken represents a JSON Web Token (as specified in RFC7519).
func ParseEncrypted ¶
func ParseEncrypted(s string, keyAlgorithms []jose.KeyAlgorithm, contentEncryption []jose.ContentEncryption, ) (*JSONWebToken, error)
ParseEncrypted parses token from JWE form.
The keyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc" header parameters respectively. They must be nonempty, and each "alg" or "enc" header in parsed data must contain a value that is present in the corresponding parameter. That includes the protected and unprotected headers as well as all recipients. To accept multiple algorithms, pass a slice of all the algorithms you want to accept.
Example ¶
key := []byte("itsa16bytesecret") raw := `eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIn0..jg45D9nmr6-8awml.z-zglLlEw9MVkYHi-Znd9bSwc-oRGbqKzf9WjXqZxno.kqji2DiZHZmh-1bLF6ARPw` tok, err := jwt.ParseEncrypted(raw, []jose.KeyAlgorithm{jose.DIRECT}, []jose.ContentEncryption{jose.A128GCM}) if err != nil { fmt.Printf("parsing JWT: %s\n", err) return } out := jwt.Claims{} if err := tok.Claims(key, &out); err != nil { fmt.Printf("validating claims: %s\n", err) return } fmt.Printf("iss: %s, sub: %s\n", out.Issuer, out.Subject)
Output: iss: issuer, sub: subject
func ParseSigned ¶
func ParseSigned(s string, signatureAlgorithms []jose.SignatureAlgorithm) (*JSONWebToken, error)
ParseSigned parses token from JWS form.
Example ¶
raw := `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJpc3N1ZXIiLCJzdWIiOiJzdWJqZWN0In0.OFD0iVfPczqWBA_TRi1jGB5PF699eekcHt4D6qNoimc` tok, err := jwt.ParseSigned(raw, []jose.SignatureAlgorithm{jose.HS256}) if err != nil { fmt.Printf("parsing JWT: %s\n", err) return } out := jwt.Claims{} if err := tok.Claims(sharedKey, &out); err != nil { fmt.Printf("validating claims: %s\n", err) return } 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) ¶
raw := `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJpc3N1ZXIiLCJzdWIiOiJzdWJqZWN0In0.OFD0iVfPczqWBA_TRi1jGB5PF699eekcHt4D6qNoimc` tok, err := jwt.ParseSigned(raw, []jose.SignatureAlgorithm{jose.HS256}) if err != nil { fmt.Printf("parsing JWT: %s\n", err) return } out := make(map[string]interface{}) if err := tok.Claims(sharedKey, &out); err != nil { fmt.Printf("validating claims: %s\n", err) return } fmt.Printf("iss: %s, sub: %s\n", out["iss"], out["sub"])
Output: iss: issuer, sub: subject
Example (Multiple) ¶
raw := `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJpc3N1ZXIiLCJzY29wZXMiOlsiczEiLCJzMiJdLCJzdWIiOiJzdWJqZWN0In0.O9XxAYZsxXxWpTftO75vLpyYZ1g7FHxBvyvctGg3Ih0` tok, err := jwt.ParseSigned(raw, []jose.SignatureAlgorithm{jose.HS256}) if err != nil { fmt.Printf("parsing JWT: %s\n", err) return } out := jwt.Claims{} out2 := struct { Scopes []string `json:"scopes"` }{} if err := tok.Claims(sharedKey, &out, &out2); err != nil { fmt.Printf("validating claims: %s\n", err) return } fmt.Printf("iss: %s, sub: %s, scopes: %s\n", out.Issuer, out.Subject, strings.Join(out2.Scopes, ","))
Output: iss: issuer, sub: subject, scopes: s1,s2
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) // Serialize serializes a token. Serialize() (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 Serialize.
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 { fmt.Printf("making encrypter: %s\n", err) return } cl := jwt.Claims{ Subject: "subject", Issuer: "issuer", } raw, err := jwt.SignedAndEncrypted(rsaSigner, enc).Claims(cl).Serialize() if err != nil { fmt.Printf("encrypting and signing JWT: %s\n", err) return } fmt.Println(raw)
Output:
type NestedJSONWebToken ¶
func ParseSignedAndEncrypted ¶
func ParseSignedAndEncrypted(s string, encryptionKeyAlgorithms []jose.KeyAlgorithm, contentEncryption []jose.ContentEncryption, signatureAlgorithms []jose.SignatureAlgorithm, ) (*NestedJSONWebToken, error)
ParseSignedAndEncrypted parses signed-then-encrypted token from JWE form.
The encryptionKeyAlgorithms and contentEncryption parameters are used to validate the "alg" and "enc" header parameters, respectively, of the outer JWE. They must be nonempty, and each "alg" or "enc" header in parsed data must contain a value that is present in the corresponding parameter. That includes the protected and unprotected headers as well as all recipients. To accept multiple algorithms, pass a slice of all the algorithms you want to accept.
The signatureAlgorithms parameter is used to validate the "alg" header parameter of the inner JWS. It must be nonempty, and the "alg" header in the inner JWS must contain a value that is present in the parameter.
Example ¶
raw := `eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4R0NNIiwiY3R5IjoiSldUIn0..-keV-9YpsxotBEHw.yC9SHWgnkjykgJqXZGlzYC5Wg_EdWKO5TgfqeqsWWJYw7fX9zXQE3NtXmA3nAiUrYOr3H2s0AgTeAhTNbELLEHQu0blfRaPa_uKOAgFgmhJwbGe2iFLn9J0U72wk56318nI-pTLCV8FijoGpXvAxQlaKrPLKkl9yDQimPhb7UiDwLWYkJeoayciAXhR5f40E8ORGjCz8oawXRvjDaSjgRElUwy4kMGzvJy_difemEh4lfMSIwUNVEqJkEYaalRttSymMYuV6NvBVU0N0Jb6omdM4tW961OySB4KPWCWH9UJUX0XSEcqbW9WLxpg3ftx5R7xNiCnaVaCx_gJZfXJ9yFLqztIrKh2N05zHM0tddSOwCOnq7_1rJtaVz0nTXjSjf1RrVaxJya59p3K-e41QutiGFiJGzXG-L2OyLETIaVSU3ptvaCz4IxCF3GzeCvOgaICvXkpBY1-bv-fk1ilyjmcTDnLp2KivWIxcnoQmpN9xj06ZjagdG09AHUhS5WixADAg8mIdGcanNblALecnCWG-otjM9Kw.RZoaHtSgnzOin2od3D9tnA` tok, err := jwt.ParseSignedAndEncrypted(raw, []jose.KeyAlgorithm{jose.DIRECT}, []jose.ContentEncryption{jose.A128GCM}, []jose.SignatureAlgorithm{jose.RS256}) if err != nil { fmt.Printf("validating claims: %s\n", err) return } nested, err := tok.Decrypt(sharedEncryptionKey) if err != nil { fmt.Printf("decrypting JWT: %s\n", err) return } out := jwt.Claims{} if err := nested.Claims(&rsaPrivKey.PublicKey, &out); err != nil { fmt.Printf("validating claims: %s\n", err) return } fmt.Printf("iss: %s, sub: %s\n", out.Issuer, out.Subject)
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, ignoring leap seconds. Non-integer values can be represented in the serialized format, but we round to the nearest second. See RFC7519 Section 2: https://tools.ietf.org/html/rfc7519#section-2
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.