int-main
int-main

Reputation: 57

Unauthorized error on Spring Boot Authorization Server /oauth/authorize

I am trying to develop a simple POC for OAuth2 Authorization Server in Spring Boot using @EnableAuthorizationServer and a in-memory client.

My Web Security configuration class looks like follows:

package com.example.authservice;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**")
                .authorizeRequests().
                antMatchers("/", "/login**", "/oauth/authorize", "/oauth/authorize**")
                .permitAll().
                anyRequest()
                .authenticated();
    }
}

And the authorization server configuration is as follows:

package com.example.authservice;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().
                withClient("auth-client").
                secret("secret-key").
                authorizedGrantTypes("authorization_code").
                scopes("openid");
    }

}

This is based on Authorization Code grant flow and when I try to get code (which will be used in next call to get access token), I am getting Unauthorized error.

curl -X GET \
  'http://localhost:8080/oauth/authorize?client_id=auth-client&client_secret=secret-key&grant_type=authorization_code&response_type=code'

Error:

{
    "timestamp": "2019-03-20T15:35:41.009+0000",
    "status": 403,
    "error": "Forbidden",
    "message": "Access Denied",
    "path": "/oauth/authorize"
}

I assumed that since /oauth/authorize is permitted in my web security configuration, it should return a code which can be used to get the access token. Does anyone have a clue about what might be going wrong.

Upvotes: 0

Views: 5625

Answers (2)

wl.GIG
wl.GIG

Reputation: 316

/oauth/authorize 

is the default authorization server endpoint, which means it comes with a high priority security level.

authorizeRequests().antMatchers("/oauth/authorize").permitAll()

would not work on the spring security default api. It will be better if you are using brower to test with things like

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .inMemoryAuthentication().passwordEncoder(new PasswordEncoder() {
        @Override
        public String encode(CharSequence charSequence) {
            return charSequence.toString();
        }

        @Override
        public boolean matches(CharSequence charSequence, String s) {
            return s.equals(charSequence.toString());
        }
    })
        .withUser("gig")
        .password("123456")
        .roles("USER");

}

also, it is better to add a redirectUris after your scope. my test url

http://localhost:8080/oauth/authorize?response_type=code&client_id=auth-client-&redirect_uri=http://www.baidu.com&scope=all

Upvotes: 1

int-main
int-main

Reputation: 57

When a user tries to generate authorization code by calling /oauth/authorize, the user is supposed to tell the service who he/she is i.e authenticate. That's how the authorize endpoint knows if the user is authorized to get this token. So, an important piece that was missing in my service is Authentication. In Spring Boot, authentication is handled by an AuthenticationManager.

To add the missing piece, below is the modified version of WebSecurityConfigurerAdapter.java:

package com.example.authservice;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf()
                .disable()
                .antMatcher("/**")
                .authorizeRequests()
                .antMatchers("/login")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and().
                httpBasic();
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user").password("{noop}password").roles("ROLE");
    }
}

This adds a Basic HTTP Authentication to the Spring Boot service. Now when you try to call /oauth/authorize with a HTTP Basic Authentication, it will successfully redirect to your passed redirect_uri.

Upvotes: 0

Related Questions