Documentation
¶
Overview ¶
Package authtest runs AuthKit in a host's Go tests: a real Client on a scratch PostgreSQL schema, an Outbox that captures every email and SMS, and helpers for the usual setup (a verified user, a signed-in session, a role, an authenticator app, a device key, a replica, a stale session).
auth, outbox := authtest.New(t, authtest.WithConfig(func(c *authkit.Config) {
c.Roles = myapp.Roles()
}))
alice := authtest.NewUser(t, auth)
authtest.GrantRole(t, auth, iam.RootGroup(), iam.UserSubject(alice.ID), myapp.Admin)
tokens := authtest.SignIn(t, auth, alice)
// call the host's handlers with "Bearer "+tokens.AccessToken, or drive
// auth.Handler() and read codes and links from outbox.
New needs AUTHKIT_TEST_DATABASE_URL, a database where the test may create schemas. Without it the test is skipped, or fails when AUTHKIT_TEST_REQUIRE_DB=1. AUTHKIT_TEST_KEEP_DB=1 keeps each schema.
The package is outside AuthKit's compatibility contract: it may change in any minor release.
Index ¶
- Constants
- func GrantRole(t testing.TB, auth *authkit.Client, group iam.GroupRef, subject iam.Subject, ...)
- func Replica(t testing.TB, auth *authkit.Client, opts ...Option) *authkit.Client
- func RevokeRole(t testing.TB, auth *authkit.Client, group iam.GroupRef, subject iam.Subject, ...)
- func SignIn(t testing.TB, auth *authkit.Client, u User) iam.TokenSet
- func StaleSession(t testing.TB, auth *authkit.Client, accessToken string) string
- func TOTPCode(t testing.TB, secret string, at time.Time) string
- type DeviceKey
- type Message
- type Option
- type Outbox
- type TOTP
- type TestIssuer
- func (ti *TestIssuer) Audience() string
- func (ti *TestIssuer) Close()
- func (ti *TestIssuer) CreateExpiredToken(userID, email string) string
- func (ti *TestIssuer) CreateToken(userID, email string) string
- func (ti *TestIssuer) CreateTokenWithClaims(userID, email string, extraClaims map[string]any) string
- func (ti *TestIssuer) CreateTokenWithExpiry(userID, email string, expiry time.Time) string
- func (ti *TestIssuer) Signer() keys.Signer
- func (ti *TestIssuer) URL() string
- type User
Constants ¶
const ( Issuer = "https://example.com" Audience = "authtest" )
Issuer and Audience are the token issuer and audience New configures.
const Password = "Authtest-password-1"
Password is the password NewUser gives every account.
Variables ¶
This section is empty.
Functions ¶
func GrantRole ¶ added in v0.147.0
func GrantRole(t testing.TB, auth *authkit.Client, group iam.GroupRef, subject iam.Subject, role iam.Role)
GrantRole gives subject role in group with system authority. A role that requires MFA needs the account's second factor first (EnrollTOTP).
func Replica ¶ added in v0.147.0
Replica builds another Client on auth's database and schema, as another replica of the deployment runs: the Config and Deps auth was built with (its Outbox included, when New built it), then opts. auth may be any Client authkit.New built, a host's own included. A different Token.Issuer makes a sibling deployment sharing the account store; different HTTPConfig serves the same accounts another way. HTTP and Password are copied, so opts may set their fields; replace, never mutate, the maps and slices opts change: the replica shares auth's.
func RevokeRole ¶ added in v0.147.0
func RevokeRole(t testing.TB, auth *authkit.Client, group iam.GroupRef, subject iam.Subject, role iam.Role)
RevokeRole takes role in group from subject with system authority.
func SignIn ¶ added in v0.147.0
SignIn signs u in with its password through auth's HTTP surface and follows the AuthResult to a session: a second factor is answered with u.TOTP (or the account's remembered app, TOTPOf); an enrollment the deployment requires adds an authenticator app with the enrollment token, which SignIn remembers for the account's later sign-ins. It returns the session's tokens.
func StaleSession ¶ added in v0.147.0
StaleSession moves the sign-in of the session behind accessToken a day into the past, as if its user signed in long ago, and returns a new access token for that session: routes that need a recent sign-in then ask it for a step-up. auth may be any Client authkit.New built.
Types ¶
type DeviceKey ¶ added in v0.147.0
type DeviceKey struct {
ID string
Key ed25519.PrivateKey
// AccessToken is the enrollment's sign-in.
AccessToken string
}
DeviceKey is a device key enrolled on an account (see package devicekey).
func EnrollDeviceKey ¶ added in v0.147.0
EnrollDeviceKey enrolls a new Ed25519 device key on u with the devicekey client, reading the emailed code from outbox and answering a second factor with u.TOTP. The Client needs Config.DeviceKeys.Enabled.
type Message ¶ added in v0.147.0
type Message = testoutbox.Message
Message is one captured email or SMS: Channel ("email" or "sms"), Kind, To, Language and what it carries (Code, Link and the Link's Token, the verification Purpose, a ContactChange or DeviceKey notice).
type Option ¶ added in v0.147.0
type Option func(*setup)
Option adjusts what New builds.
func WithConfig ¶ added in v0.147.0
WithConfig edits the Config New passes to authkit.New, after its defaults.
type Outbox ¶ added in v0.147.0
type Outbox = testoutbox.Outbox
Outbox captures every email and SMS AuthKit sends, in order, so a test can complete sign-up, verification, reset and sign-in flows. New wires one; for a Client built another way, pass Email() and SMS() as Deps.Email and Deps.SMS. Its methods:
- Last(t, kind, to) Message: the newest message of kind to that address or number ("" = anyone); the test fails when there is none.
- Messages(kind, to) []Message: all of them, oldest first ("" = any).
- Email() authkit.EmailSender, SMS() authkit.SMSSender: the senders.
- SetEmailHealth(err), SetSMSHealth(err): what the senders' CheckHealth returns (nil, the default, is healthy), so a test can take a channel down and bring it back.
For example, out.Last(t, iam.MessageVerification, email).Code.
func New ¶ added in v0.147.0
New migrates AuthKit into a fresh schema, builds a Client on it, and returns the Client with the Outbox wired as its email and SMS senders. The defaults differ from a zero Config only where a test needs them to:
- Token: Issuer and Audience.
- TwoFactor.TOTPSecretKey: random, so authenticator apps can enroll.
- HTTP: served (DirectPeerIP), without rate limits (Deps.Limiter).
- Deps.KeySource: an RSA key generated once per test binary.
- Schema and River.Schema: the scratch schema, unless set.
The Client is not started: call Start when a test needs River's work, such as Deps.OnEvent or the deletion hooks. Cleanup closes the Client and drops the scratch schema.
type TOTP ¶ added in v0.147.0
type TOTP struct {
Secret string
// contains filtered or unexported fields
}
TOTP is an authenticator app enrolled on an account.
func EnrollTOTP ¶ added in v0.147.0
EnrollTOTP signs u in and adds an authenticator app through auth's HTTP surface, as a user would. SignIn uses it from now on; keeping it as u.TOTP works too.
type TestIssuer ¶
type TestIssuer struct {
// contains filtered or unexported fields
}
TestIssuer is a stand-in token issuer with a JWKS endpoint, for testing a service that only verifies tokens (verify.Verifier) without running AuthKit.
func NewTestIssuer ¶
func NewTestIssuer() *TestIssuer
NewTestIssuer creates a new test issuer with an RSA key pair. Register its verifier entry with IsLocal only when modeling local user IDs. Otherwise access tokens expose the qualified external Issuer and Subject.
func NewTestIssuerWithAudience ¶
func NewTestIssuerWithAudience(audience string) *TestIssuer
NewTestIssuerWithAudience creates a test issuer with a specific audience claim.
func NewTestIssuerWithSigner ¶
func NewTestIssuerWithSigner(signer keys.Signer, audience string) *TestIssuer
NewTestIssuerWithSigner creates a test issuer using any keys.Signer (RSA, EC, Ed25519).
func (*TestIssuer) Audience ¶
func (ti *TestIssuer) Audience() string
func (*TestIssuer) Close ¶
func (ti *TestIssuer) Close()
func (*TestIssuer) CreateExpiredToken ¶
func (ti *TestIssuer) CreateExpiredToken(userID, email string) string
func (*TestIssuer) CreateToken ¶
func (ti *TestIssuer) CreateToken(userID, email string) string
func (*TestIssuer) CreateTokenWithClaims ¶
func (ti *TestIssuer) CreateTokenWithClaims(userID, email string, extraClaims map[string]any) string
func (*TestIssuer) CreateTokenWithExpiry ¶
func (ti *TestIssuer) CreateTokenWithExpiry(userID, email string, expiry time.Time) string
func (*TestIssuer) Signer ¶
func (ti *TestIssuer) Signer() keys.Signer
func (*TestIssuer) URL ¶
func (ti *TestIssuer) URL() string
type User ¶ added in v0.147.0
type User struct {
iam.User
Email string
Password string
// TOTP is the authenticator app SignIn answers a second-factor challenge
// with. Unset, SignIn uses the app EnrollTOTP or an earlier SignIn enrolled
// on the account (TOTPOf).
TOTP *TOTP
}
User is an account and what SignIn needs to sign it in. Email is the account's address as text ("" for none).