티스토리 뷰

최근 프로젝트들의 경향을 살펴보면 자체 데이터를 기반으로 인증 로직을 구현하기보다는 대형 플랫폼의 인증 시스템을 기반으로 서비스를 구현한다.

이를 위해 필수적으로 알아햐하는 방식이 OAuth2.0 프로토콜이고 Spring Security에서 해당 방식을 어떤식으로 구현해서 사용할 수 있는지 공식문서를 기반으로 알아보고 구현해보려고 한다.

 

https://docs.spring.io/spring-security/reference/servlet/oauth2/index.html

 

OAuth2 :: Spring Security

To get started, add the spring-security-oauth2-client dependency to your project. When using Spring Boot, add the following starter: OAuth2 Client with Spring Boot implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' org.springframew

docs.spring.io

위 공식 문서를 참고하여 포스팅을 시작한다.

 

초기 설정

Google OAuth 2.0을 사용해서 로그인을 구현하기 위해서는 Google API Console에서 OAuth 2.0 credentials을 얻어야한다.

 

https://console.cloud.google.com/welcome?organizationId=0

 

Google 클라우드 플랫폼

로그인 Google 클라우드 플랫폼으로 이동

accounts.google.com

우선 위 링크에 접속해서 새로운 프로젝트를 만든다.

 

Google Console

위 화면에서 API 및 서비스 메뉴를 클릭하여 접속한다.

 

API 및 서비스

위 화면과 같이 사용자 인증 정보 메뉴에 접속해서 동의 화면 구성 버튼을 클릭한다.

 

OAuth 동의 화면

나는 예제 프로젝트에 누구나 Google API를 통해 로그인이 가능하도록 설정할 것이기 때문에 외부를 선택했다.

 

OAuth 동의 화면 구성

그리고 이후 화면에서는 앱 이름, 사용자 지원 이메일, 개발자 이메일만 입력하고 넘어가고 범위, 테스트 사용자 설정에서도 아무것도 입력하지 않고 동의 화면 구성을 끝낸다.

 

사용자 인증 정보 만들기

그리고 다시 사용자 인증 정보 메뉴로 접속하여 상단의 "+ 사용자 인증 정보 만들기" 메뉴 중 OAuth 클라이언트 ID를 선택한다.

 

OAuth2.0 클라이언트 ID 만들기

 

위와 같이 애플리케이션 유형은 웹 애플리케이션으로 선택하고 프로젝트 이름을 입력해준다.

그리고 승인된 JavaScript 원본에는 서버 주소와 포트를 입력해주고 승인된 리디렉션 URI에는 서버 접속 정보에 /auth/google path를 추가해서 설정해준다.

(Redirect URI는 사용자가 구글 인증 및 OAuth Client 동의 페이지에서 권한을 얻은 후 리다이렉팅되는 경로이다)

 

이렇게 클라이언트 ID와 클라이언트 보안 비밀번호를 생성하게 되는데 이 정보를 가지고 Google과 OAuth2.0 인증을 수행하게 된다.

 

application.yml 설정

spring:
  security:
    oauth2:
      client:
        registration:	
          google:	
            client-id: google-client-id
            client-secret: google-client-secret

생성된 클라이언트 ID와 보안 비밀번호를 application.yml에 위와 같이 설정한다.

 

서버 접속

프로젝트를 기동하고 나서 localhost:8080으로 접속하면 위와 같이 자동 생성되는 구글 로그인 페이지를 만날 수 있다.

http://localhost:8080

우선 localhost:8080으로 접속하면 Response Header의 Location 값의 주소로 리다이렉션이 되도록 302 Found Status로 응답한다.

 

http://localhost:8080/oauth2/authorization/google

리다이렉션된 요청을 다시 호출하게 되더라도 302 Found Status로 응답되며 이 때 다음 리다이렉션 URI는 구글 API이다.

 

구글 API 호출

구글 API를 호출해서 로그인 뷰에 해당하는 HTML을 받게 된다.

 

CommonOAuth2Provider

CommonOAuth2Provider는 자주 사용되는 provider의 client property들을 미리 정의해둔 것이다.

