How do you properly configure Spring Security's OAuth2 system to work with EmberJS - spring

I'm creating an EmberJS app wrapped with Cordova alongside a Rest API provided by Spring Boot. Here is my Spring Code:
#SpringBootApplication
#RestController
public class Application extends SpringBootServletInitializer {
...
#Configuration
#EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
// any calls made to the API must be authenticated
http.antMatcher("/api/**")
.authorizeRequests()
.anyRequest().fullyAuthenticated();
http
.cors().disable();
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId("b-api");
}
}
#Configuration
#EnableWebSecurity
public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
// we're hosting a static landing page with Spring so we're removing any security requirements for them
.antMatchers("/resources/**")
.antMatchers("/img/**")
.antMatchers("/*")
// this is to allow preflight to work but it doesn't seem to be doing the trick...
.antMatchers(HttpMethod.OPTIONS, "/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/public/**").permitAll().anyRequest()
.hasRole("USER");
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
// enable in memory based authentication with a user named "user" and "admin"
.inMemoryAuthentication()
.withUser("user")
.password("password")
.roles("USER")
.and()
.withUser("admin")
.password("password")
.roles("USER", "ADMIN");
}
}
#Configuration
#EnableAuthorizationServer
#CrossOrigin(origins = "http://localhost:4200", methods = {RequestMethod.GET, RequestMethod.PUT, RequestMethod.OPTIONS, RequestMethod.HEAD}, allowedHeaders = "**")
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("my-trusted-client")
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT", "ROLE_USER")
.scopes("read", "write", "trust")
.resourceIds("b-api")
.accessTokenValiditySeconds(600);
}
}
}
The frontend code is using EmberJS with ember-simple-auth's oauth2 authenticator.
Currently when I try and authenticate through the frontend Chrome's devtools throw this error:
XMLHttpRequest cannot load http://localhost:8080/oauth/token. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 403.
Any ideas regarding what I'm missing would be appreciated. Thanks :)

Related

Connect multiple authentication mechanisms Spring Boot Security

