Skip to content
cccskills
FreePublished on GitHub

configuration-oauth-applications

Define named OAuth clients and configure portal OpenID Connect providers in Caddy security settings. The skill covers private registration storage, credential revisions and rotation, callback URLs, scopes, and client options, while distinguishing these applications from external login providers.

OriginalShow the original description

Register named OAuth clients, manage private registration storage, and configure portal OIDC providers. Owns security oauth/oidc provisioning commands; external login providers and security local are separate.

Run score Not tested

See how to install

Good for

  • Registering confidential or public OAuth clients
  • Selecting stored credential revisions for applications
  • Configuring portal OIDC providers and callbacks
  • Reviewing private registration storage and rotation

Files included (6)

  • SKILL.md14.7 KB
  • agents/openai.yaml317 B
  • references/oidc-conformance-actions.md11.6 KB
  • references/oidc-conformance.md32.2 KB
  • references/oidc-provider.md23.4 KB
  • references/private-provisioning.md14.2 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Configuration OAuth Applications

Ownership

oauth application <nickname> belongs inside global security. The Caddy adapter collects these blocks before parsing other declarations, including portals and identity providers. caddyfile_oauth_application.go encodes the header separately from each body statement and delegates to go-authcrunch/pkg/oidc/parser.NewOAuthApplicationConfigFromDirectives. Config.AddOAuthApplication validates and copies each registration. Collect applications directly from the enclosing dispenser: Caddy's NextSegment omits empty blocks, which otherwise turns an empty registration into a misleading missing-block error. Dispatch errors must also omit raw tokens; malformed quoted headers can contain misplaced credentials before the application parser runs. Check the closing brace before calling NextBlock: that helper can skip a brace followed by another token on the same line and read the following setting inside the application. Reject this form so misplaced consent, PKCE, and callback settings cannot change the registration. Reject unquoted closing braces among header/body arguments too. RemainingArgs accepts them as values, so a missing client_id could otherwise become } and shift which enclosing block supplies the application's closing brace. After collection, also require the enclosing security dispenser's nesting to return to zero, including for direct dispenser callers. Caddy treats quoted "{" and "}" arguments as literal values. Preserve those values and following declarations; EOF must still reject an incomplete owned block. Test missing security/portal delimiters separately from the host global block. The testcase_security_oauth_applications fixture deliberately uses "{" and "}" as client display names. These are valid literal values for parser and provisioning regressions, not recommended operator-facing application names. The published go-authcrunch module selected in go.mod supports these APIs and repeated singular redirect_uri statements. No local replacement is required; follow the dependency workflow when changing the selected version. Follow the repository scope when consulting or selecting sibling source.

An application declares a client. A portal enables an OpenID Provider (OP) by selecting those clients in an oidc provider block. See Portal OpenID Provider for the one-block contract, all settings/defaults, deferred attachment, realm selection, issuer/cookie isolation, HTTP mounting, protocol capabilities, native callbacks, JSON restoration, and Caddy TLS relying-party coverage. See Official Caddy OP conformance for the pinned Foundation plans, private local prerequisites, trusted HTTPS, real browser interaction, signed evidence, original nonzero results and remaining reviews. The operator examples exercise the outer configuration, persisted confidential/public applications, two independent portals and generated native JSON with actual Caddy TLS journeys. Use the Caddy harness rather than treating library conformance as deployment evidence. See Private provisioning and activation for the tested create/load/rotate workflow, storage security, candidate activation, and key rollover. External login through oauth identity provider uses configuration-oauth-providers.

Keep host storage names scoped to OAuth: oauth registration store in Caddyfiles, oauth_registration_store in app JSON, and oauth_registration_* source files. Use oauth_store.Caddyfile, oauth_client.Caddyfile, and oauth_rotate.Caddyfile for standalone provisioning inputs. User registration remains a separate domain.

Grammar

This is a catalogue of fields inside security; redirect_uri and request_object_key may repeat:

