map_claims.go

  1package jwt
  2
  3import (
  4	"encoding/json"
  5	"fmt"
  6)
  7
  8// MapClaims is a claims type that uses the map[string]interface{} for JSON
  9// decoding. This is the default claims type if you don't supply one
 10type MapClaims map[string]interface{}
 11
 12// GetExpirationTime implements the Claims interface.
 13func (m MapClaims) GetExpirationTime() (*NumericDate, error) {
 14	return m.parseNumericDate("exp")
 15}
 16
 17// GetNotBefore implements the Claims interface.
 18func (m MapClaims) GetNotBefore() (*NumericDate, error) {
 19	return m.parseNumericDate("nbf")
 20}
 21
 22// GetIssuedAt implements the Claims interface.
 23func (m MapClaims) GetIssuedAt() (*NumericDate, error) {
 24	return m.parseNumericDate("iat")
 25}
 26
 27// GetAudience implements the Claims interface.
 28func (m MapClaims) GetAudience() (ClaimStrings, error) {
 29	return m.parseClaimsString("aud")
 30}
 31
 32// GetIssuer implements the Claims interface.
 33func (m MapClaims) GetIssuer() (string, error) {
 34	return m.parseString("iss")
 35}
 36
 37// GetSubject implements the Claims interface.
 38func (m MapClaims) GetSubject() (string, error) {
 39	return m.parseString("sub")
 40}
 41
 42// parseNumericDate tries to parse a key in the map claims type as a number
 43// date. This will succeed, if the underlying type is either a [float64] or a
 44// [json.Number]. Otherwise, nil will be returned.
 45func (m MapClaims) parseNumericDate(key string) (*NumericDate, error) {
 46	v, ok := m[key]
 47	if !ok {
 48		return nil, nil
 49	}
 50
 51	switch exp := v.(type) {
 52	case float64:
 53		if exp == 0 {
 54			return nil, nil
 55		}
 56
 57		return newNumericDateFromSeconds(exp), nil
 58	case json.Number:
 59		v, _ := exp.Float64()
 60
 61		return newNumericDateFromSeconds(v), nil
 62	}
 63
 64	return nil, newError(fmt.Sprintf("%s is invalid", key), ErrInvalidType)
 65}
 66
 67// parseClaimsString tries to parse a key in the map claims type as a
 68// [ClaimsStrings] type, which can either be a string or an array of string.
 69func (m MapClaims) parseClaimsString(key string) (ClaimStrings, error) {
 70	var cs []string
 71	switch v := m[key].(type) {
 72	case string:
 73		cs = append(cs, v)
 74	case []string:
 75		cs = v
 76	case []interface{}:
 77		for _, a := range v {
 78			vs, ok := a.(string)
 79			if !ok {
 80				return nil, newError(fmt.Sprintf("%s is invalid", key), ErrInvalidType)
 81			}
 82			cs = append(cs, vs)
 83		}
 84	}
 85
 86	return cs, nil
 87}
 88
 89// parseString tries to parse a key in the map claims type as a [string] type.
 90// If the key does not exist, an empty string is returned. If the key has the
 91// wrong type, an error is returned.
 92func (m MapClaims) parseString(key string) (string, error) {
 93	var (
 94		ok  bool
 95		raw interface{}
 96		iss string
 97	)
 98	raw, ok = m[key]
 99	if !ok {
100		return "", nil
101	}
102
103	iss, ok = raw.(string)
104	if !ok {
105		return "", newError(fmt.Sprintf("%s is invalid", key), ErrInvalidType)
106	}
107
108	return iss, nil
109}