I have a security configuration for my application that authenticates the user via LDAP. This works out pretty fine, but now I'd like to add another AuthenticationProvider that does some more checks on the user that tries authenticate. So I tried to add a DbAuthenticationProvider that (for testing purposes) always denies the access. So when I am trying to log in with my domain account (that works for the activeDirectoryLdapAuthenticationProvider) I am not able to access the page because the second provider fails the authentication.
To accomplish this goal, I used the following code:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Value("${ad.domain}")
private String AD_DOMAIN;
#Value("${ad.url}")
private String AD_URL;
#Autowired
UserRoleComponent userRoleComponent;
#Autowired
DbAuthenticationProvider dbAuthenticationProvider;
private final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);
#Override
protected void configure(HttpSecurity http) throws Exception {
this.logger.info("Verify logging level");
http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin()
.successHandler(new CustomAuthenticationSuccessHandler()).and().httpBasic().and().logout()
.logoutUrl("/logout").invalidateHttpSession(true).deleteCookies("JSESSIONID");
http.formLogin().defaultSuccessUrl("/", true);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
auth.authenticationProvider(dbAuthenticationProvider);
}
#Bean
public AuthenticationManager authenticationManager() {
return new ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider(), dbAuthenticationProvider));
}
#Bean
public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(AD_DOMAIN,
AD_URL);
provider.setConvertSubErrorCodesToExceptions(true);
provider.setUseAuthenticationRequestCredentials(true);
return provider;
}
}
And this is my DbAuthenticationProvider:
#Component
public class DbAuthenticationProvider implements AuthenticationProvider {
Logger logger = LoggerFactory.getLogger(DbAuthenticationProvider.class);
#Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
auth.setAuthenticated(false);
this.logger.info("Got initialized");
return auth;
}
#Override
public boolean supports(Class<?> authentication) {
return true;
}
}
Sadly I am able to log in (the access is not denied as I expected it to be). Did I miss out something?
Spring Won't use more than one AuthenticationProvider to authenticate the request, so the first (in the ArrayList) AuthenticationProvider that support the Authentication object and successfully authenticate the request will be the only one used. in your case it's activeDirectoryLdapAuthenticationProvider.
instead of using ActiveDirectoryLdapAuthenticationProvider, you can use a custom AuthenticationProvider that delegates to LDAP and do additional checks:
CustomerAuthenticationProvider implements AuthenticationProvider{
privtae ActiveDirectoryLdapAuthenticationProvider delegate; // add additional methods to initialize delegate during your configuration
#Override
public Authentication authenticate(Authentication auth) throws
AuthenticationException {
Authentication authentication= delegate.authenticate(auth);
additionalChecks(authentication);
return auth;
}
#Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
public void additionalCheck(Authentication authentication){
// throw AuthenticationException when it's not allowed
}
}
That is not how an AuthenticationProvider works, only one will be consulted for authentication. Apparently you want to combine some information from LDAP and from the DB. For this you can configure a custom UserDetailsContextMapper and/or GrantedAuthoritiesMapper. The default implementation will use the information from LDAP to contruct the UserDetails and its GrantedAuthorities however you could implement a strategy which consults the database.
Another solution is to use the LdapUserDetailsService which allows you to use the regular DaoAuthenticationProvider. The name is misleading as it actually requires an UserDetailsService. This AuthenticationProvider does additional checks using the UserDetailsChecker, which by default checks some of the properties on the UserDetails, but can be extended with your additional checks.
NOTE: The LdapUserDetailsService uses plain LDAP so I don't know if that is applicable to the slightly different Active Directory approach!
A final solution could be to create a DelegatingAuthenticationProvider which extends from AbstractUserDetailsAuthenticationProvider so that you can reuse the logic in there to utilize the UserDetailsChecker. The retrieveUser method would then delegate to the actual ActiveDirectoryLdapAuthenticationProvider to do the authentication.
NOTE: Instead of extending the AbstractUserDetailsAuthenticationProvider you could of course also create a simpler version yourself.
All in all I suspect that creating a customized UserDetailsContextMapper would be the easiest and when not found in DB throw an UsernameNotFoundException. This way the normal flow still applies and you can reuse most of the existing infrastructure.
As sample work around on multiple authentication mechanism :
find the code
#Configuration
#EnableWebSecurity
#Profile("container")
public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationProvider authenticationProvider;
#Autowired
private AuthenticationProvider authenticationProviderDB;
#Override
#Order(1)
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
#Order(2)
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProviderDB);
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/scripts/**","/styles/**","/images/**","/error/**");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/rest/**").authenticated()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.successHandler(new AuthenticationSuccessHandler() {
#Override
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication a) throws IOException, ServletException {
//To change body of generated methods,
response.setStatus(HttpServletResponse.SC_OK);
}
})
.failureHandler(new AuthenticationFailureHandler() {
#Override
public void onAuthenticationFailure(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException ae) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
})
.loginProcessingUrl("/access/login")
.and()
.logout()
.logoutUrl("/access/logout")
.logoutSuccessHandler(new LogoutSuccessHandler() {
#Override
public void onLogoutSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication a) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
})
.invalidateHttpSession(true)
.and()
.exceptionHandling()
.authenticationEntryPoint(new Http403ForbiddenEntryPoint())
.and()
.csrf()//Disabled CSRF protection
.disable();
}
}
configured two authentication providers in Spring Security
<security:authentication-manager>
<security:authentication-provider ref="AuthenticationProvider " />
<security:authentication-provider ref="dbAuthenticationProvider" />
</security:authentication-manager>
configuration which helps configure multiple authentication providers in java config.
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
auth.authenticationProvider(DBauthenticationProvider);
}
#Configuration
#EnableWebSecurity
public class XSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private LDAPAuthenticationProvider authenticationProvider;
#Autowired
private DBAuthenticationProvider dbauthenticationProvider;
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/scripts/**","/styles/**","/images/**","/error/**");
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
auth.authenticationProvider(dbauthenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/","/logout").permitAll()
.antMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/index")
.loginProcessingUrl("/perform_login")
.usernameParameter("user")
.passwordParameter("password")
.failureUrl("/index?failed=true")
.defaultSuccessUrl("/test",true)
.permitAll()
.and()
.logout().logoutUrl("/logout")
.logoutSuccessUrl("/index?logout=true").permitAll()
.and()
.exceptionHandling().accessDeniedPage("/error");
}
}
objectPostProcessor inside the configure method need AuthenticationManagerBuilder to actually build the object before we can access and change the order of the providers
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.passwordEncoder(new BCryptPasswordEncoder());
auth.authenticationProvider(new CustomAuthenticationProvider(this.dataSource));
auth.objectPostProcessor(new ObjectPostProcessor<Object>() {
#Override
public <O> O postProcess(O object) {
ProviderManager providerManager = (ProviderManager) object;
Collections.swap(providerManager.getProviders(), 0, 1);
return object;
}
});
}

How to configure oAuth2 when Authorization Server is also the Resource server

I'm trying to setup a very basic oAuth2 authentication in spring boot 2.x.x using either authorization code grant or implicit grant but I can't seem to access the Resource server (which resides in the same spring boot app as the Authorization server) after the token is obtained.
Following is the configuration of WebSecurityConfigurerAdapter
#EnableWebSecurity
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final String[] IGNORE_URIS = {
"/swagger-resources/**",
"/swagger-ui.html",
"/v2/api-docs",
"/webjars/**",
"/resources/**",
"/h2-console/**",
"/common/**",
"/configuration/ui",
"/configuration/security",
"/error"
};
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers(IGNORE_URIS);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/product/**")
.hasAnyRole("ADMIN").and()
.httpBasic().and().formLogin().and().authorizeRequests().anyRequest().authenticated();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("{noop}admin").roles("ADMIN");
}
#Bean
public PasswordEncoder bCrypt() {
return new BCryptPasswordEncoder();
}
And the AuthorizationServerConfigurerAdapter
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
#Autowired
public AuthorizationServerConfiguration(AuthenticationConfiguration authenticationConfiguration) throws Exception {
this.authenticationManager = authenticationConfiguration.getAuthenticationManager();
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("my-client-id")
.authorizedGrantTypes("authorization_code", "implicit")
.authorities("ADMIN")
.scopes("all")
.resourceIds("product_api")
.secret("{noop}secret").redirectUris("https://google.com").accessTokenValiditySeconds(0);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
So far so good. I am able to reach the default Spring login page by typing the following Url in the browser.
http://localhost:8080/oauth/authorize?response_type=token&client_id=my-client-id&redirect_uri=https://google.com
Then The login page shows up and I enter my credentials.
After I log in I can then grant access to "my-client-id" app.
Eventually after I approve the app I can see the newly generated access token in the URL bar of the browser which is something like this.
https://www.google.com/#access_token=f2153498-6a26-42c6-93f0-80825ef03b16&token_type=bearer&scope=all
My question is that All of this flow won't work when I also configure a Resource Server.
#EnableResourceServer
#Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId("product_api");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/**")
.and().authorizeRequests()
.antMatchers("/**").permitAll();
}
}
What am I doing wrong? When I try to access the oauth/authorize url as before I get the following:
Why? How can one access the login page and retrieve the token? What Am I missing?
You need to use
#Order
Annotation to specify order for WebMvc and ResourceServer classes
#EnableWebSecurity
#Configuration
#Order(1)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
...
}
and for Resource Server
#EnableResourceServer
#Configuration
#Order(2)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
...
}
If you want to see workable example, you can check it here https://github.com/alex-petrov81/stackoverflow-answers/tree/master/auth-server-also-resource
I've created it from your code example.

Spring OAuth2 "Full authentication is required to access this resource error" when trying to access login url

I am using Spring Security OAuth2 (Spring Boot 2.0.2 + Spring Cloud Finchley) and trying to initiate an implicit login. The browser redirects me to the /login URL but I get the the error "Full authentication is required to access this resource." How do I allow the login page to be displayed but still allow all REST urls to be secured?
My config is as follows:
App.java
#SpringBootApplication
#RestController
#EnableResourceServer
#EnableAuthorizationServer
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
OAuth2Config.java
#Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private UserDetailsService userDetailsService;
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("XXXXX")
.secret("XXXXX")
.authorizedGrantTypes("refresh_token", "password", "client_credentials")
.scopes("webclient", "mobileclient");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
}
WebSecurityConfigurer.java
#Configuration
#Order(-20) // EDIT
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
#Bean
public UserDetailsService userDetailsServiceBean() throws Exception {
return super.userDetailsServiceBean();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("XXXXX"). password("XXXXXX").roles("USER");
}
// EDIT
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().permitAll()
.and().httpBasic().and()
.requestMatchers()
//specify urls handled
.antMatchers("/login", "/oauth/authorize", "/oauth/confirm_access")
.antMatchers("/fonts/**", "/js/**", "/css/**")
.and()
.authorizeRequests()
.antMatchers("/fonts/**", "/js/**", "/css/**").permitAll()
.anyRequest().authenticated();
}
}
}

spring security oauth2 manipulate request url before redirect

I have a Vaadin application that is secured using spring security OAuth2. This works fine except for the occasional PUSH or HEARTBEAT endpoint being used to request first and thus triggering the auth process and the user ends up on the wrong page (These endpoints should not be visited directly by the user).
A simple but unsecure fix is to permitAll() on these endpoints. However as this poses a threat I need to close this hole up.
To do this I would like to parse and potentially edit the request url before redirecting to it at successfull auth. How would I go about doing this?
I would guess I need to add a filter somewhere in the chain to intercept the request and edit it. But I'm not sure where.
Here is my client:
#Configuration
#EnableOAuth2Sso
public class OAuthConfig extends WebSecurityConfigurerAdapter
{
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login**").permitAll()
.antMatchers("/vaadinServlet/PUSH/**").permitAll() //todo fix this hole
.antMatchers("/vaadinServlet/HEARTBEAT/**").permitAll() //todo fix this hole
.anyRequest().authenticated()
.and()
.logout()
.logoutSuccessUrl("/")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
#Override
public void configure(WebSecurity web) throws Exception
{
web.ignoring().antMatchers("/css/*").antMatchers("/VAADIN/**"); // Static resources are ignored
}
}
And the server:
#Configuration
#EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter
{
//jwt token stuff & my own client/auth providers. Should not be important.
...
}
server login form:
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
#Autowired
private RestAuthenticationProvider authenticationProvider;
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.authenticationProvider(authenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/forgetPassword*").permitAll()
.antMatchers(HttpMethod.POST,"/user/resetPassword*").permitAll()
.antMatchers(HttpMethod.GET,"/user/changePassword*").permitAll()
.antMatchers("/user/updatePassword*", "/user/savePassword*", "/updatePassword*")
.hasAnyAuthority("CHANGE_PASSWORD_PRIVILEGE","ROLE_USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.csrf().csrfTokenRepository(csrfTokenRepository());
}
private CsrfTokenRepository csrfTokenRepository()
{
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
Just add some implementation with your project
1: create Authentication Failure handler
#Component
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
System.out.print("here failure");
String s=request.getParameter("username");
setDefaultFailureUrl("/login?error&username="+s);
super.onAuthenticationFailure(request,response,exception);
}
}
2: Authentication Success Handler
#Component
public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest request , HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
/* custom Block
Do any thing here
*/
setDefaultTargetUrl("/home/");
super.onAuthenticationSuccess(request,response,authentication);
}
}
3: access request entry point
#Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
System.out.print("Unauthorized Access");
httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
}
Implement the components as per your requirement.

