Reputation: 120
I am implementing a oauth2 rest server using spring 4 and spring oauth2. Response can be either xml or json as specifeid by the client request header. But am getting issues from oauth2 when ever I try to access the token it supports only JSON (application/json), its not supporting xml(application/xml).
Am getting error as:
HTTP Status 406 -
type Status report
message
description The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.
Apache Tomcat/7.0.54
My security configuration is as follows:
@Configuration
@EnableWebSecurity(debug = true)
@ComponentScan(basePackages = { "org.bluez.logiczweb.config.security.handler" })
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final static String applicationName = "crm";
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends
ResourceServerConfigurerAdapter {
@Autowired
private HeaderOnlyOAuth2ExceptionRenderer headerOnlyExceptionRender;
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(applicationName);
}
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(
SessionCreationPolicy.STATELESS);
http.requestMatchers().and().authorizeRequests()
.antMatchers("/rest/accounts")
.access("#oauth2.hasScope('read')").and().httpBasic()
.authenticationEntryPoint(clientAuthenticationEntryPoint());
// // .apply(new OAuth2ServerConfigurer())
// .tokenStore(new InMemoryTokenStore())
// .resourceId(applicationName);
}
@Bean
public OAuth2AccessDeniedHandler oauthAccessDeniedHandler() {
OAuth2AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler();
accessDeniedHandler.setExceptionRenderer(headerOnlyExceptionRender);
return accessDeniedHandler;
}
@Bean
public OAuth2AuthenticationEntryPoint clientAuthenticationEntryPoint() {
OAuth2AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
authenticationEntryPoint.setRealmName("sparklr2/client");
authenticationEntryPoint.setTypeName("Basic");
authenticationEntryPoint
.setExceptionRenderer(headerOnlyExceptionRender);
return authenticationEntryPoint;
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends
AuthorizationServerConfigurerAdapter {
@Autowired
private TokenStore tokenStore;
@Autowired
private AuthenticationManager authenticationManager;
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
final String scopes[] = "read,write,trust".split(",");
final String secret = "123456";
final String[] authorizedGrantTypes = { "password",
"authorization_code", "refresh_token" };
final String authorities = "ROLE_USER";
clients.inMemory().withClient("android-crm")
.resourceIds(applicationName).scopes(scopes)
.authorities(authorities)
.authorizedGrantTypes(authorizedGrantTypes).secret(secret)
.and().withClient("ios-crm").resourceIds(applicationName)
.scopes(scopes).authorities(authorities)
.authorizedGrantTypes(authorizedGrantTypes).secret(secret);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints.tokenStore(tokenStore).authenticationManager(
authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)
throws Exception {
oauthServer.realm("sparklr2/client");
}
@Bean
public ApprovalStore approvalStore() throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
/*
* @Bean public OAuth2AccessDeniedHandler oauthAccessDeniedHandler(){
* OAuth2AccessDeniedHandler accessDeniedHandler=new
* OAuth2AccessDeniedHandler();
*
* return accessDeniedHandler; }
*/
}
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
@Bean
TextEncryptor textEncryptor() {
return Encryptors.noOpText();
}
@Bean
public UserDetailsService userDetailsServiceBean() throws Exception {
return super.userDetailsServiceBean();
}
protected void configure(AuthenticationManagerBuilder authManagerBuilder)
throws Exception {
authManagerBuilder.userDetailsService(userDetailsServiceBean())
.passwordEncoder(passwordEncoder()).and()
.inMemoryAuthentication().withUser("admin").password("admin")
.roles("ADMIN", "USER");
}
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
}
My response as JSON is:
{
"access_token": "27f93b60-a2ab-4ae6-90c9-81124cc7d10b",
"token_type": "bearer",
"refresh_token": "6bb643cf-3eda-402a-bb6d-5f3b05e56bee",
"expires_in": 43199,
"scope": "read"
}
I want it as XML
My MVC Configuration is as follows:
@EnableWebMvc
@Configuration
public class WebMVCConfiguration extends WebMvcConfigurationSupport {
@Bean
public ExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver() {
ExceptionHandlerExceptionResolver exceptionResolver = new ExceptionHandlerExceptionResolver();
exceptionResolver.setOrder(0);
exceptionResolver.setMessageConverters(messageConverters());
return exceptionResolver;
}
@Bean
public List> messageConverters() {
List> messageConverters = new ArrayList>();
messageConverters.add(jsonHttpMessageConverter());
// messageConverters.add(stringHttpMessageConverter());
messageConverters.add(xmlConverter());
return messageConverters;
}
@Bean
public StringHttpMessageConverter stringHttpMessageConverter() {
return new StringHttpMessageConverter();
}
@Bean
public MappingJackson2HttpMessageConverter jsonHttpMessageConverter() {
return new MappingJackson2HttpMessageConverter();
}
@Bean
public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
return new ByteArrayHttpMessageConverter();
}
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
RequestMappingHandlerAdapter adapter = super
.requestMappingHandlerAdapter();
adapter.setOrder(0);
adapter.getMessageConverters().addAll(messageConverters());
adapter.getMessageConverters().add(byteArrayHttpMessageConverter());
return adapter;
}
@Bean
public Jaxb2Marshaller jaxbMarshaller() {
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller
.setPackagesToScan("org.bluez.logiczweb.core.models.vo.*");
return jaxb2Marshaller;
}
@Bean
public MarshallingHttpMessageConverter xmlConverter() {
MarshallingHttpMessageConverter converter = new MarshallingHttpMessageConverter(
jaxbMarshaller());
converter.setSupportedMediaTypes(Arrays
.asList(MediaType.APPLICATION_XML));
return converter;
}
}
please help me..
Upvotes: 1
Views: 2478
Reputation: 58124
MarshallingHttpMessageConverter
is not smart enough to convert access tokens. that's why Spring OAuth has a JaxbOAuth2AccessTokenMessageConverter
(and also a JaxbOAuth2ExceptionMessageConverter
). You need those, and you also need them in the OAuth2AuthenticationEntryPoint
and OAuth2AccessDeniedHandler
that get used in the /token
endpoint security (assuming your client wants Security errors to be rendered in XML as well). The current @EnableAuthorizationServer
support lets you inject your own AuthenticationEntryPoint
, but you'll need to extend AuthorizationServerSecurityConfiguration
yourself to override the AccessDeniedHandler
.
Upvotes: 3