oauth application <nickname> {
	registration <immutable-revision>
	client_id <id>
	client_name <display_name>
	client_secret <secret>
	token_endpoint_auth_method <client_secret_basic|client_secret_post|none>
	redirect_uri <uri>
	scopes <scope> [<scope>...]
	require_pkce <true|yes|on|1|false|no|off|0>
	skip_consent <true|yes|on|1|false|no|off|0>
	request_object_signing_alg <none|RS256>
	request_object_key <kid> <base64url-modulus> <base64url-exponent>
}
  • Optional registration selects a previously provisioned revision from the single oauth registration store in security. Without it, credentials are explicit. Revisions are 1–64 ASCII letters/digits/hyphens/underscores, starting with a letter or digit. Only declared nicknames become registered.
  • Nickname identifies the declaration. client_id identifies the protocol client; client_name is its display name and defaults to nickname. Keep these separate, including in native JSON and lookup keys.
  • Duplicate nicknames fail, even for identical definitions, repeated imports, or different protocol IDs. Different nicknames may share a protocol ID at registration time; provider validation owns conflicting client-ID references.
  • Scalars require exactly one value. Quote display names containing spaces. Each redirect_uri statement takes exactly one URI and appends it in declaration order. scopes occupies one statement with one or more values; repeated scopes statements fail. The redirect_uris directive is rejected, including mixed singular/plural input. Nested blocks, spaced field aliases, and grouped keywords are unsupported.
  • Use unquoted block braces. End the line after the closing brace; following settings and declarations belong on a new line.
  • Booleans retain the application parser's true/yes/on/1 and false/no/off/0 spellings. Provider/refresh enabled/disabled state syntax is unsupported here.
  • Authentication defaults to client_secret_basic; confidential clients may choose client_secret_post. Both require an explicit or stored client ID and a secret of 32–1024 bytes. IDs must be nonempty, at most 256 bytes, and have no leading or trailing whitespace, tabs, or newlines.
  • Public clients choose none, omit the secret, and require PKCE. PKCE defaults to true for all clients; only confidential clients may disable it.
  • Consent skipping defaults to false; explicitly enabling it grants the registered scopes. Scopes default to openid profile email; an explicit list must be distinct, include openid, and use supported scopes: openid profile email address phone offline_access. OIDC offline access still requires an explicit consent prompt and approval, even with skip_consent.
  • Request Object verification keys contain only public RSA parameters, with distinct kid values, 2048–8192-bit moduli, and at most eight keys. Both integer parameters use unpadded base64url. request_object_signing_alg RS256 requires registered keys and rejects unsigned objects; none permits only unsigned objects. Omitting the pin permits unsigned objects and RS256 signatures from the registered keys. Keys and algorithm policy come from current directives, not persisted-policy inheritance. No key file or remote JWKS is fetched.
  • Callback URIs are required, distinct, and preserved byte-for-byte, including case, percent encoding, query ordering, and explicit ports. HTTPS is required except for public native clients using HTTP with literal 127.0.0.1 or [::1]. Hostname loopback and private URI schemes are not supported. The provider's native-loopback port exception changes only the authorization port for these literal HTTP addresses; token redemption must repeat the exact actual redirect. It does not authorize new CORS origins. Real IPv4/IPv6 listener coverage lives in oidc_loopback_e2e_test.go, exercised by TestCaddyOIDCRelyingPartyE2E.

Why One Callback per Statement

Each callback is a separate registration entry, so write it on its own line:

redirect_uri https://App.example.test:443/a%2Fb?next=%2F&x=+
redirect_uri https://app.example.test/callback

Inside oauth application, this lets reviewers add, remove, or inspect one callback without rewriting a packed list. The shared upstream parser owns append behavior; Caddy forwards each complete statement and preserves exact URI bytes. Repeated identical URIs remain errors. Retaining no plural alias keeps one directive form and unambiguous one-value arity. The serialized redirect_uris array retains its name and order for stored-config compatibility.

Credentials and Snapshots

Normal adaptation never generates or persists credentials. registration v1 loads the validated named record from the explicit private store. Only omitted ID and secret inherit; callbacks, scopes, display name, authentication method, consent, PKCE, and Request Object keys/policy come from the current declaration and parser defaults. Public clients inherit no secret. Moving to confidential authentication requires an explicit secret through the provisioning command. Changing IDs never borrows another ID's secret. Secret rotation retains the ID; use a new nickname to create a different stored client identity.

An explicit ID/secret in a stored declaration must match its selected durable revision. First stage any credential change with security oauth rotate secret, then select that revision. A mismatched, missing, corrupt, unreadable, or nonprivate record fails closed. Changes to a file between adaptation and activation are rejected by a digest of the validated registration. Never edit published records.

Stored application references serialize in apps.security.oauth_application_sources with nickname, revision, digest, and current noncredential directives. The oauth_registration_store.path is absolute. Provider statements serialize in oidc_provider_directives, keyed by portal name. Loaded credentials and copied provider clients are removed before serializing the Caddy configuration; App reconstructs them only in its private runtime copy. This protects the saved credentials from adapted JSON, Caddy autosave, and admin configuration views.

Without registration, existing native JSON remains supported at apps.security.config.oauth_applications, as { "name": ..., "client": ... } objects. Explicit credentials remain secret-bearing configuration. Caddy's {$VARIABLE} substitution runs before adaptation; application fields do not implement runtime {env.*} or secrets:* expansion. The separate provisioning file does not expand variables or imports. Its client_secret is literal.

Protect all configurations, diagnostics, and backups because other settings can still contain passwords or keys. Generic configuration dumping is not credential storage. See the private provisioning reference for filesystem permissions, protected RP handoff, and recovery after interrupted writes.

Examples and Validation

The complete, synthetic example is testcase_security_oauth_applications.Caddyfile. It includes all three authentication methods, a local portal, exact callbacks, and applications declared after the portal. Replace its fixture credentials before using it outside tests.

