구글, 네이버 로그인에 이어 카카오 로그인을 구현하겠다.
1. KAKAO OAuth 서비스 등록하기
1-1) 애플리케이션 추가하기
"애플리케이션 추가하기" 를 클릭한다.
애플리케이션 추가하기 > 앱 이름 : "task app project"
> 회사명 : "개인"
> 카테고리 : "라이브러리/데모"
※ '회사명' , '카테고리' 는 임의로 작성하였다.
"저장" 버튼을 클릭하여 애플리케이션을 추가한다.
추가된 애플리케이션 "task app project" 를 확인할 수 있다.
"task app project" 를 클릭하여, 애플리케이션의 설정으로 접속한다.
1-2) 애플리케이션 설정하기
카카오 로그인 > 활성화 설정 > 상태 : "ON"
OpenID Connent 활성화 설정 > 상태 : "ON"
Redirect URL : 추가 - "http://localhost:8080/login/oauth2/code/kakao"
이 부분이 중요하다.
동의항목 > 개인정보 > '닉네임' , '카카오계정(이메일)' - "필수동의"
[문제 상황 - 동의항목 (카카오계정(이메일) 추가하기)]
여기서 '닉네임' 은 "사용 안 함" 으로 설정 되어 있고, 이를 "필수 동의" 로 변경할 수 있었지만,
'카카오계정(이메일)' 은 "권한없음" 으로 설정되어 있다.
이 것은 "비즈 앱" 으로 설정되어 있지 않기 때문이다.
이전에는 "비즈 앱" 으로 설정 되어 있지 않았어도, 이메일 정보를 사용가능 했지만, 최근 "비즈 앱" 에 한해서 이메일 정보를 사용가능하도록 제한 해 둔 것 같다.
따라서 "비즈 앱" 으로 현재 애플리케이션을 등록해야 한다.
위 이미지는 이미 비즈 앱으로 등록된 애플리케이션의 화면이다.
내 애플리케이션> 앱 설정 > 비즈니스 > 비즈 앱 등록 을 통해 비즈 앱으로 등록한다.
※ 비즈 앱 등록은 안내를 쭉 따라가면 되기 때문에, 설명은 생략하겠다.
(비즈 앱 등록을 위해선 애플리케이션 대표 이미지를 등록해야 한다.)
1-3) "Client Secret" , "Client ID" 확인하기
보안 > Client Secret > 코드
Client Secret 를 확인한다.
앱 키 > 앱 키 > REST API 키
키를 확인한다.
2. application-oauth.yml 에 KAKAO OAuth 정보 등록하기
spring:
security:
oauth2:
client:
registration:
#GOOGLE 'client-id' , 'client-secret' , 'scope'
# google 생략
#KAKAO 'client-id' , 'client-secret' , 'scope'
kakao:
client-id: "your-kakao-client-id"
client-secret: "your-kakao-client-secret"
scope:
- profile_nickname
- account_email
#KAKAO Spring Security 수동 입력
redirect-uri: http://localhost:8080/login/oauth2/code/kakao
authorization-grant-type: authorization_code
client-name: Kakao
client-authentication-method: client_secret_post
#NAVER 'client-id' , 'client-secret' , 'scope'
#NAVER Spring Security 수동 입력
# naver 생략
provider:
#NAVER provider 등록
# naver provider 생략
#KAKAO provider 등록
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-name-attribute: kakao_account
<KAKAO 'client-id' , 'client-secret' , 'scope' 등록>
'client-id' 는 앞서 확인한 'REST_API 키' 이다.
'client-secret' 는 앞서 확인한 'client-secret' 코드 이다.
'scope' 는 동의항목에 있는 항목의 ID 를 입력한다. "profile_nickname" , "account_email"
<KAKAO Spring Security 수동 입력>
#KAKAO Spring Security 수동 입력
redirect-uri: http://localhost:8080/login/oauth2/code/kakao
authorization-grant-type: authorization_code
client-name: Kakao
client-authentication-method: client_secret_post
네이버와 모두 동일하지만, 'client-authentication-method: client_secret_post' 가 추가되었다.
스프링 부트의 버전이 2.x.x 에서 3.x.x 로 넘어가면서 추가되었다.
보안을 위해 'client-secret' 를 사용하는데, 이를 적극적으로 명시해주기 위함이다.
※ 만약 'client-authentication-method: client_secret_post' 을 추가하지 않으면,
이 오류가 발생하게 된다.
<KAKAO provider 등록>
#KAKAO provider 등록
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-name-attribute: kakao_account
네이버와 마찬가지로 provider 를 등록해야 한다.
3. OAuthAttributes.class
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Getter
@ToString
public class OAuthAttributes {
private Map<String, Object> attributes;
private String nameAttributeKey;
private String username;
private String email;
private UserRole role;
//인증자가 누구인지 구분 메서드
public static OAuthAttributes of(String registrationId,
String usernameAttributeName,
Map<String, Object> attributes) {
//1. Google
if (registrationId.equals("google")) {
return ofGoogle(usernameAttributeName, attributes);
}
//2. Kakao
if (registrationId.equals("kakao")) {
return ofKakao(usernameAttributeName, attributes);
}
//3. Naver
if (registrationId.equals("naver")) {
return ofNaver(usernameAttributeName, attributes);
}
return null;
}
private static OAuthAttributes ofKakao(String usernameAttributeName, Map<String, Object> attributes) {
Map<String, Object> response = (Map<String, Object>) attributes.get("kakao_account");
return OAuthAttributes.builder()
.username((String) response.get("email"))
.email((String) response.get("email"))
.attributes(response)
.nameAttributeKey(usernameAttributeName)
.build();
}
/*ofNaver 메서드 생략*/
/*ofGoogle 메서드 생략*/
}
}
"KakaoAccount" 의 속성에 "email" 속성을 가져온다.
4. Thymeleaf
<!--login.html 中...-->
<!--간편 로그인-->
<div class="social-login-container">
<!--구글 로그인-->
<a href="/oauth2/authorization/google" role="button" class="social-login-btn">
<img src="/img/google-logo.png" alt="google-login" class="login-img"/>
구글로 로그인
</a>
<!--네이버 로그인-->
<a href="/oauth2/authorization/naver" role="button" class="social-login-btn" style="background: #1EC800;">
<img src="/img/naver-logo.png" alt="naver-login" class="login-img"/>
네이버로 로그인
</a>
<!--카카오 로그인-->
<a href="/oauth2/authorization/kakao" role="button" class="social-login-btn" style="background: #FEE500;">
<img src="/img/kakao-logo.png" alt="kakao-login" class="login-img"/>
카카오로 로그인
</a>
</div>
"/oauth2/authorization/kakao" 로 URL 을 설정한다.
5. 완성 화면
소셜 로그인으로 로그인 된 회원이 DB에 추가된 것을 확인할 수 있다.