spring security token request requires authentication

I am trying to implement Authorization Code Grant Flow of OAuth 2.0. But stuck with the issue of Authentication popup on token request.
Here is my code.
#SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
#Configuration
public class SecurityConfig
extends WebSecurityConfigurerAdapter {
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password("abc").roles("ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll()
.and().csrf().disable();
}
}
#Configuration
#EnableAuthorizationServer
public class AuthServerOAuth2Config
extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("test")
.secret("test_secret")
.authorizedGrantTypes("authorization_code")
.scopes("write");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints
.authorizationCodeServices(authorizationCodeServices())
.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.approvalStoreDisabled();
}
#Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
#Bean
protected AuthorizationCodeServices authorizationCodeServices() {
return new InMemoryAuthorizationCodeServices();
}
}
To get token I do the following steps:
Using browser go to:
http://localhost:9000/oauth/authorize?response_type=code&client_id=test&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&scope=write
First it redirects me to a Login form, where I enter username and passord: admin abc
Then it asks if I allow to provide the permission to my "test" client.
It redirects me to "redirect uri": http://localhost:8080?code=XXX
Then I copy code and use Google Advanced Rest Client to send Token Request:
POST on http://localhost:9000/oauth/token?client_id=test&grant_type=authorization_code&code=XXX
Without any headers. As far as I understand Poster should use Browser cookie.
As result on token request I see a popup asking to fill username and password while expecting to get access token in response.
Please, help me to solve the issue. Should I add some headers to my token request? Or my Authorization Server config is not correct?
I found the reason of the issue by myself just reading others resources of OAuth2 specification.
It it is required to send Authorization on token request with the following value:
Authorization: Basic {base64 encode of clientId:clientSecret}

Resources