이 포스트에서는 스프링 부트로 소셜 로그인을 구현해보겠습니다. 스프링 시큐리티와 스프링 OAuth2 클라이언트 라이브러리를 사용하여 구글, 네이버, 카카오 서비스와 연동하여 로그인, 회원 탈퇴 기능이 들어간 간단한 애플리케이션을 구현해보겠습니다.
OAuth2
https://datatracker.ietf.org/doc/html/rfc6749
OAuth2 앱 생성
OAuth2 연동을 하기 위해서 먼저 OAuth2 제공자인 구글, 네이버, 카카오에서 OAuth2 애플리케이션을 생성해야합니다. 각 서비스 별로 애플리케이션을 생성하는 방법은 비슷합니다. 애플리케이션을 생성하면 Client ID 와 Client Secret 이 생성됩니다. 이 두개의 값은 앞으로 만들 스프링 애플리케이션에서 사용합니다.
https://console.cloud.google.com 에서 상단의 프로젝트 선택을 누르고 프로젝트를 선택합니다. 처음에는 프로젝트가 없으므로 새 프로젝트를 선택하여 생성합니다.
프로젝트 이름을 입력하여 생성합니다.
상단에서 생성한 프로젝트를 선택하고 메뉴 -> API 및 서비스 -> OAuth 동의 화면을 선택합니다. User Type은 외부를 선택하고 동의 화면을 만듭니다.
앱 정보에 앱 이름, 사용자 지원 이메일, 개발자 연락처 정보를 입력합니다.
범위에서 email, profile, openid 를 선택합니다.
테스트 사용자를 입력합니다. (이메일 주소)
메뉴 -> API 및 서비스 -> 사용자 인증 정보로 이동합니다. 사용자 인증 정보 만들기 -> OAuth 클라이언트 ID를 선택합니다.
애플리케이션 유형은 웹 애플리케이션, 애플리케이션 이름을 입력합니다. 승인된 리디렉션 URI에 http://localhost:8080/login/oauth2/code/google 을 입력하여 OAuth 클라이언트 ID를 생성합니다.
클라이언트 ID가 Client ID 값 입니다. 클라이언트 보안 비밀번호는 Client Secret 값 입니다. 나중에 쓸 값이므로 저장해둡니다.
https://developers.naver.com 에서 Application -> 애플리케이션 등록을 선택합니다.
아래와 같이 애플리케이션 이름을 입력합니다. 사용 API는 네이버 로그인을 선택합니다. 필수 정보로 이름, 이메일, 별명, 프로필 사진을 선택합니다.
환경은 PC 웹 환경을 선택하고 서비스 URL은 테스트 용도이므로 http://localhost:8080 네이버 로그인 Callback URL은 http://localhost:8080/login/oauth2/code/naver 을 입력합니다.
애플리케이션을 생성하면 Client ID 와 Client Secret 정보를 발급받습니다. 이 정보는 유출되지 않도록 합니다.
https://developers.kakao.com 에서 내 애플리케이션 -> 애플리케이션 추가하기를 선택합니다.
아래와 같이 애플리케이션 이름과 사업자명을 입력하여 애플리케이션을 생성합니다.
메뉴에서 앱 설정 -> 앱 키를 들어가면 나오는 REST API 키가 Client ID 값 입니다.
메뉴에서 제품 설정 -> 카카오 로그인을 선택합니다. 활성화 설정을 ON 으로 설정합니다. Redirect URI에 http://localhost:8080/login/oauth2/code/kakao 를 입력합니다.
메뉴에서 제품 설정 -> 카카오 로그인 -> 동의 항목을 선택합니다. 아래와 같이 닉네임, 프로필 사진을 필수 동의로 설정합니다. 카카오 계정(이메일)은 애플리케이션 검수를 받아야 필수 동의로 설정할 수 있습니다. 테스트 용도 이므로 일단 선택 동의로 설정합니다.
메뉴에서 제품 설정 -> 카카오 로그인 -> 보안을 선택합니다. 아래와 같이 코드 생성 버튼을 선택하여 Client Secret 을 생성하고 활성화 상태를 사용함으로 설정합니다.
https://start.spring.io 에서 아래와 같이 의존성을 추가하여 프로젝트를 생성합니다.
인텔리제이에서 프로젝트를 열어 메인 클래스를 실행합니다. http://localhost:8080 에 접속되는지 확인합니다.
스프링 부트 설정 파일
프로젝트에 기본으로 생성된 src/main/resources/application.properties 파일을 삭제하고 src/main/resources/application.yml 파일을 생성합니다. 아래 내용을 추가해줍니다. 앞에서 각 서비스별로 생성했던 Client ID와 Client Secret을 적어줍니다.
spring:
security:
oauth2:
client:
registration:
google:
client-id: # 발급 받은 Client ID
client-secret: # 발급 받은 Client Secret
scope: # 기본 값 openid,profile,email => profile, email 로 설정 변경
- profile
- email
naver:
client-id: # 발급 받은 Client ID
client-secret: # 발급 받은 Client Secret
client-authentication-method: client_secret_post
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/{action}/oauth2/code/{registrationId}"
# scope:
# - name
# - email
# - profile_image
client-name: Naver
kakao:
client-id: # 발급 받은 Client ID
client-secret: # 발급 받은 Client Secret
client-authentication-method: client_secret_post
authorization-grant-type: authorization_code
scope: # https://developers.kakao.com/docs/latest/ko/kakaologin/common#user-info
- profile_nickname
- profile_image
- account_email
redirect-uri: "{baseUrl}/{action}/oauth2/code/{registrationId}"
client-name: Kakao
provider:
naver:
authorization-uri: https://nid.naver.com/oauth2.0/authorize
token-uri: https://nid.naver.com/oauth2.0/token
user-info-uri: https://openapi.naver.com/v1/nid/me
user-info-authentication-method: header
user-name-attribute: response # Naver 응답 값 resultCode, message, response 중 response 지정
kakao:
authorization-uri: https://kauth.kakao.com/oauth/authorize
token-uri: https://kauth.kakao.com/oauth/token
user-info-uri: https://kapi.kakao.com/v2/user/me
user-info-authentication-method: header
user-name-attribute: id # Kakao 응답 값 id, connected_at, properties, kakao_account 중 id 지정
Google은 scope 필드의 기본 값이 openid, profile, email 입니다. 이를 profile, email 로 설정을 변경합니다. openid가 scope에 있으면 Open Id Provider로 인식하기 때문입니다.
client-authentication-method: 인가 코드로 액세스 토큰을 요청할 때 방법을 정의합니다.
authorization-uri: 소셜 로그인 버튼을 눌렀을 때 이동 할 URL 입니다. 해당 URL로 이동하면 소셜 로그인과 사용자 동의를 진행하고 인가 코드를 발급하여 사용자 서비스 서버로 리다이렉트 합니다.
token-uri: 사용자 서비스 서버가 Redirect URI로 전달받은 인가 코드로 액세스 토큰을 요청하는 URI 입니다.
user-info-uri: 서비스 서버가 발급받은 액세스 토큰으로 사용자 정보를 가져오는 URI 입니다.
user-info-authentication-method: 사용자 정보를 가져올 때 토큰을 보내는 방법 입니다. header, form, query 중 header 가 기본 값 입니다. 기본 값은 헤더에 액세스 토큰을 담아서 보내는 것 입니다.
Google, GitHub, Facebook, Okta는 CommonOAuth2Provider enum 에 미리 정의되어 있습니다. Google에 scope 값이 openid, profile, email이 설정되어 있는 것을 볼 수 있습니다.