[英]Spring boot Oauth2 grant_type password always return invalid_grant Bad Credentials
I am trying to create an API that is in charge of securing the rest of my APIs.我正在尝试创建一个负责保护其余 API 的 API。 This api has the functionality of generating the token for the users of the whole set.
该api具有为整个集合的用户生成令牌的功能。 Users must authenticate by clientId and secrt and with their username and password.
用户必须通过 clientId 和 secrt 以及他们的用户名和密码进行身份验证。 To test it I am using a postman request like this:
为了测试它,我使用了这样的邮递员请求:
curl --location --request POST 'http://localhost:5101/oauth/token' \
--header 'Authorization: Basic cHJ1ZWJhOnBydWViYQ==' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=usuario' \
--data-urlencode 'password=pass' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'scope=all'
The authorization header is composed of the clientId and its secret key.授权标头由 clientId 及其密钥组成。
I always get invalid_grant error when grant_type is password当grant_type是密码时,我总是收到invalid_grant 错误
{
"error": "invalid_grant",
"error_description": "Bad credentials"
}
When I use the grant_type client_credentials it works fine, it returns the client token.当我使用 grant_type client_credentials 时它工作正常,它返回客户端令牌。
This is my Main class这是我的主课
@EnableAuthorizationServer
@SpringBootApplication
public class Auth implements CommandLineRunner {
@Autowired
private BCryptPasswordEncoder passwordEncoder;
public static void main(String[] args) {
SpringApplication.run(Auth.class, args);
}
@Override
public void run(String... args) throws Exception {
// TODO Auto-generated method stub
String password = "pass";
for (int i = 0; i < 4; i++) {
String pasBcript = passwordEncoder.encode(password);
System.out.println(pasBcript);
}
}
}
I have used run method to obtain passwords for my database users.我使用 run 方法为我的数据库用户获取密码。
SecurityConfig安全配置
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
// @Autowired private AuthenticationEventPublisher eventPublisher;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
//.and().authenticationEventPublisher(eventPublisher);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
AuthorizationServerConfig授权服务器配置
@RefreshScope
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{
@Autowired
private Environment env;
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()") //Endpoint para generar el token public, POST /oauth/token
.checkTokenAccess("isAuthenticated()"); // validar el toekn
}
// Doble autenticacion cliente (aplicacion) y usuarios
// hay que envioar dos crecenciales las de la aplicacion y las del usuario
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("prueba")
.secret(passwordEncoder.encode("prueba"))
.scopes("all") // Permiso de la app prueba
.authorizedGrantTypes("password", "refresh_token", "client_credentials") // Tipo de autenticación, como vamos a obtener el token
.accessTokenValiditySeconds(3600)
.refreshTokenValiditySeconds(3600);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter()));
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore()) // Componente que se encarga de guardar el token
.accessTokenConverter(accessTokenConverter())
.tokenEnhancer(tokenEnhancerChain);
}
@Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();
// Codigo secreto para firmar
tokenConverter.setSigningKey(Base64.getEncoder().encodeToString(env.getProperty("config.security.oauth.jwt.key").getBytes()));
return tokenConverter;
}
}
UserService用户服务
@Service
public class UserService implements IUserService, UserDetailsService {
Logger logger = LoggerFactory.getLogger(UserService.class);
@Autowired
private IUserRepository userRepository;
@Override
public AuthUser loadUserByUsername(String username) {
return userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
}
}
POM.XML POM文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.11</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>net.example.auth</groupId>
<artifactId>auth-service</artifactId>
<version>3.0.0</version>
<packaging>jar</packaging>
<name>Auth</name>
<description></description>
<properties>
<java.version>11</java.version>
<spring-cloud.version>2020.0.4</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I'm sure the credentials are fine, both for the client and for the user.我确信凭据对于客户端和用户来说都很好。 I have checked it several times.
我已经检查了几次。 I already ran out of ideas, any help please??
我已经没有想法了,有什么帮助吗??
The problem was in userRepository , I was looking for users by username , and in my database the username is the login field.问题出在userRepository 中,我正在通过username查找用户,而在我的数据库中, username是登录字段。 I have changed username to login in the repository and now it works correctly.
我已将用户名更改为登录存储库,现在它可以正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.