The profiler panel¶
A request that is pushed, signed or bound to a key says nothing to whoever watches it from outside: the browser carries a reference, the client posts a JWT, the endpoint answers a document. The panel the bundle adds to the Symfony profiler says what the provider received, decided and emitted during the request, read where the provider itself reads it.
When it is there¶
The panel is wired when the kernel runs in debug, and nothing else turns it on: a deployment that does not run
in debug has no panel and no option to give it one. It is a page of the Symfony profiler, so the kernel
registers WebProfilerBundle and the profiler of the framework collects, which the standalone application
does in development.
It reports on a request that reached a route of the provider, one whose name starts with
beffroi_interaction_ or beffroi_protocol_, and on no other: on a page of the host application, the toolbar
carries no entry of the provider. A route the process refuses for its plane is not reported as one it served.
What it shows is recorded by observers that decorate services the provider already uses, the reader of an authorization request, the repository of the clients, the issuers of the tokens, the providers of the keys, and add nothing to what those services do: the panel says what the request did and never what a list kept beside the code claims.
What it shows¶
The toolbar shows how many facts were recorded and, per tab, their headings. The panel groups them under their tabs, in the order the request first spoke of each.
| Tab | Heading | What it says |
|---|---|---|
| Request | Endpoint | The route, the method and the path; the certificate the edge handed over, by the x5t#S256 a token would be bound to (RFC 8705 §3.1), or that one was carried in a header and refused; whether a DPoP proof was presented (RFC 9449 §4.1) |
| Request | Authorization request | How it came in, in the query, pushed (RFC 9126 §4) or carried by a request object (OIDC Core §6.1); the query the browser carried and the request as the provider read it, side by side; the parameters of the query that were dropped |
| Request | JWT received, not yet verified | The alg, kid, typ and claims of every compact JWT read during the request, before anything verified it: a request object, a client assertion, a DPoP proof, a software statement, the assertion of a trusted issuer, and also the access token in the shape of a JWT and the signed ID token the token endpoint has just issued, which the panel reads back the same way to describe them |
| Interaction | Interaction | The authorization request the provider parked while the person signs in and consents: where it is, its dates, its language, the client, the redirection URI, the response mode, the scopes, the PKCE method, whether a state, a nonce, a login_hint and an id_token_hint were carried, prompt, max_age, acr_values, ui_locales, display, dpop_jkt, the claims asked for by name, and the session and consent attached to it |
| Client | Client | The client as it is registered: its identifier, its name, its authentication method, whether it must push its requests, whether it needs PKCE and consent, its grant types, its scopes, the shape of its access tokens and of its ID tokens, UserInfo answers and authorization responses |
| Client | Consent | The consent the request found or wrote, its scopes and when it was granted |
| Session | Session | The sid, the auth_time, the amr and the acr of the session, when it expires and whether it has ended |
| Decision | Decision | What the authorization endpoint decided and why: the login and the classes a step-up is still short of, with the kinds of credential that would reach one; the consent and the scopes asked; the answer and the names of the parameters sent back; or the refusal, with its error and its description |
| Tokens | Access token | The grant, the shape, the jti, the aud, the exp, the scopes of the response and the scopes granted, the binding of the token, and what the session had proven, or that nobody signed in |
| Tokens | ID token | Its aud and shape, whether the nonce was carried back, the acr, amr and auth_time, the claims the client asked for by name and the claims it carries |
| Keys | Key | The key that signed, or that opened what a client encrypted to the provider: its kid, algorithm, use and status, and the name of the key management client that opens it |
| Events | Event | Every event the provider announced during the request, by its name and the moment it happened |
| Response | Answer | The status, the content type, and the members of a JSON answer |
| Provider | What this provider serves | The discovery document of the tenant, member by member, read from the handler that answers it |
| Provider | Provider | Why the discovery document cannot be built, in its place, when it cannot |
What it withholds¶
The panel withholds a value by its name, wherever it is written: a parameter a client sent, a member an endpoint answered, a claim of a JWT.
- A value under the name of a credential is said to be there and never written down:
token,code,code_verifier,client_secret,request,client_assertion,dpop, and every name that ends in_tokenor_token_hint, whether it was received or sent, written by the provider or read by it. The panel writes(present, withheld)in its place. - A claim about a person is named only, every claim the provider serves being one: the panel writes
(a claim about the user, named only). - Every other value is written as it is. That includes values a client polls or presents with: the
device_code,user_codeandverification_uri_completeof an answer of the device authorization endpoint, theauth_req_idof an answer of the backchannel authentication endpoint, and therequest_uriof an answer of the pushed authorization endpoint, which the query of the browser then carries too. - What the provider encrypted for its client is not opened: an ID token encrypted for its client is said to be so, and an answer that is not JSON is described as a page, a redirection or a document signed for the client rather than read.
- A key is named by its
kid, its algorithm, its use and its status, never by its material, and the key management client by the name it carries inkey_management.clients, never by its DSN, which may hold a credential. - A session is named by its identifier, which tokens carry as
sidanyway, and an event by its name and the moment it happened, never by what it carries.
The panel of the key management service¶
symfony/key-management has a panel of its own, and in debug the bundle hands it what the provider seals and
opens: the envelopes of the keys and secrets of the tenant, and the store of the data keys of its sealed
columns. That panel then reports a request that read a sealed column, its calls grouped by scope,
<slug>.<family>. A data key is opened once per key and per process, so a request served by a process that
already holds it reports no call to the service, which is what that panel is there to show.