authtest

package
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 38 Imported by: 0

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, an identity provider to sign in with (IdP), 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 covered by AuthKit's compatibility contract like the rest of the module (docs/stability.md).

Index

Constants

View Source
const (
	Issuer   = "https://example.com"
	Audience = "authtest"
)

Issuer and Audience are the token issuer and audience New configures.

View Source
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

func Replica(t testing.TB, auth *authkit.Client, opts ...Option) *authkit.Client

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 is copied, so opts may set its 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

func SignIn(t testing.TB, auth *authkit.Client, u User) iam.TokenSet

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

func StaleSession(t testing.TB, auth *authkit.Client, accessToken string) string

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.

func TOTPCode added in v0.147.0

func TOTPCode(t testing.TB, secret string, at time.Time) string

TOTPCode is the RFC 6238 code of secret (base32) at the given time: SHA-1, six digits, 30-second steps.

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

func EnrollDeviceKey(t testing.TB, auth *authkit.Client, outbox *Outbox, u User) DeviceKey

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 IdP added in v1.1.0

type IdP struct {
	// contains filtered or unexported fields
}

IdP is an OpenID Provider on a local TLS server, for tests of signing in with an identity provider: discovery, JWKS, and the token and userinfo endpoints. A sign-in start redirects the browser to it; SignIn answers the way it would.

func NewIdP added in v1.1.0

func NewIdP(t testing.TB) *IdP

NewIdP starts an IdP, closed at the test's cleanup.

func (*IdP) Provider added in v1.1.0

func (p *IdP) Provider(name string, opts ...provider.Option) provider.Provider

Provider is an OpenID Connect provider named name for this IdP, trusted to verify email, for Deps.Providers. opts come after the defaults.

func (*IdP) SignIn added in v1.1.0

func (p *IdP) SignIn(t testing.TB, authURL string, user provider.Identity) url.Values

SignIn is the query of the IdP's redirect back to AuthKit's callback once user signs in at authURL, the IdP URL a sign-in start redirected to: its state and a code. AuthKit redeems the code for an ID token naming user's Subject, Email (verified when EmailVerified), PreferredUsername and DisplayName.

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

func WithConfig(fn func(*authkit.Config)) Option

WithConfig edits the Config New passes to authkit.New, after its defaults.

func WithDeps added in v0.147.0

func WithDeps(fn func(*authkit.Deps)) Option

WithDeps edits the Deps New passes to authkit.New. The Outbox's senders are already Email and SMS; set Postgres to use a pool of your own instead of AUTHKIT_TEST_DATABASE_URL.

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

func New(t testing.TB, opts ...Option) (*authkit.Client, *Outbox)

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), with every rate limit lifted (RateLimits).
  • 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

func EnrollTOTP(t testing.TB, auth *authkit.Client, u User) *TOTP

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.

func TOTPOf added in v0.149.0

func TOTPOf(userID string) *TOTP

TOTPOf is the authenticator app EnrollTOTP or SignIn enrolled on the account userID; nil for none.

func (*TOTP) Code added in v0.147.0

func (a *TOTP) Code(t testing.TB) string

Code returns a code AuthKit has not accepted yet. AuthKit takes each 30s step once, and at most one step ahead, so Code waits for the clock when both usable steps are spent.

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).

func NewUser added in v0.147.0

func NewUser(t testing.TB, auth *authkit.Client) User

NewUser creates an account with a verified email, a username and Password, as the host's own code would (Client.CreateUser). The username (user plus 16 random hex digits) and email are random, so test processes sharing one schema never collide.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL