/*- * Copyright 2016 Zbigniew Mandziejewicz * Copyright 2016 Square, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jwt import ( "strconv" "time" "gopkg.in/square/go-jose.v2/json" ) // Claims represents public claim values (as specified in RFC 7519). 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"` } // 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. type NumericDate int64 // NewNumericDate constructs NumericDate from time.Time value. func NewNumericDate(t time.Time) *NumericDate { if t.IsZero() { return nil } // While RFC 7519 technically states that NumericDate values may be // non-integer values, we don't bother serializing timestamps in // claims with sub-second accurancy and just round to the nearest // second instead. Not convined sub-second accuracy is useful here. out := NumericDate(t.Unix()) return &out } // MarshalJSON serializes the given NumericDate into its JSON representation. func (n NumericDate) MarshalJSON() ([]byte, error) { return []byte(strconv.FormatInt(int64(n), 10)), nil } // UnmarshalJSON reads a date from its JSON representation. func (n *NumericDate) UnmarshalJSON(b []byte) error { s := string(b) f, err := strconv.ParseFloat(s, 64) if err != nil { return ErrUnmarshalNumericDate } *n = NumericDate(f) return nil } // Time returns time.Time representation of NumericDate. func (n *NumericDate) Time() time.Time { if n == nil { return time.Time{} } return time.Unix(int64(*n), 0) } // Audience represents the recipients that the token is intended for. type Audience []string // UnmarshalJSON reads an audience from its JSON representation. func (s *Audience) UnmarshalJSON(b []byte) error { var v interface{} if err := json.Unmarshal(b, &v); err != nil { return err } switch v := v.(type) { case string: *s = []string{v} case []interface{}: a := make([]string, len(v)) for i, e := range v { s, ok := e.(string) if !ok { return ErrUnmarshalAudience } a[i] = s } *s = a default: return ErrUnmarshalAudience } return nil } func (s Audience) Contains(v string) bool { for _, a := range s { if a == v { return true } } return false }