{"record":{"id":"3952afacfe4aa172","repo":"spring-projects/spring-security","slug":"runasimplauthenticationprovider-incorrectkey","errorCode":"RunAsImplAuthenticationProvider.incorrectKey","errorMessage":"The presented RunAsUserToken does not contain the expected key","messagePattern":"The presented RunAsUserToken does not contain the expected key","errorType":"exception","errorClass":"BadCredentialsException","httpStatus":401,"severity":"error","filePath":"access/src/main/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java","lineNumber":68,"sourceCode":"@NullUnmarked\n@Deprecated\npublic class RunAsImplAuthenticationProvider implements InitializingBean, AuthenticationProvider, MessageSourceAware {\n\n\tprotected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();\n\n\t@SuppressWarnings(\"NullAway.Init\")\n\tprivate @Nullable String key;\n\n\t@Override\n\tpublic void afterPropertiesSet() {\n\t\tAssert.notNull(this.key, \"A Key is required and should match that configured for the RunAsManagerImpl\");\n\t}\n\n\t@Override\n\tpublic Authentication authenticate(Authentication authentication) throws AuthenticationException {\n\t\tRunAsUserToken token = (RunAsUserToken) authentication;\n\t\tif (token.getKeyHash() != this.key.hashCode()) {\n\t\t\tthrow new BadCredentialsException(this.messages.getMessage(\"RunAsImplAuthenticationProvider.incorrectKey\",\n\t\t\t\t\t\"The presented RunAsUserToken does not contain the expected key\"));\n\t\t}\n\t\treturn authentication;\n\t}\n\n\tpublic String getKey() {\n\t\treturn this.key;\n\t}\n\n\tpublic void setKey(String key) {\n\t\tthis.key = key;\n\t}\n\n\t@Override\n\tpublic void setMessageSource(MessageSource messageSource) {\n\t\tthis.messages = new MessageSourceAccessor(messageSource);\n\t}\n","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/access/src/main/java/org/springframework/security/access/intercept/RunAsImplAuthenticationProvider.java#L50-L86","documentation":"RunAsImplAuthenticationProvider validates RunAsUserToken instances by comparing the token's key hash with the provider's configured key. If they do not match, the token is not trusted and BadCredentialsException is thrown. This prevents forged run-as identity escalation.","triggerScenarios":"authenticate() is given a RunAsUserToken whose getKeyHash() differs from hashCode() of the RunAsManager's configured secure key — typically the RunAsManager and RunAsImplAuthenticationProvider were configured with different keys.","commonSituations":"Copy-paste configuration where the run-as key differs between the <run-as-manager>/RunAsManagerImpl and the authentication provider; multiple applications sharing a token cache but keys were changed; bean wiring pulling the wrong provider.","solutions":["Ensure the exact same key string is set on both RunAsManagerImpl and RunAsImplAuthenticationProvider","Externalize the shared key into a property so both beans reference one value","Verify the authentication provider handling run-as tokens is registered for RunAsUserToken type","Check for stale serialized tokens from a previous key and re-authenticate"],"exampleFix":"// before\nnew RunAsManagerImpl(\"keyOne\", \"ROLE_RUNAS\");\nnew RunAsImplAuthenticationProvider(\"keyTwo\");\n\n// after\nString key = \"shared-secure-key\";\nnew RunAsManagerImpl(key, \"ROLE_RUNAS\");\nnew RunAsImplAuthenticationProvider(key);","handlingStrategy":"validation","validationCode":"if (runAsToken instanceof RunAsUserToken t && t.getKeyHash() != sharedKey.hashCode()) {\n    throw new IllegalStateException(\"RunAs key mismatch before provider call\");\n}","typeGuard":"boolean isTrustedRunAsToken(Authentication auth, String key) {\n    return auth instanceof RunAsUserToken t && t.getKeyHash() == key.hashCode();\n}","tryCatchPattern":"try {\n    return provider.authenticate(token);\n} catch (BadCredentialsException e) {\n    throw new AuthenticationServiceException(\"RunAs key mismatch\", e);\n}","preventionTips":["Define the run-as key once in shared configuration","Never change the key without invalidating in-flight tokens","Verify provider ordering in the AuthenticationManager"],"tags":["spring-security","run-as","bad-credentials","key-mismatch","authentication"],"backgroundTag":"authentication-required","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}