{"record":{"id":"f6747c589be53fa8","repo":"quarkusio/quarkus","slug":"tenant-nonce-is-a-configured-callback-method","errorCode":null,"errorMessage":"/tenant-nonce is a configured callback method","messagePattern":"/tenant-nonce is a configured callback method","errorType":"http","errorClass":"RuntimeException","httpStatus":500,"severity":"error","filePath":"integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/TenantNonce.java","lineNumber":30,"sourceCode":"public class TenantNonce {\n\n    @Inject\n    OidcSession session;\n    @Inject\n    RoutingContext routingContext;\n\n    @GET\n    @Authenticated\n    public String getTenant() {\n        session.logout().await().indefinitely();\n        return session.getTenantId() + (routingContext.get(\"reauthenticated\") != null ? \":reauthenticated\" : \"\");\n    }\n\n    @GET\n    @Authenticated\n    @Path(\"/callback\")\n    public String getTenantCallback() {\n        throw new RuntimeException(\"/tenant-nonce is a configured callback method\");\n    }\n}\n","sourceCodeStart":12,"sourceCodeEnd":33,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/TenantNonce.java#L12-L33","documentation":"Deliberate sentinel in TenantNonce: the /callback path is the configured OIDC redirect_uri for this tenant and must be handled by the OIDC extension itself, never by this JAX-RS method. If getTenantCallback executes, the OIDC code-flow callback was not intercepted — authentication completed unexpectedly or the callback path is not registered as the tenant's redirect path.","triggerScenarios":"A request arrives at /tenant-nonce/callback without the OIDC extension handling it as the code-flow callback (e.g. missing state/code, wrong redirect-path config, or authentication already completed).","commonSituations":"quarkus.oidc.<tenant>.redirect-path not set to /tenant-nonce/callback; testing that the callback is consumed by OIDC (nonce verification flow); hitting the callback URL directly in a browser.","solutions":["Set the tenant's redirect-path so the OIDC extension intercepts /tenant-nonce/callback","Ensure the callback request carries valid code and state parameters from the provider","Verify only the root /tenant-nonce resource is ever served to authenticated users"],"exampleFix":"// before\n@GET\n@Authenticated\n@Path(\"/callback\")\npublic String getTenantCallback() {\n    throw new RuntimeException(\"/tenant-nonce is a configured callback method\");\n}\n// after\n// configure instead:\nquarkus.oidc.tenant-nonce.redirect-path=/tenant-nonce/callback","handlingStrategy":"validation","validationCode":"// ensure OIDC intercepts the callback before it reaches JAX-RS\nif (uri.getPath().endsWith(\"/tenant-nonce/callback\") && securityIdentity.isAnonymous()) {\n    // expected: OIDC extension handles this as the code-flow callback\n}","typeGuard":null,"tryCatchPattern":"try {\n    given().get(\"/tenant-nonce/callback\");\n} catch (RuntimeException e) {\n    // callback reached JAX-RS; check quarkus.oidc.tenant-nonce.redirect-path\n}","preventionTips":["Register the callback path as the tenant redirect-path","Never call the callback URL directly; enter via the provider redirect","Test nonce verification end-to-end through Keycloak"],"tags":["oidc","callback","nonce"],"backgroundTag":"unexpected-callback-invocation","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-15T02:17:10.978Z"}