{"record":{"id":"9fc8412e52cb8926","repo":"spring-projects/spring-security","slug":"the-presented-anonymousauthenticationtoken-does-no","errorCode":null,"errorMessage":"The presented AnonymousAuthenticationToken does not contain the expected key","messagePattern":"The presented AnonymousAuthenticationToken does not contain the expected key","errorType":"exception","errorClass":"BadCredentialsException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationProvider.java","lineNumber":55,"sourceCode":" */\npublic class AnonymousAuthenticationProvider implements AuthenticationProvider, MessageSourceAware {\n\n\tprotected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();\n\n\tprivate String key;\n\n\tpublic AnonymousAuthenticationProvider(String key) {\n\t\tAssert.hasLength(key, \"A Key is required\");\n\t\tthis.key = key;\n\t}\n\n\t@Override\n\tpublic @Nullable Authentication authenticate(Authentication authentication) throws AuthenticationException {\n\t\tif (!supports(authentication.getClass())) {\n\t\t\treturn null;\n\t\t}\n\t\tif (this.key.hashCode() != ((AnonymousAuthenticationToken) authentication).getKeyHash()) {\n\t\t\tthrow new BadCredentialsException(this.messages.getMessage(\"AnonymousAuthenticationProvider.incorrectKey\",\n\t\t\t\t\t\"The presented AnonymousAuthenticationToken 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\t@Override\n\tpublic void setMessageSource(MessageSource messageSource) {\n\t\tAssert.notNull(messageSource, \"messageSource cannot be null\");\n\t\tthis.messages = new MessageSourceAccessor(messageSource);\n\t}\n\n\t@Override\n\tpublic boolean supports(Class<?> authentication) {\n\t\treturn (AnonymousAuthenticationToken.class.isAssignableFrom(authentication));","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/core/src/main/java/org/springframework/security/authentication/AnonymousAuthenticationProvider.java#L37-L73","documentation":"AnonymousAuthenticationProvider.authenticate() compares the shared key hash of the incoming AnonymousAuthenticationToken with its configured key. On mismatch it throws BadCredentialsException 'The presented AnonymousAuthenticationToken does not contain the expected key'. The shared-key protects against forged anonymous tokens.","triggerScenarios":"An AnonymousAuthenticationToken was created with a different key string than the one configured on AnonymousAuthenticationProvider (via AnonymousAuthenticationFilter).","commonSituations":"Changing the anonymous key in the filter but not the provider (or vice versa); multiple app nodes with different configured keys; tokens deserialized from an old session after key rotation; copying example code with mismatched keys.","solutions":["Use the same key for AnonymousAuthenticationFilter and AnonymousAuthenticationProvider","If you don't need a custom key, use the same constant/SecureRandom-generated key shared between both beans","Clear old sessions after rotating the key so stale tokens are dropped","Ensure all cluster nodes share the same configured key"],"exampleFix":"// before\nnew AnonymousAuthenticationFilter(\"uniqueKey\", \"anon\", authorities);\nnew AnonymousAuthenticationProvider(\"differentKey\");\n// after\nString key = \"uniqueKey\";\nnew AnonymousAuthenticationFilter(key, \"anon\", authorities);\nnew AnonymousAuthenticationProvider(key);","handlingStrategy":"validation","validationCode":"AnonymousAuthenticationFilter filter = new AnonymousAuthenticationFilter(key, \"anonUser\", authorities);\nAnonymousAuthenticationProvider provider = new AnonymousAuthenticationProvider(key);\nassert key != null && !key.isBlank();","typeGuard":"boolean hasValidKey(AnonymousAuthenticationToken t, String key) { return key != null && key.hashCode() == t.getKeyHash(); }","tryCatchPattern":"try { return provider.authenticate(auth); } catch (BadCredentialsException e) { log.warn(\"Anonymous token key mismatch, dropping token\"); return null; }","preventionTips":["Define the shared key once as a constant/bean and inject it into both filter and provider","Clear sessions after rotating the key","Keep keys identical across all cluster nodes"],"tags":["spring-security","anonymous-authentication","shared-key"],"backgroundTag":"authentication-required","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}