스프링 마이크로서비스 코딩 공작소 7장 AuthorizationServer설정 시 (Annotation NotFound,Full authentication is required to access this resource) 발생 문제

600g (Kim Dong Geun)·2020년 8월 28일
2

스프링부트를 이용한 마이크로서비스 구축론과 프레임워크를 제시해주고 있는 책이다.

그런데 7장을 보면, Authorization 서버를 구축하는 내용을 볼 수 있는데,

책에서 하라는대로 했는데도 불구하고 맨 처음부터 코드가 돌아가지 않는다.

분명히 그대로했는데 또 안된다... 😭

이유인 즉슨, 이 책은 2018년에 출간했는데, 2019년 말에 Spring-cloud-security에서 Authorization Server에 대한 지원 종료를 한다고 언급했기 때문이다.
따라서 문제 해결을 위해 공식 레포를 뒤져봤는데도 SSO (Single Sign On)에 대한 언급 뿐, Authorization Server에 대한 언급은 없다...

따라서 책 내용을 그대로 하다보면, 총 3가지의 문제 때문에 서버가 정상 동작하지 않는다

3가지 문제점은 다음과 같다.

1. Annotation이 들어먹질 않는다.

@EnableAuthorizationServer
@EnableResourceServer

제시된 의존성을 추가했는데 위 두 Annotation에 대해 Not Found Error를 내뿜는걸 볼 수 있다.

  • 해결방법
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>

을 추가하면 어노테이션을 찾을 수 없다는 문제를 해결할 수 있다.

다음은 Full authentication is required to access this resource에 대한 문제 해결 방법이다.

2. Spring Security 5.x로의 변화

Spring Security의 5.x대로의 변화로 Password Encoder 방식이 변경됐다. 그래서 백날 시도해봐야 Full Authentication 이 필요하다고 뜨더라,,

  • 해결방법
    기존의 코드가
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("eagleeye")
                .secret(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("thisissecret"))
                .authorizedGrantTypes("refresh_token","password","client_credentials")
                .scopes("webclient","mobileclient");
    }

라면 다음과 같이 수정한다.

   @Override
   public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
       clients.inMemory()
               .withClient("eagleeye")
               .secret("{noop}thisissecret")
               .authorizedGrantTypes("refresh_token","password","client_credentials")
               .scopes("webclient","mobileclient");
   }

또 아래코드를

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        auth.inMemoryAuthentication()
                .passwordEncoder(encoder)
                .withUser("admin1234").password("password1").roles("USER","ADMIN")
                .and()
                .withUser("test1234").password("password1").roles("USER");
    }

다음과 같이 고친다.

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin1234").password("{noop}password1").roles("USER","ADMIN")
                .and()
                .withUser("test1234").password("{noop}password1").roles("USER");
    }

위 코드의 경우 NoOpPasswordEncoder 방식으로 해결하는 경우이다.

실제 코드의 경우 InMemory방식이 아니라 DB 연동방식의 경우가 대부분일 것이고 Bcrpyt를 사용할 것이다...

아무튼 문제를 해결하고 이제 되나 싶었더니

그럼에도 불구하고 또 안된다. 😂

3. 토큰을 요청하는 경로가 잘못됨

책에서는 분명히 http://localhost:port/auth/oauth/token/ 에 요청을 하라고 했는데, 실제 경로 요청은 http://localhost:port/oauth/token 이다.

잘못된 경로로 계속 요청을 하니, 들어먹을리가 있나...

아무튼 위와 같은 모든 문제를 해결하고 나면

올바르게 토큰이 생성되는 것을 볼 수 있다.

후기

시간을 생각보다 많이 썼다..
그래도 뭔가 책에 있는 내용이 잘못됨을 지적하고, 해결법을 제시해서 뿌듯하긴하다.

개정판이 얼른 나왔으면 좋겠다 ㅎ

profile
수동적인 과신과 행운이 아닌, 능동적인 노력과 치열함

0개의 댓글