Files
Assistant/modules/identity/domain/session.go
m 5fca81531a
CI / test (push) Failing after 15m55s
feat: add Creator username password login
2026-08-16 16:56:38 +03:00

65 lines
2.4 KiB
Go

package domain
import (
"crypto/hmac"
"crypto/sha256"
"crypto/subtle"
"encoding/base64"
"encoding/json"
"errors"
"strings"
"time"
"git.cin.su/m/Assistant/contracts/identity"
)
var ErrInvalidCreatorSession = errors.New("invalid creator session")
func IssueCreatorSession(secret []byte, now time.Time, ttl time.Duration) (string, identity.CreatorSession, error) {
if len(secret) < 32 || ttl <= 0 {
return "", identity.CreatorSession{}, ErrInvalidCreatorSession
}
session := identity.CreatorSession{ActorID: "domovoy-creator-actor", PrincipalID: "domovoy-creator-principal", ExpiresAtUnix: now.Add(ttl).Unix()}
payload, err := json.Marshal(session)
if err != nil {
return "", identity.CreatorSession{}, err
}
encoded := base64.RawURLEncoding.EncodeToString(payload)
return encoded + "." + signature(secret, encoded), session, nil
}
func ValidateCreatorSession(secret []byte, token string, now time.Time) (identity.CreatorSession, error) {
parts := strings.Split(token, ".")
if len(parts) != 2 || len(secret) < 32 || subtle.ConstantTimeCompare([]byte(signature(secret, parts[0])), []byte(parts[1])) != 1 {
return identity.CreatorSession{}, ErrInvalidCreatorSession
}
payload, err := base64.RawURLEncoding.DecodeString(parts[0])
if err != nil {
return identity.CreatorSession{}, ErrInvalidCreatorSession
}
var session identity.CreatorSession
if json.Unmarshal(payload, &session) != nil || session.ActorID != "domovoy-creator-actor" || session.PrincipalID != "domovoy-creator-principal" || now.Unix() >= session.ExpiresAtUnix {
return identity.CreatorSession{}, ErrInvalidCreatorSession
}
return session, nil
}
func BootstrapMatches(expected, supplied string) bool {
return expected != "" && supplied != "" && subtle.ConstantTimeCompare([]byte(expected), []byte(supplied)) == 1
}
func CreatorCredentialsMatch(expectedUsername, expectedPassword string, supplied identity.CreatorCredentials) bool {
if expectedUsername == "" || expectedPassword == "" || supplied.Username == "" || supplied.Password == "" {
return false
}
usernameMatches := subtle.ConstantTimeCompare([]byte(expectedUsername), []byte(supplied.Username))
passwordMatches := subtle.ConstantTimeCompare([]byte(expectedPassword), []byte(supplied.Password))
return usernameMatches&passwordMatches == 1
}
func signature(secret []byte, payload string) string {
mac := hmac.New(sha256.New, secret)
mac.Write([]byte(payload))
return base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
}