Spring OAuth2 JWT添加自定义Payload属性技术咨询
Hey there! I see you've got a working Spring OAuth2 setup with JWT tokens, and you want to add custom attributes like the user's full name to the JWT payload. Let's break down the steps to make this happen, starting with your existing code.
Step 1: Create a Custom Token Enhancer
The key to adding custom claims is building a TokenEnhancer implementation that injects your desired attributes into the token's additional information. This runs before the token is converted to JWT, so we can safely add user-specific data here.
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.TokenEnhancer; import org.springframework.security.core.userdetails.UserDetails; import java.util.HashMap; import java.util.Map; public class CustomTokenEnhancer implements TokenEnhancer { @Override public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { // Fetch the authenticated user's details UserDetails userDetails = (UserDetails) authentication.getPrincipal(); // Add your custom claims here Map<String, Object> additionalInfo = new HashMap<>(); // Replace with your actual user attribute (e.g., getFullName() if you have a custom UserDetails) additionalInfo.put("full_name", userDetails.getUsername()); additionalInfo.put("user_id", ((CustomUserDetails) userDetails).getId()); // Example of a custom field ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo); return accessToken; } }
Important Note: If you're using a custom UserDetails implementation (instead of the default User class), make sure it includes fields like fullName or userId, and cast userDetails to your custom class to access those fields.
Step 2: Update Your Authorization Server Configuration
Next, we need to register the custom enhancer and add it to the TokenEnhancerChain alongside your existing JwtAccessTokenConverter. This ensures our custom claims are added before the token is signed and converted to JWT.
Update your AuthorizationServerConfig class:
import org.springframework.context.annotation.Bean; import org.springframework.security.oauth2.provider.token.TokenEnhancer; import org.springframework.security.oauth2.provider.token.TokenEnhancerChain; import java.util.Arrays; @Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { // ... your existing fields and autowired dependencies ... // Register the custom token enhancer as a Spring bean @Bean public TokenEnhancer customTokenEnhancer() { return new CustomTokenEnhancer(); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { TokenEnhancerChain enhancerChain = new TokenEnhancerChain(); // Order matters: first apply custom enhancements, then convert to JWT enhancerChain.setTokenEnhancers(Arrays.asList(customTokenEnhancer(), accessTokenConverter)); endpoints.tokenStore(tokenStore) .accessTokenConverter(accessTokenConverter) .tokenEnhancer(enhancerChain) .authenticationManager(authenticationManager); } // ... your other existing methods ... }
Step 3: Verify the Custom Claims
After making these changes, generate a new access token (via your OAuth2 flow) and decode it (use tools like jwt.io to inspect the payload). You should see your custom claims (like full_name) included in the JWT body.
Bonus: Access Custom Claims in the Resource Server
If you need to retrieve these custom claims in your resource server endpoints, you can pull them from the authentication object:
import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Map; @RestController public class UserInfoController { @GetMapping("/api/user/profile") public Map<String, Object> getProfile(Authentication authentication) { OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails(); Map<String, Object> tokenPayload = details.getDecodedDetails(); // Extract custom claims String fullName = (String) tokenPayload.get("full_name"); Long userId = (Long) tokenPayload.get("user_id"); // Return or use the data as needed tokenPayload.put("greeting", "Hello, " + fullName + "!"); return tokenPayload; } }
Quick Check of Your Existing Code
Your current setup is already well-structured—you just missed the custom TokenEnhancer to inject additional claims. The rest of your configuration (WebSecurityConfig, ResourceServerConfig) doesn't need major changes, just ensure your UserDetailsService returns a user object that includes the custom attributes you want to add to the JWT.
内容的提问来源于stack exchange,提问作者Denis Stephanov

