Skip to content

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

Closed
@wwpwan

Description

@wwpwan

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

Handling error: UnsupportedGrantTypeException, Unsupported grant type: password

Activity

wwpwan

wwpwan commented on Mar 2, 2017

@wwpwan
Author

步骤一、在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

wwpwan commented on Mar 2, 2017

@wwpwan
Author

出现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 commented on Mar 3, 2017

@dewafer
Collaborator

感谢您的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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @dewafer@wwpwan

        Issue actions

          Handling error: UnsupportedGrantTypeException, Unsupported grant type: password · Issue #3 · newnil/oauth2-family-barrel