Skip to content

Protocol endpoints ​

This page lists the HTTP endpoints that Wicket v0.1.4 actually handles, along with the methods they accept, how they authenticate, and what their error responses look like. All behavior is based on the source code (di/dsl_core.go, handlers/) and on testing the Quick start example.

Routing rules ​

Wicket mounts as middleware in front of the host handler:

go
handler := hosting.ScopeMiddleware(root)(srv.UseWicket()(app))

On each incoming request, the router compares r.URL.Path against the registered endpoint paths as a whole-string, case-insensitive match:

  • Match → the corresponding handler processes it, and the host's app isn't called;
  • No match → the request is passed to the host's app unchanged.

You must wrap it in ScopeMiddleware

UseWicket() relies on the scope that hosting.ScopeMiddleware(root) puts into the request context. Without that layer, the Wicket middleware passes every request straight through to the host without any error—every endpoint turns into the host's 404 or home page.

When a handler hits a failure that can't be mapped to a protocol error (for example a storage error), the middleware responds with HTTP 501 and a plain-text error message (hosting/middleware.go). In production, wrap the host in an outer recovery and logging middleware, and keep in mind that this error text may contain internal details.

Registered endpoints ​

The table below corresponds one-to-one to the 11 hosting.Endpoint registrations in di/dsl_core.go.

PathMethodPurposeNotes
/connect/authorizeGET; POST (form)Entry point for authorization requestsPOST must be application/x-www-form-urlencoded, otherwise 415. On parameter errors, 302 to the host's error page (default /home/error?errorId=...)
/connect/authorize/callbackGETWhere the user returns after interacting with the login/consent page, to resume the original authorization requestNon-GET returns 405
/connect/tokenPOST (form)Token endpointSee "Supported grant types" and "Client authentication methods" below. v0.1.4 doesn't check the method: GET/PUT also reach the processing logic, and in testing return 400 invalid_request
/.well-known/openid-configurationGETDiscovery documentNon-GET returns 405; 404 when Endpoints.EnableDiscoveryEndpoint=false. See Discovery document
/.well-known/openid-configuration/jwksGETJWKS public key setNon-GET returns 405; 404 when EnableDiscoveryEndpoint or Discovery.ShowKeySet is false
/connect/userinfoGET, POSTUser infoRequires a Bearer access token; 401 with no token or an invalid token, 403 when the token lacks the openid scope
/connect/introspectPOST (form)Token introspection (RFC 7662)The caller authenticates with an API resource name + API secret; any failure is 401 with no body; non-form 415; non-POST 405
/connect/endsessionGET; POST (form)RP-initiated logoutNon-form POST 415, other methods 405
/connect/endsession/callbackGETRenders the front-channel logout page after logout completesNon-GET 405
/connect/checksessionGETThe check-session iframe for OIDC session managementReturns HTML with a CSP header
/connect/cibaPOST (form)CIBA backchannel authentication requestOn success returns auth_req_id, expires_in (and optionally interval)

Some endpoints are controlled by WicketOptions.Endpoints switches (returning 404 when turned off): userinfo, endsession, endsession/callback, checksession, discovery, jwks. The authorize, token, introspect, and ciba handlers don't read these switches—setting EnableTokenEndpoint and the like to false only removes them from the discovery document; requests are still processed.

URLs that appear in the discovery document but aren't registered ​

constants.go also defines the following path constants, and the discovery document advertises several of these URLs by default, but v0.1.4 registers no handler for them:

PathDiscovery document fieldActual behavior
/connect/revocationrevocation_endpointThe request falls through to the host handler; Wicket doesn't handle it
/connect/deviceauthorizationdevice_authorization_endpointSame as above
/connect/mtls/token, /connect/mtls/revocation, /connect/mtls/introspect, /connect/mtls/deviceauthorizationmtls_endpoint_aliases (only present when MutualTls.Enabled=true)Same as above

Observed (Quick start example, with the host home page returning host app):

text
POST /connect/revocation          → 200 host app
POST /connect/deviceauthorization → 200 host app
POST /connect/mtls/token          → 200 host app

Turn off advertisements for endpoints that don't exist

Token revocation and device authorization requests aren't handled by Wicket in v0.1.4. If your host returns 200 for unknown paths, clients may even believe a revocation succeeded. Turn off these two advertisements during wiring:

