feat: initial commit for media tracking software
- Setup C++/Qt6 desktop application structure - Added initial Go proxy backend for TMDB/IGDB integration
This commit is contained in:
commit
3f07c78316
63 changed files with 6547 additions and 0 deletions
68
server/token.go
Normal file
68
server/token.go
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// appClaims is the payload of a desktop-app access token. These tokens are
|
||||
// minted by this server after a successful Authentik login and are independent
|
||||
// of the (short-lived) OIDC tokens, so a friend can paste one into the desktop
|
||||
// app and keep using it until it expires.
|
||||
type appClaims struct {
|
||||
Subject string `json:"sub"`
|
||||
Email string `json:"email"`
|
||||
Expires int64 `json:"exp"` // unix seconds
|
||||
}
|
||||
|
||||
// mintToken creates a stateless, HMAC-signed token of the form
|
||||
// base64url(payload).base64url(sig). No server-side storage is needed.
|
||||
func mintToken(secret []byte, sub, email string, ttl time.Duration) (string, error) {
|
||||
payload := appClaims{
|
||||
Subject: sub,
|
||||
Email: email,
|
||||
Expires: time.Now().Add(ttl).Unix(),
|
||||
}
|
||||
raw, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
body := base64.RawURLEncoding.EncodeToString(raw)
|
||||
sig := sign(secret, body)
|
||||
return body + "." + sig, nil
|
||||
}
|
||||
|
||||
// verifyToken validates the signature and expiry, returning the claims.
|
||||
func verifyToken(secret []byte, token string) (*appClaims, error) {
|
||||
parts := strings.SplitN(strings.TrimSpace(token), ".", 2)
|
||||
if len(parts) != 2 {
|
||||
return nil, errors.New("malformed token")
|
||||
}
|
||||
expected := sign(secret, parts[0])
|
||||
if !hmac.Equal([]byte(expected), []byte(parts[1])) {
|
||||
return nil, errors.New("bad signature")
|
||||
}
|
||||
raw, err := base64.RawURLEncoding.DecodeString(parts[0])
|
||||
if err != nil {
|
||||
return nil, errors.New("bad payload encoding")
|
||||
}
|
||||
var claims appClaims
|
||||
if err := json.Unmarshal(raw, &claims); err != nil {
|
||||
return nil, errors.New("bad payload")
|
||||
}
|
||||
if time.Now().Unix() >= claims.Expires {
|
||||
return nil, errors.New("token expired")
|
||||
}
|
||||
return &claims, nil
|
||||
}
|
||||
|
||||
func sign(secret []byte, body string) string {
|
||||
m := hmac.New(sha256.New, secret)
|
||||
m.Write([]byte(body))
|
||||
return base64.RawURLEncoding.EncodeToString(m.Sum(nil))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue