simpleauth/pkg/token/token.go

82 lines
1.5 KiB
Go
Raw Normal View History

2021-08-15 11:03:25 -06:00
package token
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
2023-02-18 16:39:18 -07:00
"encoding/gob"
2021-12-05 16:16:52 -07:00
"log"
2021-08-15 11:03:25 -06:00
"time"
)
type T struct {
2023-02-18 16:39:18 -07:00
Expiration time.Time
Username string
Mac []byte
2021-08-15 11:03:25 -06:00
}
func (t T) computeMac(secret []byte) []byte {
2023-02-18 16:39:18 -07:00
zt := t
zt.Mac = nil
2021-08-15 11:03:25 -06:00
mac := hmac.New(sha256.New, secret)
2023-02-18 16:39:18 -07:00
mac.Write(zt.Bytes())
2021-08-15 11:03:25 -06:00
return mac.Sum([]byte{})
}
2023-02-18 16:39:18 -07:00
// Bytes encodes the token
func (t T) Bytes() []byte {
2021-08-15 11:03:25 -06:00
f := new(bytes.Buffer)
2023-02-18 16:39:18 -07:00
enc := gob.NewEncoder(f)
if err := enc.Encode(t); err != nil {
2021-12-05 16:16:52 -07:00
log.Fatal(err)
}
2023-02-18 16:39:18 -07:00
return f.Bytes()
}
// String returns the ASCII string encoding of the token
func (t T) String() string {
return base64.StdEncoding.EncodeToString(t.Bytes())
2021-08-15 11:03:25 -06:00
}
// Valid returns true iff the token is valid for the given secret and current time
func (t T) Valid(secret []byte) bool {
2023-02-18 16:39:18 -07:00
if time.Now().After(t.Expiration) {
2021-08-15 11:03:25 -06:00
return false
}
2023-02-18 16:39:18 -07:00
if !hmac.Equal(t.Mac, t.computeMac(secret)) {
2021-08-15 11:03:25 -06:00
return false
}
return true
}
// New returns a new token
2023-02-18 16:39:18 -07:00
func New(secret []byte, username string, expiration time.Time) T {
2021-08-15 11:03:25 -06:00
t := T{
2023-02-18 16:39:18 -07:00
Username: username,
Expiration: expiration,
2021-08-15 11:03:25 -06:00
}
2023-02-18 16:39:18 -07:00
t.Mac = t.computeMac(secret)
2021-08-15 11:03:25 -06:00
return t
}
// Parse returns a new token from the given bytes
func Parse(b []byte) (T, error) {
2023-02-18 16:39:18 -07:00
var t T
2021-08-15 11:03:25 -06:00
f := bytes.NewReader(b)
2023-02-18 16:39:18 -07:00
dec := gob.NewDecoder(f)
err := dec.Decode(&t)
return t, err
2021-08-15 11:03:25 -06:00
}
2023-02-18 16:39:18 -07:00
// ParseString parses an ASCII-encoded string, as created by T.String()
2021-08-15 11:03:25 -06:00
func ParseString(s string) (T, error) {
b, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return T{}, nil
}
return Parse(b)
}