{"record":{"id":"6a127cc976d51f2b","repo":"spring-projects/spring-security","slug":"cookie-token-was-not-base64-encoded-value-was-c","errorCode":null,"errorMessage":"Cookie token was not Base64 encoded; value was '<cookieValue>'","messagePattern":"Cookie token was not Base64 encoded; value was '<cookieValue>'","errorType":"exception","errorClass":"InvalidCookieException","httpStatus":null,"severity":"warning","filePath":"web/src/main/java/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServices.java","lineNumber":220,"sourceCode":"\t}\n\n\t/**\n\t * Decodes the cookie and splits it into a set of token strings using the \":\"\n\t * delimiter.\n\t * @param cookieValue the value obtained from the submitted cookie\n\t * @return the array of tokens.\n\t * @throws InvalidCookieException if the cookie was not base64 encoded.\n\t */\n\tprotected String[] decodeCookie(String cookieValue) throws InvalidCookieException {\n\t\tfor (int j = 0; j < cookieValue.length() % 4; j++) {\n\t\t\tcookieValue = cookieValue + \"=\";\n\t\t}\n\t\tString cookieAsPlainText;\n\t\ttry {\n\t\t\tcookieAsPlainText = new String(Base64.getDecoder().decode(cookieValue.getBytes()));\n\t\t}\n\t\tcatch (IllegalArgumentException ex) {\n\t\t\tthrow new InvalidCookieException(\"Cookie token was not Base64 encoded; value was '\" + cookieValue + \"'\");\n\t\t}\n\t\tString[] tokens = StringUtils.delimitedListToStringArray(cookieAsPlainText, DELIMITER);\n\t\tfor (int i = 0; i < tokens.length; i++) {\n\t\t\ttokens[i] = URLDecoder.decode(tokens[i], StandardCharsets.UTF_8);\n\t\t}\n\t\treturn tokens;\n\t}\n\n\t/**\n\t * Inverse operation of decodeCookie.\n\t * @param cookieTokens the tokens to be encoded.\n\t * @return base64 encoding of the tokens concatenated with the \":\" delimiter.\n\t */\n\tprotected String encodeCookie(String[] cookieTokens) {\n\t\tStringBuilder sb = new StringBuilder();\n\t\tfor (int i = 0; i < cookieTokens.length; i++) {\n\t\t\tsb.append(URLEncoder.encode(cookieTokens[i], StandardCharsets.UTF_8));\n\t\t\tif (i < cookieTokens.length - 1) {","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/web/src/main/java/org/springframework/security/web/authentication/rememberme/AbstractRememberMeServices.java#L202-L238","documentation":"AbstractRememberMeServices.decodeCookie Base64-decodes the remember-me cookie value before splitting it into tokens. If the value is not valid Base64, Base64.getDecoder() throws IllegalArgumentException which is rethrown as InvalidCookieException so the invalid cookie can be rejected (and typically cancelled).","triggerScenarios":"Calling decodeCookie (via the cookieTokens extraction path of autoLogin) with a cookie value that contains characters outside the Base64 alphabet, or that has been tampered with, truncated, or otherwise corrupted in transit.","commonSituations":"Manual cookie manipulation; a proxy or application server rewriting/truncating the cookie; client code writing the cookie without Base64 encoding; leftover cookies from an older scheme after upgrading the remember-me implementation or changing the encoding.","solutions":["Clear the invalid cookie in the browser (or have the app call cancelCookie on InvalidCookieException, which the default implementation does) and log in again.","Verify the client sets the cookie exactly as the server returned it, without decoding/encoding or trimming '=' padding.","Check intermediary infrastructure (proxies, WAFs) for cookie rewriting.","If you generate remember-me cookies yourself, encode with Base64.getEncoder().encodeToString(...)."],"exampleFix":"// before\ncookie.setValue(username + \":\" + token); // not Base64 -> InvalidCookieException\n// after\ncookie.setValue(Base64.getEncoder().encodeToString((username + \":\" + token).getBytes(StandardCharsets.UTF_8)));","handlingStrategy":"try-catch","validationCode":"boolean isBase64(String v) {\n    try { Base64.getDecoder().decode(v.getBytes(StandardCharsets.UTF_8)); return true; }\n    catch (IllegalArgumentException e) { return false;\n}","typeGuard":"boolean isValidRememberMeCookie(Cookie c) {\n    return c != null && c.getValue() != null\n        && c.getValue().matches(\"[A-Za-z0-9+/]+=*\");\n}","tryCatchPattern":"try {\n    Authentication a = rememberMeServices.autoLogin(request, response);\n} catch (InvalidCookieException e) {\n    ((AbstractRememberMeServices) rememberMeServices).cancelCookie(request, response);\n    // continue unauthenticated\n}","preventionTips":["Never rewrite/trim the cookie value client-side; store exactly what the server set","Watch for proxies/WAFs mangling cookies and fix them server-side","After changing remember-me key/implementation, invalidate old cookies","Keep the default cancelCookie-on-invalid behavior so bad cookies are cleared automatically"],"tags":["cookie","base64","remember-me","spring-security"],"backgroundTag":"invalid-argument-format","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"}