50 lines
1.6 KiB
Go
50 lines
1.6 KiB
Go
package ficha
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
)
|
|
|
|
// payload is the internal structure that gets encrypted into a token.
|
|
// It has two compartments for consumer use:
|
|
//
|
|
// - Permissions: a flat list of string identifiers that ficha understands
|
|
// and provides check methods for (Has, HasAll, HasAny, etc.).
|
|
// Consumers choose any string convention they like (e.g. "orders:read",
|
|
// "admin", "team:42:write").
|
|
//
|
|
// - Data: a freeform JSON blob that ficha treats as opaque bytes.
|
|
// Consumers marshal/unmarshal it into their own types.
|
|
//
|
|
// The payload itself is unexported because consumers never construct one directly.
|
|
type payload struct {
|
|
ID string `json:"id"`
|
|
Iat int64 `json:"iat"`
|
|
Exp int64 `json:"exp"`
|
|
Permissions []string `json:"perms,omitempty"`
|
|
Data json.RawMessage `json:"data,omitempty"`
|
|
}
|
|
|
|
// encodePayload serializes a payload to bytes ready for encryption.
|
|
func encodePayload(p payload) ([]byte, error) {
|
|
return json.Marshal(p)
|
|
}
|
|
|
|
// decodePayload deserializes bytes (post-decryption) back into a payload.
|
|
func decodePayload(b []byte) (payload, error) {
|
|
var p payload
|
|
if err := json.Unmarshal(b, &p); err != nil {
|
|
return payload{}, err
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
// expired reports whether the payload's expiry has passed at the given time.
|
|
// Uses >= so a token expiring exactly at `now` is considered expired
|
|
// (the conservative choice). Exp == 0 means the token never expires.
|
|
func (p payload) expired(now time.Time) bool {
|
|
if p.Exp == 0 {
|
|
return false
|
|
}
|
|
return now.Unix() >= p.Exp
|
|
}
|