package httpapi import ( "time" "github.com/go-jose/go-jose/v4" "github.com/go-jose/go-jose/v4/jwt" ) // mintSessionToken signs a short-lived cdrop self-signed session access token // (AUTH.md §3.1): HS256 over the SessionSecret-derived key, sub=userID, sid=the // web_sessions row id, typ=session, scope=full|guest. The matching verifier is // jwtauth.verifySelfToken. Returns the token and its lifetime in seconds (for the // client's expires_in). Used by scan-login and self/guest session refresh — never // touches the IdP. func (s *Server) mintSessionToken(userID, sid, scope string) (string, int, error) { ttl := time.Duration(s.cfg.SessionTokenTTLSeconds) * time.Second now := time.Now() sig, err := jose.NewSigner( jose.SigningKey{Algorithm: jose.HS256, Key: s.sessionTokenKey}, (&jose.SignerOptions{}).WithType("JWT"), ) if err != nil { return "", 0, err } std := jwt.Claims{ Subject: userID, IssuedAt: jwt.NewNumericDate(now), Expiry: jwt.NewNumericDate(now.Add(ttl)), } tok, err := jwt.Signed(sig). Claims(std). Claims(map[string]any{"typ": "session", "scope": scope, "sid": sid}). Serialize() if err != nil { return "", 0, err } return tok, int(ttl / time.Second), nil }