package identity import ( "fmt" "time" "github.com/golang-jwt/jwt/v5" ) const ( tokenIssuer = "yovision-sense" tokenAudience = "sense-ui" ) type sessionClaims struct { Username string `json:"username"` Role string `json:"role"` jwt.RegisteredClaims } func issueToken(key []byte, user User, session Session, now time.Time) (string, error) { claims := sessionClaims{ Username: user.Username, Role: user.Role, RegisteredClaims: jwt.RegisteredClaims{ Issuer: tokenIssuer, Subject: user.ID, Audience: jwt.ClaimStrings{tokenAudience}, ExpiresAt: jwt.NewNumericDate(session.ExpiresAt), IssuedAt: jwt.NewNumericDate(now), NotBefore: jwt.NewNumericDate(now.Add(-time.Minute)), ID: session.ID, }, } return jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(key) } func parseToken(key []byte, raw string, now time.Time) (*sessionClaims, error) { claims := &sessionClaims{} token, err := jwt.ParseWithClaims(raw, claims, func(token *jwt.Token) (any, error) { if token.Method != jwt.SigningMethodHS256 { return nil, fmt.Errorf("unexpected signing method") } return key, nil }, jwt.WithIssuer(tokenIssuer), jwt.WithAudience(tokenAudience), jwt.WithTimeFunc(func() time.Time { return now })) if err != nil || !token.Valid { return nil, fmt.Errorf("invalid Sense session") } return claims, nil }