{"record":{"id":"213239289dc1de3c","repo":"quarkusio/quarkus","slug":"securityidentity-must-have-a-routingcontext-attrib","errorCode":null,"errorMessage":"SecurityIdentity must have a RoutingContext attribute","messagePattern":"SecurityIdentity must have a RoutingContext attribute","errorType":"http","errorClass":"OIDCException","httpStatus":500,"severity":"error","filePath":"integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/ProtectedResource.java","lineNumber":136,"sourceCode":"    @GET\n    @Path(\"configMetadataIdTokenSigningAlgorithms\")\n    public String configMetadataIdTokenSigningAlgorithms() {\n        return configMetadata.getSupportedIdTokenSigningAlgorithms().stream().collect(Collectors.joining(\",\"));\n    }\n\n    @GET\n    @Path(\"configMetadataCodeChallengeMethods\")\n    public String configMetadataCodeChallengeMethods() {\n        return configMetadata.getSupportedCodeChallengeMethods().stream().collect(Collectors.joining(\",\"));\n    }\n\n    @GET\n    public String getName() {\n        if (!idTokenCredential.getToken().equals(idToken.getRawToken())) {\n            throw new OIDCException(\"ID token values are not equal\");\n        }\n        if (identity.getAttribute(RoutingContext.class.getName()) == null) {\n            throw new OIDCException(\"SecurityIdentity must have a RoutingContext attribute\");\n        }\n        return idToken.getName();\n    }\n\n    @GET\n    @Path(\"tenant-idtoken-only\")\n    public String getNameIdTokenOnly() {\n        return \"tenant-idtoken-only:\" + getName();\n    }\n\n    @GET\n    @Path(\"tenant-id-refresh-token\")\n    public String getNameIdRefreshTokenOnly() {\n        return \"tenant-id-refresh-token:\" + getName();\n    }\n\n    @GET\n    @Path(\"tenant-split-tokens\")","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/ProtectedResource.java#L118-L154","documentation":"This is a deliberate test assertion inside the protected JAX-RS resource of the oidc-code-flow integration test. The endpoint verifies that Quarkus OIDC attaches the Vert.x RoutingContext as a SecurityIdentity attribute; if the attribute is missing, the CDI-authenticated identity is malformed and the resource throws OIDCException. It guards against regressions in the OIDC identity augmentation pipeline.","triggerScenarios":"GET request reaches ProtectedResource.getName() (the '/' endpoint) after OIDC authentication, but identity.getAttribute(RoutingContext.class.getName()) returns null — i.e. the SecurityIdentity was built without the RoutingContext attribute the OIDC extension normally injects.","commonSituations":"A change or misconfiguration in the OIDC/HTTP security extensions that skips SecurityIdentityAugmentor execution; testing against a stack where custom identity augmentors replace rather than wrap the default OIDC augmentor; running a modified authentication path in integration tests.","solutions":["Verify the quarkus-oidc and quarkus-vertx-http extensions are on the runtime classpath and unmodified so the default OIDC identity augmentation runs","Check for custom SecurityIdentityAugmentor implementations that build a new SecurityIdentity without propagating existing attributes; propagate attributes from the parent identity","Ensure the request actually passed through the OIDC code-flow authentication (valid session cookie/id token) rather than a fallback permit-all path","Rebuild core/extensions; if this fires in CI on unmodified code, it signals a regression — inspect recent changes to OidcAuthenticationMechanism / SecurityIdentity augmentation"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (identity.getAttribute(org.jboss.resteasy.reactive.server.vertx.RoutingContext.class.getName()) == null) { throw new IllegalStateException(\"RoutingContext attribute missing from SecurityIdentity\"); }","typeGuard":"boolean hasRoutingContext(SecurityIdentity id) { return id != null && id.getAttribute(io.vertx.ext.web.RoutingContext.class.getName()) != null; }","tryCatchPattern":"try { return getName(); } catch (javax.ws.rs.OIDCException e) { log.error(\"identity augmentation failed\", e); return Response.status(500).build(); }","preventionTips":["Do not add custom SecurityIdentityAugmentors that rebuild identity without propagating attributes","Keep quarkus-oidc and vertx-http extensions in sync (same Quarkus version)","Assert identity attributes in application-level integration tests","Log identity attribute names at startup debugging when augmentation behavior changes"],"tags":["oidc","security-identity","quarkus","test-assertion"],"backgroundTag":"missing-security-identity-attribute","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}