package auth import ( "fmt" "time" jwt "github.com/dgrijalva/jwt-go" "github.com/pkg/errors" ) // These are the expected values for Claims.Roles. const ( RoleAdmin = "admin" RoleUser = "user" ) // ctxKey represents the type of value for the context key. type ctxKey int // Key is used to store/retrieve a Claims value from a context.Context. const Key ctxKey = 1 // Claims represents the authorization claims transmitted via a JWT. type Claims struct { AccountIds []string `json:"accounts"` Roles []string `json:"roles"` jwt.StandardClaims } // NewClaims constructs a Claims value for the identified user. The Claims // expire within a specified duration of the provided time. Additional fields // of the Claims can be set after calling NewClaims is desired. func NewClaims(userId, accountId string, accountIds []string, roles []string, now time.Time, expires time.Duration) Claims { c := Claims{ AccountIds: accountIds, Roles: roles, StandardClaims: jwt.StandardClaims{ Subject: userId, Audience: accountId, IssuedAt: now.Unix(), ExpiresAt: now.Add(expires).Unix(), }, } return c } // Valid is called during the parsing of a token. func (c Claims) Valid() error { for _, r := range c.Roles { switch r { case RoleAdmin, RoleUser: // Role is valid. default: return fmt.Errorf("invalid role %q", r) } } if err := c.StandardClaims.Valid(); err != nil { return errors.Wrap(err, "validating standard claims") } return nil } // HasRole returns true if the claims has at least one of the provided roles. func (c Claims) HasRole(roles ...string) bool { for _, has := range c.Roles { for _, want := range roles { if has == want { return true } } } return false }