Coverage belongs to caddyfile_oauth_application_test.go, TestCaddyfileAdaptAuthenticationToJSON, TestResolveRuntimeAppConfig, and TestCaddyOAuthApplicationsE2E in oauth_application_e2e_test.go. The E2E test adapts that file, provisions Caddy with a valid local portal, authenticates over TLS, reloads repeatedly, rejects invalid native JSON, removes/reintroduces an application, and checks explicit secret rotation and redacted process logs. Header-error tests cover inline and imported declarations through the real adapter, including empty blocks and grouped headers with misplaced credentials. Block-boundary tests reject quoted delimiters and settings after a closing brace. The E2E test also verifies login remains available after those adaptations fail. It verifies that application declarations alone enable no OP endpoints. TestCaddyRegistrationE2E exercises the registered CLI in independent processes, real Caddy restart/reload and validation, RP code exchange and ID-token signature verification, old-secret rejection after activation, failed activation, key rollover, and redaction of actual admin/autosave/log surfaces. TestCaddyRegistrationInterruptedWriterE2E kills a writer during a partial write, checks that the actual CLI times out on the retained lock while adaptation still reads the prior registration, and verifies rotation after deliberate recovery. oauth_registration_store_test.go covers atomic failure paths, concurrency, permissions, invalid lock entries, read-only adaptation with a failing randomness source, bounded publication, ambiguous/corrupt JSON, and revision integrity. oauth_registration_config_test.go checks provider key path identity and permissions for Caddyfile and native JSON providers; command_provision_test.go checks private input filename identity. The process E2E tests reject malformed input and records without creating credentials or replacing the active deployment. They also verify that unsafe keys in native JSON are rejected without changing the active provider or autosave, and that private keys work in explicit configurations without a store. command_security_test.go covers Caddy command-group registration, descriptive subcommand help, flags specific to each action, and rejection of positional secrets. Keep the namespace's inherited Cobra flag-error handler: flag parsing runs before command handlers, and default errors echo unknown flag names and invalid values. Help must perform no provisioning. TestCaddySecurityCommandE2E and TestCaddySecurityCommandFlagErrorsE2E check help, dispatch, and error redaction through the actual Caddy CLI in separate processes. testcase_security_oauth_registration_store, testcase_security_oauth_registration_malformed, and testcase_security_oauth_registration_legacy cover the new adaptation syntax; the positive fixture provisions deterministic synthetic credentials in a temporary private directory. Runtime reference resolution is tested through the complete App and Caddy lifecycle, since the older root-config-only resolution helper does not load host-owned references.

Validation commands follow testing-and-ci, with syntax maintenance when changing the Caddy wrapper or selected upstream grammar.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Build or troubleshoot HTTP clients for an authentication portal’s JSON login, token refresh, Documents, profile, and admin APIs. The skill explains request and response contracts, browser and native transports, and public signing-key discovery so clients can interact with the configured portal correctly.

  • Implement a JSON login client for a portal
  • Troubleshoot browser or native token refresh
  • Call profile, Documents, or admin endpoints
greenpau/caddy-security2.3KUpdated Oct 26, 2026

Investigate caddy-security deployment and runtime failures using configuration, logs, version details, and HTTP evidence. The skill helps identify a focused correction or document an unresolved issue with a useful handoff, while keeping observed facts separate from hypotheses and redacting secrets.

  • Diagnosing login, callback, or authorization failures
  • Finding a minimal correction for a Caddy configuration
  • Preparing a redacted break-fix issue report
greenpau/caddy-security2.3KUpdated Oct 26, 2026

Use these conventions to implement or review caddy-security Go code, Caddy modules, Caddyfile parsers, and HTTP integrations. Keep app boundaries and lifecycle behavior clear, delegate authentication logic to go-authcrunch, and handle errors and logs safely.

  • Reviewing a Caddyfile parser change
  • Adding a Caddy module or HTTP handler
  • Checking app lifecycle and cleanup behavior
greenpau/caddy-security2.3KUpdated Oct 26, 2026

configuration

FreeSummary

Build or review caddy-security Caddyfiles by starting with the security app and wiring authenticate or authorize routes to named portals and policies. Use its domain map to find focused guidance for the requested login, provider, storage, or integration setup.

  • Drafting a complete caddy-security Caddyfile
  • Wiring portal authentication into routes
  • Connecting authorization policies to protected paths
greenpau/caddy-security2.3KUpdated Oct 26, 2026

Configure Caddy authentication portals and connect them to protected routes. Select login backends, set trusted login and logout redirect rules, and wire portal behavior such as refresh and Documents storage while relying on focused skills for specialized settings.

  • Create a portal and connect it to protected routes
  • Choose which identity stores and providers can log in
  • Set trusted login and logout redirect destinations
greenpau/caddy-security2.3KUpdated Oct 26, 2026

Set authentication portal cookie names, prefixes, domains, paths, and browser attributes, including refresh-cookie overrides. The guidance explains naming precedence, validation, and how authorization policies must explicitly discover matching token cookies.

  • Giving portal cookies a shared prefix
  • Overriding one cookie name
  • Setting cookie paths and domains
greenpau/caddy-security2.3KUpdated Oct 26, 2026

See all skills by greenpau

Report a problem with this skill