스터디를 통해 스프링부트와 AWS로 혼자 구현하는 웹 서비스(저자 이동욱) 서적을 공부하는 중입니다.
공부/실습한 내용을 정리한 포스팅입니다.
책에 모르는 부분이 있으면 구글링하거나 챗gpt에 물어봐서 보충하였습니다.
(아직 초보라 모르는 부분이 많아 이것저것 다 적었습니다.)
참고한 사이트 출처는 포스팅 맨 하단에 적었습니다.
application-oauth.properties
코드 추가application-oauth.properties
파일에 있는 설정은 Spring Boot에서 OAuth 2.0 인증 프로토콜을 이용하여 네이버 로그인을 구현하는데 필요한 정보들을 설정하는 부분.
네이버는 Spring Security에서 공식 지원하지 않아서 Common-OAuth2Provider
를 통해 정보를 제공받지 못하여 일일이 수동으로 입력해줘야 함.
#naver-registration
spring.security.oauth2.client.registration.naver.client-id=클라이언트 ID
spring.security.oauth2.client.registration.naver.client-secret= 클라이언트 Secret
spring.security.oauth2.client.registration.naver.redirect-uri={baseUrl}/{action}/oauth2/code/{registrationId}
spring.security.oauth2.client.registration.naver.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.naver.scope=name,email,profile_image
spring.security.oauth2.client.registration.naver.client-name=Naver
#naver-provider
spring.security.oauth2.client.provider.naver.authorization_uri=https://nid.naver.com/oauth2.0/authorize
spring.security.oauth2.client.provider.naver.token_uri=https://nid.naver.com/oauth2.0/token
spring.security.oauth2.client.provider.naver.user-info-uri=https://openapi.naver.com/v1/nid/me
spring.security.oauth2.client.provider.naver.user_name_attribute=response
user_name_attribute
: 기준이 되는 user_name의 이름을 네이버에서는 response
로 해야함. 이유는 네이버 회원 조회 시 반환되는 JSON 형태 때문. Spring Security에선 하위 필드를 명시할 수 없는데 네이버 응답값 최상위 필드는 resultcode,message,response임. Spring Security에선 세 개의 필드만 인식 가능.{
"resultcode" : "00",
"message" : "success",
"response" : {
"email" : "openapi@naver.com",
"nickname" : "OpenAPI",
"profile_image" : "https://ssl.pstatic.net/statice/pwe/address/nodate_33x33.gif",
"age" : "40-49",
"gender" : "F",
"id" : "32742776",
"name" : "오픈API",
"birthday" : "10-01",
}
}
application.properties
에서 {}
는 프로퍼티 값을 참조하는 변수를 의미. 아래의 것들은 placeholder라 불리는 변수들. placeholder란 설정 파일에서 값을 동적으로 대체하거나 치환하는데 사용한 특수한 문자열 패턴. 설정 파일에 사전에 정의되지 않고, 나중에 해당 값을 대체하기 위해 사용.
OAuth 2.0 인증을 구현하는 클래스에서 실제로 값을 채워넣음.
- {baseUrl}
: 애플리케이션 기본 URL
- {action}
: 액션 정보를 나타내며, 각 애플리케이션에 따라 다른 값이 될 수 있음. 예를 들어, 로그인 요청, 회원 가입 요청 등의 액션에 따라 값이 달라짐.
- {registrationId}
: OAuth 2.0 Client의 등록정보 구분하는 식별자
spring.security.oauth2.client.registration.naver.client-name=Naver
: 여기서의 client-name
은 실제 OAuth 2.0 Client가 아니라 애플리케이션이 OAuth 2.0 서비스(provider)와 연동할 때 해당 provider를 식별하는 이름을 의미. OAuth 2.0에서의 용어와 Spring Security 설정에서 사용되는 용어 구분해야 하는데, Spring Security에서는 client-name
이라는 용어를 사용하여 각 Provider 식별. (Spring Security에서는 OAuth 2.0 제공 서비스를 Client로 생각.)
OAuth 2.0 프로토콜을 통해 인증이 완료되면, 인증 제공자로부터 액세스 토큰과 사용자 정보가 반환되는데, 이때 사용자 정보는 JSON 형식으로 제공.
하지만 application.properties
의 경우, 단순한 키-값 쌍의 형태이므로 복잡한 JSON 구조를 직접 표현이 어려움.
따라서 application.properties
에서는 사용자 정보를 단순히 최상위 필드만 설정. 나머지 복잡한 구조의 사용자 정보는 애플리케이션 코드에서 처리.
spring.security.oauth2.client.provider.naver.user_name_attribute
: OAuth 2.0 인증 서비스(Provider)에서 사용자 이름을 어떤 필드로 받아올지를 지정하는 설정. OAuth 2.0 인증을 통해 제공자로부터 사용자 정보를 받아올 때, 사용자의 식별자가 필요. 하지만, OAuth 2.0 제공자마다 사용자 식별자를 나타내는 필드 이름이 다름.
spring.security.oauth2.client.registration
와 spring.security.oauth2.client.provider
- registration : OAuth2.0 인증을 위한 클라이언트 등록 정보 설정.
- provider : OAuth 2.0 제공자(provider)의 구성 정보를 설정.
OAuthAttributes
네이버인지 판단하는 코드와 네이버 생성자만 추가.
public static OAuthAttributes of(String registrationId, String userNameAttributeName, Map<String,Object> attributes){
if("naver".equals(registrationId)){
return ofNaver("id",attributes);
}
return ofGoogle(userNameAttributeName,attributes);
}
public static OAuthAttributes ofNaver(String userNameAttributeName, Map<String,Object> attributes){
Map<String,Object> response = (Map<String, Object>) attributes.get("response");
return OAuthAttributes.builder()
.name((String) response.get("name"))
.email((String) response.get("email"))
.picture((String) response.get("profile_image"))
.attributes(response)
.nameAttributeKey(userNameAttributeName)
.build();
}
index.mustache
네이버 로그인 버튼 추가
{{^userName}}
<a href="/oauth2/authorization/google" class="btn btn-success active" role="button">Google Login</a>
<a href="/oauth2/authorization/naver" class="btn btn-secondary active" role="button">Naver Login</a>
{{/userName}}
/oauth2/authorization/naver
/oauth2/authorization/
까지는 고정. 마지막 Path는 각 소셜 로그인 코드 사용. 여기선 naver가 마지막 Path.