package jws import ( "net/http" "time" "github.com/SermoDigital/jose" "github.com/SermoDigital/jose/crypto" "github.com/SermoDigital/jose/jwt" ) // NewJWT creates a new JWT with the given claims. func NewJWT(claims Claims, method crypto.SigningMethod) jwt.JWT { j, ok := New(claims, method).(*jws) if !ok { panic("jws.NewJWT: runtime panic: New(...).(*jws) != true") } j.sb[0].protected.Set("typ", "JWT") j.isJWT = true return j } // Serialize helps implements jwt.JWT. func (j *jws) Serialize(key interface{}) ([]byte, error) { if j.isJWT { return j.Compact(key) } return nil, ErrIsNotJWT } // Claims helps implements jwt.JWT. func (j *jws) Claims() jwt.Claims { if j.isJWT { if c, ok := j.payload.v.(Claims); ok { return jwt.Claims(c) } } return nil } // ParseJWTFromRequest tries to find the JWT in an http.Request. // This method will call ParseMultipartForm if there's no token in the header. func ParseJWTFromRequest(req *http.Request) (jwt.JWT, error) { if b, ok := fromHeader(req); ok { return ParseJWT(b) } if b, ok := fromForm(req); ok { return ParseJWT(b) } return nil, ErrNoTokenInRequest } // ParseJWT parses a serialized jwt.JWT into a physical jwt.JWT. // If its payload isn't a set of claims (or able to be coerced into // a set of claims) it'll return an error stating the // JWT isn't a JWT. func ParseJWT(encoded []byte) (jwt.JWT, error) { t, err := parseCompact(encoded, true) if err != nil { return nil, err } c, ok := t.Payload().(map[string]interface{}) if !ok { return nil, ErrIsNotJWT } t.SetPayload(Claims(c)) return t, nil } // IsJWT returns true if the JWS is a JWT. func (j *jws) IsJWT() bool { return j.isJWT } func (j *jws) Validate(key interface{}, m crypto.SigningMethod, v ...*jwt.Validator) error { if j.isJWT { if err := j.Verify(key, m); err != nil { return err } var v1 jwt.Validator if len(v) > 0 { v1 = *v[0] } c, ok := j.payload.v.(Claims) if ok { if err := v1.Validate(j); err != nil { return err } return jwt.Claims(c).Validate(jose.Now(), v1.EXP, v1.NBF) } } return ErrIsNotJWT } // Conv converts a func(Claims) error to type jwt.ValidateFunc. func Conv(fn func(Claims) error) jwt.ValidateFunc { if fn == nil { return nil } return func(c jwt.Claims) error { return fn(Claims(c)) } } // NewValidator returns a jwt.Validator. func NewValidator(c Claims, exp, nbf time.Duration, fn func(Claims) error) *jwt.Validator { return &jwt.Validator{ Expected: jwt.Claims(c), EXP: exp, NBF: nbf, Fn: Conv(fn), } } var _ jwt.JWT = (*jws)(nil)