crpcauthtesting

package
v0.0.237 Latest Latest
Warning

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

Go to latest
Published: May 19, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package crpcauthtesting provides test helpers for stdcrpcauthfx that use real JWT signing and validation. A local JWKS server is started so the real authentication code path runs in tests.

Index

Constants

View Source
const (
	// TestAudience is the audience claim used in test JWTs.
	TestAudience = "urn:test:audience"

	// TestKeyID is the key ID used for signing test JWTs.
	TestKeyID = "test-key"
)

Variables

View Source
var TestClockTime = time.Date(2026, 4, 1, 0, 0, 0, 0, time.UTC)

TestClockTime is the fixed wall-clock time used for JWT validation in tests.

Functions

func CallAs added in v0.0.229

func CallAs[Req, Resp any](
	ctx context.Context,
	tb testing.TB,
	signer *TokenSigner,
	subject string,
	scopes []string,
	tenantID string,
	method func(context.Context, *connect.Request[Req]) (*connect.Response[Resp], error),
	msg *Req,
) (*connect.Response[Resp], error)

CallAs invokes a typed Connect RPC method as the caller identified by subject/scopes/tenantID.

The three identity parameters mirror stdcrpcauthfx.Claims so the test-side abstraction stays in lockstep with the production middleware: subject becomes the JWT "sub" claim, scopes are space-joined into the "scope" claim, and tenantID (when non-empty) is written under the JWT path the signer was configured with at construction time. Passing a non-empty tenantID to a signer without a configured tenant claim path is a test failure (see TokenSigner.SignClaims).

The supplied method is typically a method value of a generated Connect client (e.g. client.WhoAmI), which keeps the helper free of any per-service knowledge.

CallAs is deliberately authenticated-only: tests for the unauthenticated path should call the client method directly so the absence of a token is explicit at the call site. Tests that need to mint tokens with claim shapes outside the Claims model (unknown claim paths, malformed payloads, etc.) should call the lower-level TokenSigner methods (Sign, SignWithClaims, SignWithPermissions, …) and decorate their own connect.Request.

func Clock

func Clock() jwt.Clock

Clock returns a jwt.Clock fixed to TestClockTime, suitable for fx.Supply.

Types

type TokenSigner

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

TokenSigner signs JWTs using a test RSA key pair.

func NewJWKSServer

func NewJWKSServer(tb testing.TB, tenantClaim string) (serverURL string, signer *TokenSigner)

NewJWKSServer starts a local JWKS httptest.Server and returns the server URL and a TokenSigner. The server is automatically closed when the test completes. The server URL can be used as STDCRPCAUTH_TOKEN_ISSUER and the server serves the public key at /.well-known/jwks.json.

tenantClaim is the JWT claim path under which SignClaims will place tenantID values. Pass the same string used for STDCRPCAUTH_TENANT_CLAIM in the application's fx env so test signing and production reading line up. Pass "" for tests that don't exercise tenancy.

func (*TokenSigner) Sign

func (s *TokenSigner) Sign(tb testing.TB, subject string, scopes []string) string

Sign creates a signed JWT with the given subject and scopes (via the "scope" claim).

func (*TokenSigner) SignClaims added in v0.0.229

func (s *TokenSigner) SignClaims(tb testing.TB, subject string, scopes []string, tenantID string) string

SignClaims creates a signed JWT shaped after stdcrpcauthfx.Claims. It sets the "sub" and space-joined "scope" claims and, when tenantID is non-empty, writes it under the JWT path the signer was configured with at construction time (matching what production reads from STDCRPCAUTH_TENANT_CLAIM). An empty tenantID is omitted, mirroring production behavior where an absent tenant claim leaves Claims.TenantID empty.

Passing a non-empty tenantID to a signer that was created without a tenant claim path is a test failure: there is no path to write it under, so the production middleware would silently drop it. Failing fast catches that wiring drift.

func (*TokenSigner) SignWithClaims added in v0.0.226

func (s *TokenSigner) SignWithClaims(
	tb testing.TB, subject string, scopes []string, extraClaims map[string]any,
) string

SignWithClaims creates a signed JWT with the given subject, scopes (via the "scope" claim) and any number of extra claims. Useful for testing custom claim paths such as tenancy identifiers (e.g. "https://example.com/org_id"). Claim keys with "/" or other path-like characters are passed through verbatim so namespaced Auth0 claims work as-is.

func (*TokenSigner) SignWithPermissions added in v0.0.219

func (s *TokenSigner) SignWithPermissions(tb testing.TB, subject string, permissions []string) string

SignWithPermissions creates a signed JWT with the given subject and permissions (via the "permissions" claim as a JSON array, matching the Auth0 SPA token format).

func (*TokenSigner) SignWithScopeAndPermissions added in v0.0.220

func (s *TokenSigner) SignWithScopeAndPermissions(
	tb testing.TB, subject string, scopes []string, permissions []string,
) string

SignWithScopeAndPermissions creates a signed JWT with both the "scope" claim (space-separated) and the "permissions" claim (JSON array), matching the Auth0 m2m token format where the same scope can appear in both claims.

Jump to

Keyboard shortcuts

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