CommonOAuth2Provider 내부 구현

위의 구현을 보면 authorization-uri, user-info-url 등을 따로 설정하지 않아도 기본 값을 CommonOAuth2Provider에서 제공한다.

그렇기 때문에 applicaion.yml에 client-id와 client-secret만 정의하더라도 정상적으로 동작할 수 있었다.

 

Spring Boot에서 OAuth2 Client Auto-Configuration

OAuth2ClientAutoConfiguration 클래스는 스프링 부트에서 아래와 같은 방식으로 OAuth Client 자동 설정의 역할을 수행한다.

  1. OAuth Client property 기반의 ClientRegistration으로 구성된 ClientRegistrationRepository 빈을 등록
  2. httpSecurity.oauth2Login()을 통해 OAuth 2.0 Login의 활성화하여 SecurityFilterChain 빈을 등록

 

ClientRegistrationRepository 빈 등록

@Configuration
public class OAuth2LoginConfig {
    
    @Bean
    public ClientRegistrationRepository clientRegistrationRepository() {
        return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
    }
    
    private ClientRegistration googleClientRegistration() {
        return ClientRegistration.withRegistrationId("google")
            .clientId("google-client-id")
            .clientSecret("google-client-secret")
            .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
            .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
            .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
            .scope("openid", "profile", "email", "address", "phone")
            .authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
            .tokenUri("https://www.googleapis.com/oauth2/v4/token")
            .userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
            .userNameAttributeName(IdTokenClaimNames.SUB)
            .jwSetUri("https://www.googleapis.com/oauth2/v3/certs")
            .clientName("Google")
            .build();
    }
}

 

SecurityFilterChain 빈 등록

@Configuration
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorize -> authorize
                .anyrequest().authenticated()
            )
            .oauth2Login(Customizer.withDefaults());
        
        return http.build();
    }
}

HttpSecurity.oauth2Login() 메서드는 OAuth 2.0 로그인을 위한 설정들을 제공하며, 각 프로토콜 그룹에 대응하는 엔드포인트들을 설정할 수 있다.

예를 들어 oauth2Login().authorizationEndpoint()는 인가 엔드포인트를 설정하고, oauth2Login().tokenEndpoint()는 토큰 엔드포인트를 설정한다.

 

@Configuration
@EnableWebSecurity
public class Oauth2LoginSecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .oauth2Login(oauth2 -> oauth2
                .clientRegistrationRepository(clientRegistrationRepository())
                .authorizedClientRepository(authorizedClientRepository())
                .authorizedClientService(authorizedClientService())
                .loginPage("/login")
                .authorizationEndpoint(authorization -> authorization
                    .baseUri(authorizationRequestBaseUri())
                    .authorizationRequestRepository(authorizationRequestRepository())
                    .authorizationRequestResolver(authorizationRequestResolver())
                )
                .redirectionEndpoint(redirection -> redirection
                    .baseUri(authorizationResponseBaseUri())
                )
                .tokenEndpoint(tokenEndpoint -> tokenEndpoint
                    .accessTokenResponseClient(accessTokenResponseClient())
                )
                .userInfoEndpoint(userInfo -> userInfo
                    .userAuthoritiesMapper(userAuthoritiesMapper())
                    .userService(oauth2UserService())
                    .oidcUserService(oidcUserService())
                )
            );
        
        return http.build();
    }
}

OAuth 2.0 인증 프레임워크에서는 해당 프로토콜이 동작하기 위한 엔드포인트를 설정하도록 정의한다.

위 코드의 oauth2Loing()의 용도는 이와 같은 엔드포인트를 설정하는 것이다.

 

다음 글: https://gojs.tistory.com/61

 

OAuth 2.0 with Spring Security (2) - 추가적인 로그인 설정

https://gojs.tistory.com/60 OAuth 2.0 with Spring Security (1) - 기본 로그인 구현하기최근 프로젝트들의 경향을 살펴보면 자체 데이터를 기반으로 인증 로직을 구현하기보다는 대형 플랫폼의 인증 시스템을

gojs.tistory.com

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함