Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling error: UnsupportedGrantTypeException, Unsupported grant type: password #3

Closed
wwpwan opened this issue Mar 2, 2017 · 3 comments
Labels

Comments

@wwpwan
Copy link

wwpwan commented Mar 2, 2017

我配置了一个grant_type=password的客户端,授权访问时会报:

Handling error: UnsupportedGrantTypeException, Unsupported grant type: password
@wwpwan
Copy link
Author

wwpwan commented Mar 2, 2017

步骤一、在com.newnil.cas.oauth2.provider.config中的SecurityConfig增加如下代码:

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

步骤二、在com.newnil.cas.oauth2.provider.config.OAuth2ServerConfig中的OAuth2ServerConfig里面增加如下代码:

@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;

执行上面就可以支持grant_type=password了,但是----com.newnil.cas.oauth2.provider.service.DatabaseTokenStoreService中第51行、90行(accessTokenRepository.save(entityToSave);)、111行(refreshTokenRepository.save(entityToSave);)会报:

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of org.springframework.security.oauth2.common.OAuth2RefreshToken: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information 
at [Source: {"value":"422bed46-c545-49cb-8b95-754705309952","expiration":1491041632698}; line: 1, column: 1]

@wwpwan
Copy link
Author

wwpwan commented Mar 2, 2017

出现json转转化错误的原因是org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken中没有默认构造方法,com.newnil.cas.oauth2.provider.dao.entity.util.JsonPersistenceConverters中使用com.fasterxml.jackson.databind.ObjectMapper进行json转换时就会出错。我的解决方法是定一个MyDefaultExpiringOAuth2RefreshToken继承自DefaultExpiringOAuth2RefreshToken如下:

package com.newnil.cas.oauth2.provider.util;
import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken;
import java.util.Date;
public class MyDefaultExpiringOAuth2RefreshToken extends DefaultExpiringOAuth2RefreshToken {
   /**
   * @param value
   * @param expiration
   */
    public MyDefaultExpiringOAuth2RefreshToken(String value, Date expiration) {
        super(value, expiration);
    }

    public MyDefaultExpiringOAuth2RefreshToken(){
        super("",new Date());
    }
}

然后使用该类进行转换转换后再拷贝给DefaultExpiringOAuth2RefreshToken进行中转,我在. com.newnil.cas.oauth2.provider.dao.entity.util直接中转如:

@Slf4j
public class OAuth2RefreshTokenPersistenceConverters implements  AttributeConverter<DefaultExpiringOAuth2RefreshToken, String> {
  private JsonPersistenceConverters<MyDefaultExpiringOAuth2RefreshToken> jsonPersistenceConverters = new JsonPersistenceConverters<>();

  private static final ObjectMapper objectMapper = new ObjectMapper();
  @Override
  public String convertToDatabaseColumn(DefaultExpiringOAuth2RefreshToken attribute) {
      //return jsonPersistenceConverters.convertToJson(attribute);
      MyDefaultExpiringOAuth2RefreshToken my = new MyDefaultExpiringOAuth2RefreshToken(attribute.getValue(),attribute.getExpiration());
      try {
          return objectMapper.writeValueAsString(my);
      } catch (JsonProcessingException e) {
          log.error("Serialize " + attribute + " error.", e);
          throw new RuntimeException(e);
      }
  }

  @Override
  public DefaultExpiringOAuth2RefreshToken convertToEntityAttribute(String dbData) {
      //return jsonPersistenceConverters.convertFromJson(dbData, MyDefaultExpiringOAuth2RefreshToken.class);
      try {
          MyDefaultExpiringOAuth2RefreshToken my =  (MyDefaultExpiringOAuth2RefreshToken)objectMapper.readValue(dbData, MyDefaultExpiringOAuth2RefreshToken.class);
          return new DefaultExpiringOAuth2RefreshToken(my.getValue(),my.getExpiration());
      } catch (IOException e) {
          log.error("Deserialize OAuth2AccessToken error.", e);
          throw new RuntimeException(e);
      }
  }
}

@dewafer dewafer added the bug label Mar 3, 2017
@dewafer
Copy link
Collaborator

dewafer commented Mar 3, 2017

感谢您的issue。

  1. 根据spring security oauth2的文档,开启grant type password的支持需要暴露AuthenticationManager并且在AuthorizationServerEndpointsConfigurer配置时注入。
  2. 报错是因为Jackson不知道如何正确反序列化OAuth2RefreshToken。Spring为OAuth2AccessToken提供了Serializer和Deserializer,但没有为OAuth2RefreshToken提供。在这里我们仿Spring提供的OAuth2AccessTokenJackson2SerializerOAuth2AccessTokenJackson2Deserializer创建了对应的OAuth2RefreshTokenJackson2SerializerOAuth2RefreshTokenJackson2Deserializer,并在ObjectMapper上注册,修复了无法反序列化的问题。(没有提供Jackson1的Serializer和Deserializer是因为我们的项目默认使用Jackson2,并不会用到Jackson1)

@dewafer dewafer closed this as completed Mar 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants