{"record":{"id":"2608d4eb4d705b55","repo":"spring-projects/spring-security","slug":"oauth-2-0-token-exchange-parameter-parameternam","errorCode":null,"errorMessage":"OAuth 2.0 Token Exchange parameter: ${parameterName} - The provided value is not supported by this authorization server. Supported values are urn:ietf:params:oauth:token-type:access_token and urn:ietf:params:oauth:token-type:jwt.","messagePattern":"OAuth 2\\.0 Token Exchange parameter: (.+?) - The provided value is not supported by this authorization server\\. Supported values are urn:ietf:params:oauth:token-type:access_token and urn:ietf:params:oauth:token-type:jwt\\.","errorType":"error_code","errorClass":"OAuth2AuthenticationException","httpStatus":400,"severity":"error","filePath":"oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2TokenExchangeAuthenticationConverter.java","lineNumber":208,"sourceCode":"\t\tAssert.notNull(clientPrincipal, \"clientPrincipal cannot be null\");\n\n\t\treturn new OAuth2TokenExchangeAuthenticationToken(requestedTokenType, subjectToken, subjectTokenType,\n\t\t\t\tclientPrincipal, actorToken, actorTokenType, new LinkedHashSet<>(resources),\n\t\t\t\tnew LinkedHashSet<>(audiences), requestedScopes, additionalParameters);\n\t}\n\n\tprivate static void validateTokenType(String parameterName, String tokenTypeValue) {\n\t\tif (!SUPPORTED_TOKEN_TYPES.contains(tokenTypeValue)) {\n\t\t\tOAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.UNSUPPORTED_TOKEN_TYPE,\n\t\t\t\t\tString.format(\"OAuth 2.0 Token Exchange parameter: %s\", parameterName), TOKEN_TYPE_IDENTIFIERS_URI);\n\t\t\t// @formatter:off\n\t\t\tString message = String.format(\n\t\t\t\t\t\"OAuth 2.0 Token Exchange parameter: %s - \" +\n\t\t\t\t\t\"The provided value is not supported by this authorization server. \" +\n\t\t\t\t\t\"Supported values are %s and %s.\",\n\t\t\t\t\tparameterName, ACCESS_TOKEN_TYPE_VALUE, JWT_TOKEN_TYPE_VALUE);\n\t\t\t// @formatter:on\n\t\t\tthrow new OAuth2AuthenticationException(error, message);\n\t\t}\n\t}\n\n\tprivate static boolean isValidUri(String uri) {\n\t\ttry {\n\t\t\tURI validUri = new URI(uri);\n\t\t\treturn validUri.isAbsolute() && validUri.getFragment() == null;\n\t\t}\n\t\tcatch (URISyntaxException ex) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n}\n","sourceCodeStart":190,"sourceCodeEnd":223,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2TokenExchangeAuthenticationConverter.java#L190-L223","documentation":"OAuth2TokenExchangeAuthenticationConverter.validateTokenType rejects a Token Exchange (RFC 8693) request whose subject_token or (if present) actor_token uses a token_type identifier this authorization server does not support. The error message explicitly lists the only accepted values: urn:ietf:params:oauth:token-type:access_token and urn:ietf:params:oauth:token-type:jwt. The resulting OAuth2AuthenticationException carries the formatted message.","triggerScenarios":"A POST to the token endpoint with grant_type=urn:ietf:params:oauth:grant-type:token_exchange where subject_token_type (or actor_token_type) is set to an unsupported identifier such as urn:ietf:params:oauth:token-type:id_token, saml2, or any arbitrary string.","commonSituations":"Clients exchanging ID tokens instead of access tokens (id_token token-type is not enabled); SDKs defaulting to SAML or refresh_token type identifiers; misconfigured service-to-service exchange code copied from a different authorization server that supports more token types.","solutions":["Set subject_token_type to urn:ietf:params:oauth:token-type:access_token (or urn:ietf:params:oauth:token-type:jwt) exactly as spelled.","If you hold an ID token, either enable id_token support server-side via a custom token exchange handler or obtain an access token first and exchange that.","Verify actor_token_type, if sent, also uses one of the two supported URIs, or omit actor_token entirely.","Check the server's Token Exchange configuration to confirm which token types are actually enabled before calling."],"exampleFix":"// before\nbody.put(\"subject_token\", token);\nbody.put(\"subject_token_type\", \"urn:ietf:params:oauth:token-type:id_token\");\n// after\nbody.put(\"subject_token\", token);\nbody.put(\"subject_token_type\", \"urn:ietf:params:oauth:token-type:access_token\");","handlingStrategy":"validation","validationCode":"const SUPPORTED = ['urn:ietf:params:oauth:token-type:access_token','urn:ietf:params:oauth:token-type:jwt'];\nfunction validateTokenExchange(body) {\n  const errs = [];\n  if (!SUPPORTED.includes(body.subject_token_type)) errs.push('subject_token_type must be ' + SUPPORTED.join(' or '));\n  if (body.actor_token_type && !SUPPORTED.includes(body.actor_token_type)) errs.push('actor_token_type must be ' + SUPPORTED.join(' or '));\n  return errs;\n}","typeGuard":"function hasSupportedTokenType(body) {\n  const ok = t => t === 'urn:ietf:params:oauth:token-type:access_token'\n              || t === 'urn:ietf:params:oauth:token-type:jwt';\n  return body != null && ok(body.subject_token_type)\n    && (!body.actor_token_type || ok(body.actor_token_type));\n}","tryCatchPattern":"try {\n  exchanged = tokenExchange(subjectToken, subjectTokenType);\n} catch (OAuth2AuthenticationException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Token Exchange parameter\")) {\n    logger.warn(\"Unsupported token_type: {} — use access_token or jwt URIs\", subjectTokenType);\n    // fall back to obtaining an access token first, then retry the exchange\n  } else throw e;\n}","preventionTips":["Hardcode the exact URN constants; never type token-type URIs from memory.","Exchange access tokens or JWTs only — convert ID tokens to access tokens first if the server does not accept id_token type.","Verify server-side token exchange configuration to confirm the supported token types.","Share the URN constants between client and provisioning code so they cannot drift."],"tags":["oauth2","token-exchange","rfc8693","unsupported-value"],"backgroundTag":"unsupported-enum-value","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"}