For some reason, the input field to write the bearer access token is not showing as an implicit param on swagger UI.
This makes it impossible to access all endpoints because they require authentication.
What is showing :
What should show :
These images are from different projects but with the same configuration classes. This is the annotation I'm using to mark the endpoints that require the bearer access token.
#ApiImplicitParam(name = "Authorization", value = "Bearer Token", required = true,
allowEmptyValue = false, paramType = "header", example = "Bearer access_token")
And lastly, this is the token configuration class :
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("user")
.secret("senha")
.scopes("read", "write")
.authorizedGrantTypes("password")
.accessTokenValiditySeconds(1800);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager);
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
}
Would appreciate if someone could help with this problem I'm having for quite a few hours. Thank you.
Related
I'm trying to get a new access token using a refresh token in Spring Boot with OAuth2. It should be done as following: POST: url/oauth/token?grant_type=refresh_token&refresh_token=....
It works fine if I'm using InMemoryTokenStore because the token is tiny and contains only digits/letters but right now I'm using a JWT token and as you probably know it has 3 different parts which probably are breaking the code.
I'm using the official migration guide to 2.4.
When I try to access the URL above, I'm getting the following message:
{
"error": "invalid_token",
"error_description": "Cannot convert access token to JSON"
}
How do I pass a JWT token in the params? I tried to set a breakpoint on that message, so I could see what the actual argument was, but it didn't get to it for some reason.
/**
* The Authorization Server is responsible for generating tokens specific to a client.
* Additional information can be found here: https://www.devglan.com/spring-security/spring-boot-security-oauth2-example.
*/
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Value("${user.oauth2.client-id}")
private String clientId;
#Value("${user.oauth2.client-secret}")
private String clientSecret;
#Value("${user.oauth2.accessTokenValidity}")
private int accessTokenValidity;
#Value("${user.oauth2.refreshTokenValidity}")
private int refreshTokenValidity;
#Autowired
private ClientDetailsService clientDetailsService;
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient(clientId)
.secret(bCryptPasswordEncoder.encode(clientSecret))
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.scopes("read", "write", "trust")
.resourceIds("api")
.accessTokenValiditySeconds(accessTokenValidity)
.refreshTokenValiditySeconds(refreshTokenValidity);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.userApprovalHandler(userApprovalHandler())
.accessTokenConverter(accessTokenConverter());
}
#Bean
public UserApprovalHandler userApprovalHandler() {
ApprovalStoreUserApprovalHandler userApprovalHandler = new ApprovalStoreUserApprovalHandler();
userApprovalHandler.setApprovalStore(approvalStore());
userApprovalHandler.setClientDetailsService(clientDetailsService);
userApprovalHandler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
return userApprovalHandler;
}
#Bean
public TokenStore tokenStore() {
JwtTokenStore tokenStore = new JwtTokenStore(accessTokenConverter());
tokenStore.setApprovalStore(approvalStore());
return tokenStore;
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
final RsaSigner signer = new RsaSigner(KeyConfig.getSignerKey());
JwtAccessTokenConverter converter = new JwtAccessTokenConverter() {
private JsonParser objectMapper = JsonParserFactory.create();
#Override
protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
String content;
try {
content = this.objectMapper.formatMap(getAccessTokenConverter().convertAccessToken(accessToken, authentication));
} catch (Exception ex) {
throw new IllegalStateException("Cannot convert access token to JSON", ex);
}
Map<String, String> headers = new HashMap<>();
headers.put("kid", KeyConfig.VERIFIER_KEY_ID);
return JwtHelper.encode(content, signer, headers).getEncoded();
}
};
converter.setSigner(signer);
converter.setVerifier(new RsaVerifier(KeyConfig.getVerifierKey()));
return converter;
}
#Bean
public ApprovalStore approvalStore() {
return new InMemoryApprovalStore();
}
#Bean
public JWKSet jwkSet() {
RSAKey.Builder builder = new RSAKey.Builder(KeyConfig.getVerifierKey())
.keyUse(KeyUse.SIGNATURE)
.algorithm(JWSAlgorithm.RS256)
.keyID(KeyConfig.VERIFIER_KEY_ID);
return new JWKSet(builder.build());
}
}
I assume that the Cannot convert access token to JSON might have been due to incorrectly pasted token.
As for Invalid refresh token, it occurs because when JwtTokenStore reads the refresh token, it validates the scopes and revocation with InMemoryApprovalStore. However, for this implementation, the approvals are registered only during authorization through /oauth/authorize URL (Authorisation Code Grant) by the ApprovalStoreUserApprovalHandler.
Especially for the Authorisation Code Grant (authorization_code), you want to have this validation, so that the refresh token request will not be called with an extended scope without the user knowledge. Moreover, it's optional to store approvals for future revocation.
The solution is to fill the ApprovalStore with the Approval list for all resource owners either statically or dynamically. Additionally, you might be missing setting the user details service endpoints.userDetailsService(userDetailsService) which is used during the refresh process.
Update:
You can verify this by creating pre-filled InMemoryApprovalStore:
#Bean
public ApprovalStore approvalStore() {
InMemoryApprovalStore approvalStore = new InMemoryApprovalStore();
Date expirationDate = Date.from(Instant.now().plusSeconds(3600));
List<Approval> approvals = Stream.of("read", "write", "trust")
.map(scope -> new Approval("admin", "trusted", scope, expirationDate,
ApprovalStatus.APPROVED))
.collect(Collectors.toList());
approvalStore.addApprovals(approvals);
return approvalStore;
}
I would also take a look at implementing it in the storeRefreshToken()/storeAccessToken() methods of JwtTokenStore, as they have an empty implementation, and the method parameters contain all the necessary data.
I have configured my Oauth2 Authorization project with JWT. When I authorize using client credentials I gets the access token like as shown below. The expiry time is 43199
{
"access_token":"eyJhbGci........................",
"token_type": "bearer",
"expires_in": 43199,
"scope": "resource-access",
"jti": "45507f3e-2d8c-4dc8-95ce-295bb690cf3a"
}
I am not storing the tokens anywhere like DB or session etc, still If I invoke the same authorize token endpoint I gets the same access token with decreasing expiry time.
Not sure where this token is been stored, what I expect is to get a new token every time I invokes the token authorize endpoint.
Can anyone please help me on this
My custom AuthorizationServerConfigurerAdapter class is given below
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Value("${scopes}")
private Boolean checkUserScopes;
#Autowired
private DataSource dataSource;
#Autowired
private PasswordEncoder passwordEncoder;
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private ClientDetailsService clientDetailsService;
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Bean
public OAuth2RequestFactory requestFactory() {
CustomOauth2RequestFactory requestFactory = new CustomOauth2RequestFactory(clientDetailsService);
requestFactory.setCheckUserScopes(true);
return requestFactory;
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource).passwordEncoder(passwordEncoder);
}
#Bean
public TokenEndpointAuthenticationFilter tokenEndpointAuthenticationFilter() {
return new TokenEndpointAuthenticationFilter(authenticationManager, requestFactory());
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenEnhancer(jwtAccessTokenConverter())
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
if (checkUserScopes) {
endpoints.requestFactory(requestFactory());
}
}
#Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
CustomJwtTokenEnhancerConfig tokenEnhancer = new CustomJwtTokenEnhancerConfig();
tokenEnhancer.setKeyPair(new KeyStoreKeyFactory(new ClassPathResource("myjwt.jks"), "password".toCharArray()).getKeyPair("jwt"));
return tokenEnhancer;
}
}
JSON Web Token (JWT) authentication technique doesn't require database tables or data stores to keep the generated token. The token is generated by using cryptography algorithms.
When you call your login service, the token is generated by using a payload and a secret value. If your payload is the same, you won't get a new token value with the same secret value.
You can refer to this link for a little more information on how JWT works.
https://medium.com/vandium-software/5-easy-steps-to-understanding-json-web-tokens-jwt-1164c0adfcec
I'm creating a spring boot 2.0 application and trying to enable oauth2 security. I have Auth server and Resource server in the same application as of now. My client and user details as well as token generated are persisted in databases (mysql) and database schema is the same as provided by spring documentation. When I hit the '/oauth/token/' endpoint providing clientId and clientSecret in header and user's credentials in body using Postman, I'm getting access token successfully.
{
"access_token": "bef2d974-2e7d-4bf0-849d-d80e8021dc50",
"token_type": "bearer",
"refresh_token": "32ed6252-e7ee-442c-b6f9-d83b0511fcff",
"expires_in": 6345,
"scope": "read write trust"
}
But when I try to hit my rest api using this access token, I'm getting 401 Unauthorized error:
{
"timestamp": "2018-08-13T11:17:19.813+0000",
"status": 401,
"error": "Unauthorized",
"message": "Unauthorized",
"path": "/myapp/api/unsecure"
}
The rest APIs I'm hitting are as follows:
http://localhost:8080/myapp/api/unsecure
http://localhost:8080/myapp/api/secure
myapp is the context path of my application.
For 'secure' api, I have provided access token in request header as described in Spring documentation:
Authorization: Bearer bef2d974-2e7d-4bf0-849d-d80e8021dc50
Whereas for unsecure api, I have tried with and without Authentication header. In all cases I'm getting same error for both apis.
Also when I try to print currently authenticated user, its getting printed as anonymousUser.
What I want are as follows:
1) I want my secure api to be accessible only when access token is provided in request header.
2) I want my unsecure api to be accessible by unauthorised user.
3) I should get currently authenticated user using SecurityContextHolder when accessing secure url.
My WebSecurityConfigurerAdapter is as follows:
#Configuration
#EnableWebSecurity(debug=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Autowired
UserDetailsService userDetailsService;
#Autowired
private ClientDetailsService clientDetailsService;
#Bean
public PasswordEncoder userPasswordEncoder() {
return new BCryptPasswordEncoder(8);
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws
Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(userPasswordEncoder());
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws
Exception {
return super.authenticationManagerBean();
}
#Bean
#Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore
tokenStore){
TokenStoreUserApprovalHandler handler = new
TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new
DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
return handler;
}
#Bean
#Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws
Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.cors().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/index.html", "/**.js", "/**.css", "/").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
}
Here using antMatchers I have permitted static pages of Angular 6 application, as I'm planning to use those in my real app. And no, the following line does not work to allow static pages of angular application:
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
My AuthorizationServerConfigurerAdapter is as follows:
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends
AuthorizationServerConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Autowired
UserDetailsService userDetailsService;
#Autowired
PasswordEncoder passwordEncoder;
#Autowired
TokenStore tokenStore;
#Autowired
private UserApprovalHandler userApprovalHandler;
#Autowired
#Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.passwordEncoder(passwordEncoder);
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore)
.userApprovalHandler(userApprovalHandler)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
}
My ResourceServerConfigurerAdapter is as follows:
#Configuration
#EnableResourceServer
public abstract class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "resource-server-rest-api";
#Autowired
TokenStore tokenStore;
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
.resourceId(RESOURCE_ID)
.tokenStore(tokenStore);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.cors().disable()
.anonymous().disable()
.requestMatchers()
.antMatchers("/api/**").and()
.authorizeRequests()
.antMatchers("/api/secure").authenticated()
.antMatchers("/api/unsecure").permitAll();
}
}
But when I enable anonymous access in SecurityConfig and declare my unsecure url as permitAll, then I'm able to access that url.
.antMatchers("/api/unsecure", "/index.html", "/**.js", "/**.css", "/").permitAll()
My Controller class is as follows:
#RestController
#RequestMapping("/api")
public class DemoController {
#GetMapping("/secure")
public void sayHelloFriend() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
System.out.println("Current User: "+authentication.getName());
System.out.println("Hello Friend");
}
#GetMapping("/unsecure")
public void sayHelloStranger() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
System.out.println("Current User: "+authentication.getName());
System.out.println("Hello Stranger");
}
}
Let me know if any more information is needed. Any help will be appreciated. But please keep in mind that its Spring Boot 2.0 not 1.5 as both have some critical differences as per my findings.
Try to added
#Order(SecurityProperties.BASIC_AUTH_ORDER)
for the securityConfig? so the chain will check your Resource server's config first.
And not sure if that your type error, remove the abstract from the resource server.
In my Spring boot application I'm trying to configure Oauth2 & JWT, it works fine but I would like hide additionnal informations from the oauth2 token because they are in plain text and the same informations are duplicated in the JWT token.
This is my Oauth2ServerConfig :
#Configuration
public class OAuth2ServerConfiguration {
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
private final OAuth2ApprovalRepository oAuth2ApprovalRepository;
private final OAuth2CodeRepository oAuth2CodeRepository;
private final OAuth2ClientDetailsRepository oAuth2ClientDetailsRepository;
public AuthorizationServerConfiguration(#Qualifier("authenticationManagerBean") AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Bean
public ApprovalStore approvalStore() {
return new MyDBApprovalStore(oAuth2ApprovalRepository);
}
#Bean
protected AuthorizationCodeServices authorizationCodeServices() {
return new MyDBAuthorizationCodeServices(oAuth2CodeRepository);
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));
endpoints.authorizationCodeServices(authorizationCodeServices())
.approvalStore(approvalStore())
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancerChain)
.authenticationManager(authenticationManager);
}
#Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
#Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123");
return converter;
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(new MyClientDetailsService(oAuth2ClientDetailsRepository));
}
}
}
And my custom information adding :
public class CustomTokenEnhancer implements TokenEnhancer {
#Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
Map<String, Object> additionalInfo = new HashMap<>();
additionalInfo.put("organizationId", "123");
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
}
}
This is an example of the response of my authenticating WS call :
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcmdhbml6YXRpb25JZCI6IjEyMyIsImF1ZCI6WyJyZXNfYmh1YiJdLCJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSJdLCJleHAiOjE0OTc4NjkyNDMsImF1dGhvcml0aWVzIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwianRpIjoiOGNhYTZjN2YtNTU0Yy00OTZmLTkwYTUtZTA4MjAyM2I3ZTFlIiwiY2xpZW50X2lkIjoiYmh1YmFwcCJ9.B58c2_tmfuV_L1py8ZzOPuTK3OZAhVFviL9W1gxRoec",
"token_type": "bearer",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcmdhbml6YXRpb25JZCI6IjEyMyIsImF1ZCI6WyJyZXNfYmh1YiJdLCJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSJdLCJhdGkiOiI4Y2FhNmM3Zi01NTRjLTQ5NmYtOTBhNS1lMDgyMDIzYjdlMWUiLCJleHAiOjE0OTc4Njk0NDMsImF1dGhvcml0aWVzIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwianRpIjoiMGJjNWJhYzctMWI3Ny00OGFiLWI1N2MtNDM4ZjMyN2JmNGM2IiwiY2xpZW50X2lkIjoiYmh1YmFwcCJ9.DkQoCEX47PmmxOEj0n9kb2L5Yu6DqFgmUh7HBSTO_z4",
"expires_in": 1799,
"scope": "read write",
"organizationId": "123",
"jti": "8caa6c7f-554c-496f-90a5-e082023b7e1e"
}
I don't want to expose the organizationId of this token to external world and would like to encode this information in only the JWT token (access_token) .
How it can be implemented with Spring Boot, OAuth2, JWT ?
If the connection is over HTTPS (as it should be) then the information won't be exposed to the external world (just the client which is requesting it).
In any case, the access token you have is only a JWS (it's not encrypted) so the information isn't hidden if you put it in there (it's just Base64 encoded).
I found a solution here:
Spring OAuth 2 + JWT Inlcuding additional info JUST in access token
I also changed the configure method...
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer()));
endpoints
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancerChain)
.reuseRefreshTokens(false)
.userDetailsService(userDetailsService)
.authenticationManager(authenticationManager);
}
I am using Spring boot application and I have rest controllers. I just started using OAuth 2.0 in spring to secure my APIs. Here are the configuration classes that I have.
#Configuration
#EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final String HU_REST_RESOURCE_ID = "rest_api";
#Autowired
DataSource dataSource;
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(HU_REST_RESOURCE_ID).stateless(false);
}
#Override
public void configure(HttpSecurity http) throws Exception {
//define URL patterns to enable OAuth2 security
http.
requestMatchers().antMatchers("/user/**").and().
authorizeRequests().antMatchers("/user/**").access("#oauth2.hasScope('read') or (!#oauth2.isOAuth() and hasRole('ROLE_USER'))");
}
}
#Configuration
#EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
DataSource dataSource;
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("my-trusted-client")
.authorizedGrantTypes("password","refresh_token")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust")
.accessTokenValiditySeconds(60)
.refreshTokenValiditySeconds(600)
.and()
.withClient("my-trusted-client-with-secret")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_USER")
.scopes("read", "write", "trust")
.accessTokenValiditySeconds(60)
.refreshTokenValiditySeconds(600);
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource); // access and refresh tokens will be maintain in database
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients();
}
}
#Configuration
public class GlobalAuthenticationConfig extends GlobalAuthenticationConfigurerAdapter {
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user1").password("user1123").roles("USER");
auth.inMemoryAuthentication().withUser("user2").password("user2123").roles("ADMIN");
}
}
Now, When I hit the URL http://localhost:8080/oauth/token?grant_type=password&client_id=my-trusted-client-with-secret&username=user1&password=user1123 I get the following access tokens and refresh tokens,
{
"access_token": "87379d65-6012-4484-ba6f-e4c61766ede3",
"token_type": "bearer",
"refresh_token": "8b0d0ae3-0855-4465-9d89-a1c31c031b8a",
"expires_in": 59,
"scope": "read write trust"
}
My question is why would anyone pass the credentials as a query parameter? Can we make a post request and send the required parameters in an object as POST request? If yes, how can I do it?
My second question is, here I am using inmemory authentication, i.e two users are hard coded in the code. How can I make it check from the database for user credentials?
When you use https (which you should) the complete query is encrypted before being sent through the network, as explained here:
Are querystring parameters secure in HTTPS (HTTP + SSL)?
Regarding your second question, if you want Spring to check the authorized users from a database, you will have to create a class inheriting from UserDetailsManagerhttp://docs.spring.io/autorepo/docs/spring-security/4.0.3.RELEASE/apidocs/org/springframework/security/provisioning/UserDetailsManager.html
You can then implement its different methods, specially loadUserByUsername(String username) that it implements from UserDetailsService (which is used by the Spring authentication manager), with code which queries your database for the relevant data.
This other question describes how to add that manager to your Spring application How to make a UserDetailsManager available as a bean