go
opts.Endpoints.EnableTokenRevocationEndpoint = false
opts.Endpoints.EnableDeviceAuthorizationEndpoint = false

Note that the second setting also removes urn:ietf:params:oauth:grant-type:device_code from grant_types_supported, but doesn't disable the token endpoint's handling of that grant type. For the current state of the device flow, see Device authorization.

Supported grant types ​

The token endpoint dispatches on grant_type (validators/impl/token_request_validator.go):

grant_typeAvailable by defaultDescription
authorization_codeYesAuthorization code + PKCE; the plain method is accepted only when the client has AllowPlainTextPkce=true (default false); stick with S256
client_credentialsYesMachine to machine
refresh_tokenYesRenew with a refresh token (v0.1.4 doesn't rotate them; see Refresh tokens); concurrent refresh conflicts return invalid_grant
urn:ietf:params:oauth:grant-type:device_codeYes (token endpoint side)v0.1.4 has no built-in device authorization endpoint; device codes must be issued by the host itself
urn:openid:params:grant-type:cibaYesUsed together with /connect/ciba
passwordNoThe default validator NotSupportedResourceOwnerPasswordValidator always rejects; inject an implementation with cfg.SetResourceOwnerValidator(...)
Other valuesNoGoes to the extension grant branch; v0.1.4's ServerConfig provides no method to register extension grant validators, and in testing it returns unsupported_grant_type

Whatever the grant type, the client must also declare it in AllowedGrantTypes; otherwise the result is unauthorized_client. The implicit in the discovery document refers to flows such as response_type=token on the authorization endpoint, not a token endpoint grant_type.

Client authentication methods ​

The container registers only two secret parsers (di/dsl_core.go) and one secret validator:

Discovery document nameParserWhere it reads from
client_secret_basicBasicAuthenticationSecretParserAuthorization: Basic base64(client_id:client_secret)
client_secret_postPostBodySecretParserForm fields client_id / client_secret; requires Content-Type: application/x-www-form-urlencoded

The shared secret parsed by either is handed to HashedSharedSecretValidator for comparison: when the client is registered, Secret.Value stores a hash (the example uses utils.Sha256("change-me")), while the request carries the plaintext.

A request that carries only client_id and no secret is parsed as NoSecret, which applies only to public clients with RequireClientSecret=false.

v0.1.4 has no parsers for private_key_jwt, client_secret_jwt, or mTLS client authentication. MutualTls.Enabled=true only adds entries such as tls_client_auth to the discovery document; it doesn't actually enable certificate authentication—don't turn it on.

Success responses ​

On success, the token endpoint returns application/json with Cache-Control: no-store and Pragma: no-cache:

json
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "expires_in": 3600,
  "id_token": "",
  "refresh_token": "",
  "scope": "orders.read",
  "token_type": "Bearer"
}

The id_token and refresh_token keys are always present; when not issued, their value is an empty string (rather than the field being omitted). If a client library decides whether there's a refresh token based on "whether the field exists", change it to check for a non-empty value.

Error responses ​

Token endpoint ​

Observed shape (wrong client secret):

text
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=utf-8

{"custom":{},"error":"invalid_client","error_description":""}

Points to note, all describing v0.1.4 as it stands:

  • Besides the standard error and error_description, a custom object is always included (custom response fields from the validator, usually an empty {}).
  • error_description is usually an empty string rather than omitted.
  • All token errors are 400, including invalid_client (RFC 6749 recommends 401 for failed Basic authentication).
  • The response headers lack Content-Type: application/json and Cache-Control: no-store: the error result sets headers only after writing the status code, so those headers are dropped, and Content-Type is sniffed as text/plain by the Go standard library. Clients should handle errors by status code + parsing the body, and not rely on Content-Type.

Other endpoints ​

ScenarioResponse
Parameter errors on CIBA or introspection requests400, body {"error":...,"error_description":...}, without a custom field
userinfo: invalid token / insufficient scope401 / 403, empty body. The source intends to write a WWW-Authenticate header, but again because headers are set after the status code, the header doesn't appear in observed responses
Introspection caller authentication fails401, empty body
Method not allowed / unsupported media type / endpoint disabled405 / 415 / 404, empty body
authorize parameter errors302 to the host's error page, with error details passed via errorId

Released under the Apache License 2.0 · Documentation © 2026 Wicket authors