클라이언트 사이드 랜더링을 기준으로 설명합니다.
카카오 공식문서: https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
에서 순서도를 참고하면 좋습니다.
알면 좋은 점
1. 소셜 로그인은 (백엔드 or프론트)한 부분에서 전부 맡아서 진행하는 게 안정적이다.
2. 상태관리는 백엔드에서만 진행한다.
명칭 얼라인
1. Service Client: 프론트(리액트)
2.Service Server: 백엔드(스프링)
3. Kakao Auth Server: 카카오 인증 서버
4. REST API KEY: KEY
순서도(핵심)
1. kakao디펠로퍼에서 REST API KEY발급(KEY획득)
2. AWS에서 고정 IP로 클라우드 서비스 만들기(고정 IP획득: 리다이렉트 URI)
3. 프론트에서 백엔드로 카카오 로그인 화면 요청
4. 백엔드는 (Redirect URI + KEY)를 이용해서 카카오 인증 서버로 리다이렉트하여 로그인화면 띄어줌.
5. 프론트는 동의화면을 받고 로그인을 진행한다.
6. 사용자가 로그인을 틀렸다면 카카오 인증서버에서(402,403) 권한 불가를 전부 내려준다.
7. 만약 로그인이 성공하였다면 카카오 인증서버가 인가코드를 302 Redirect URI인 백엔드에 내려준다.
8. 인가코드로 백엔드는 다시 카카오 인증 서버 (POST /oauth/token)로 접근하여 토큰을 발급한다.(액세스, 만료기한, 리프레시 등)
9. 토큰을 통해 카카오 서버에서 사용자 정보 조회(이름, 이메일, 성별, 사진 등) 후 등록
10. 서버 서비스 로직 실행 EX) DB에 정보 저장, 가입 절차 진행 등
11. 프론트에게 200 내려주면서 헤더에 set cookie로 (세션값 or JWT) 전달하기
12. 프론트는 로그인 완료정보를 토대로 메인 페이지로 넘어가기
13. 사용자 정보를 요청할때마다 헤더 set cookie값으로 올바른 이용자인지 확인 (로컬 스토리지, 리덕스등 사용자 정보 저장하기)
순서도 번호에서 생길 수 있는 질문들
3. 프론트에서 카카오 로그인을 바로 띄우지 않고 백엔드로 로그인 요청을 하는 이유는?
=> (KEY, IP)는 보안 취약점 요소이다, 따라서 백엔드에서 @Value 어노테이션을 사용하여 환경변수로 안전하게 관리해야 한다.
이때, 카카오 로그인 화면가입을 하기 위해서는 KEY와 Redirect URI(ip가 필요)를 통해서 동의화면 페이지를 띄어주는데
페이지는 아래와 같다.
*동의 화면: 동의 화면은 사용자와 앱이 처음 연결될 때만 나타납니다. 동의 이후에 카카오 로그인 시에는
동의 화면이 나타나지 않고 즉시 인가 코드를 발급합니다.
출처: https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#request-code
프론트 코드는 아래와 같다.
const Login = () => {
const REST_API_KEY = '백엔드한테 달라하자1';
const REDIRECT_URI = '백엔드한테 달라하자2';
const link = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`;
const loginHandler = () => {
window.location.href = link;
};
return (
<button type='button' onClick={loginHandler}>
로그인 하기
</button>
);
};
있어야 띄울 수 있기에 프론트에게 맡길 수 없다. 따라서 백엔드에서 로그인 요청이 오면 카카오 인가 서버로 프론트 주소를 알려주어
카카오 인가 서버가 프론트로 동의화면 페이지를 보내도록 한다.
8. 인가코드의 역할은 무엇인가요?
인가 코드로 토큰을 발급합니다.
code: "gpzZh7jck4ORCTIBCsuUiHxsp34tPRuikwaxmTnrZIjl7DNs7BVTxwAAAAQKPXO"
인가(동의) 코드는 다음과 비슷한 모양을 지니며, 로그인이 된 사용자의 토큰을 카카오 인증서버에서 받아올 수 있도록 한다.
*인가 코드는 동의 화면을 통해 인가받은 동의항목 정보를 가지고 있다.
8 . 토큰을 발급하면 어떤 게 들어있을까?
KakaoTokenResponseDTO.java
@Getter
@NoArgsConstructor //역직렬화를 위한 기본 생성자
@JsonIgnoreProperties(ignoreUnknown = true)
public class KakaoTokenResponseDTO {
@JsonProperty("token_type")
public String tokenType;
@JsonProperty("access_token")
public String accessToken;
@JsonProperty("id_token")
public String idToken;
@JsonProperty("expires_in")
public Integer expiresIn;
@JsonProperty("refresh_token")
public String refreshToken;
@JsonProperty("refresh_token_expires_in")
public Integer refreshTokenExpiresIn;
@JsonProperty("scope")
public String scope;
}
토큰타입, 액세스토큰, 엑세스토큰 만료기간, 리프레시토큰, 리프레시토큰 만료기간, scope(권한)이 들어있다.
9. 사용자 정보에는 무엇들이 들어있을까?
KakaoUserInfoResponseDto.java
에는 이렇게 많이 들어갈 수 있지만 동의화면에서 동의를 받아야 함.
또한 동의화면에 개인정보를 받기 위해서는 디벨로퍼(서비스)가 인정을 받아야 하기 때문에 3단계 절차가 있다.
QnA: https://devtalk.kakao.com/t/how-to-set-scopes-to-required-consent/115162
동의 항목별 "필수 동의" 설정 방법 / How to set scopes to ‘Required consent’
내 애플리케이션>제품 설정>카카오 로그인>동의항목 : 1. 디벨로퍼스앱 생성 후. 카카오 로그인 활성화 시, 기본 제공 [개인 정보] 닉네임 {profile_nickname} [필수] 프로필 사진 {profile_image} [필수] 카
devtalk.kakao.com
대표적으로 받는 것들은 AuthID, NickName, ProfileImageUrl이 있다.
@Getter
@NoArgsConstructor //역직렬화를 위한 기본 생성자
@JsonIgnoreProperties(ignoreUnknown = true)
public class KakaoUserInfoResponseDto {
//회원 번호
@JsonProperty("id")
public Long id;
//자동 연결 설정을 비활성화한 경우만 존재.
//true : 연결 상태, false : 연결 대기 상태
@JsonProperty("has_signed_up")
public Boolean hasSignedUp;
//서비스에 연결 완료된 시각. UTC
@JsonProperty("connected_at")
public Date connectedAt;
//카카오싱크 간편가입을 통해 로그인한 시각. UTC
@JsonProperty("synched_at")
public Date synchedAt;
//사용자 프로퍼티
@JsonProperty("properties")
public HashMap<String, String> properties;
//카카오 계정 정보
@JsonProperty("kakao_account")
public KakaoAccount kakaoAccount;
//uuid 등 추가 정보
@JsonProperty("for_partner")
public Partner partner;
@Getter
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class KakaoAccount {
//프로필 정보 제공 동의 여부
@JsonProperty("profile_needs_agreement")
public Boolean isProfileAgree;
//닉네임 제공 동의 여부
@JsonProperty("profile_nickname_needs_agreement")
public Boolean isNickNameAgree;
//프로필 사진 제공 동의 여부
@JsonProperty("profile_image_needs_agreement")
public Boolean isProfileImageAgree;
//사용자 프로필 정보
@JsonProperty("profile")
public Profile profile;
//이름 제공 동의 여부
@JsonProperty("name_needs_agreement")
public Boolean isNameAgree;
//카카오계정 이름
@JsonProperty("name")
public String name;
//이메일 제공 동의 여부
@JsonProperty("email_needs_agreement")
public Boolean isEmailAgree;
//이메일이 유효 여부
// true : 유효한 이메일, false : 이메일이 다른 카카오 계정에 사용돼 만료
@JsonProperty("is_email_valid")
public Boolean isEmailValid;
//이메일이 인증 여부
//true : 인증된 이메일, false : 인증되지 않은 이메일
@JsonProperty("is_email_verified")
public Boolean isEmailVerified;
//카카오계정 대표 이메일
@JsonProperty("email")
public String email;
//연령대 제공 동의 여부
@JsonProperty("age_range_needs_agreement")
public Boolean isAgeAgree;
//연령대
//참고 https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#req-user-info
@JsonProperty("age_range")
public String ageRange;
//출생 연도 제공 동의 여부
@JsonProperty("birthyear_needs_agreement")
public Boolean isBirthYearAgree;
//출생 연도 (YYYY 형식)
@JsonProperty("birthyear")
public String birthYear;
//생일 제공 동의 여부
@JsonProperty("birthday_needs_agreement")
public Boolean isBirthDayAgree;
//생일 (MMDD 형식)
@JsonProperty("birthday")
public String birthDay;
//생일 타입
// SOLAR(양력) 혹은 LUNAR(음력)
@JsonProperty("birthday_type")
public String birthDayType;
//성별 제공 동의 여부
@JsonProperty("gender_needs_agreement")
public Boolean isGenderAgree;
//성별
@JsonProperty("gender")
public String gender;
//전화번호 제공 동의 여부
@JsonProperty("phone_number_needs_agreement")
public Boolean isPhoneNumberAgree;
//전화번호
//국내 번호인 경우 +82 00-0000-0000 형식
@JsonProperty("phone_number")
public String phoneNumber;
//CI 동의 여부
@JsonProperty("ci_needs_agreement")
public Boolean isCIAgree;
//CI, 연계 정보
@JsonProperty("ci")
public String ci;
//CI 발급 시각, UTC
@JsonProperty("ci_authenticated_at")
public Date ciCreatedAt;
@Getter
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Profile {
//닉네임
@JsonProperty("nickname")
public String nickName;
//프로필 미리보기 이미지 URL
@JsonProperty("thumbnail_image_url")
public String thumbnailImageUrl;
//프로필 사진 URL
@JsonProperty("profile_image_url")
public String profileImageUrl;
//프로필 사진 URL 기본 프로필인지 여부
//true : 기본 프로필, false : 사용자 등록
@JsonProperty("is_default_image")
public String isDefaultImage;
//닉네임이 기본 닉네임인지 여부
//true : 기본 닉네임, false : 사용자 등록
@JsonProperty("is_default_nickname")
public Boolean isDefaultNickName;
}
}
@Getter
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Partner {
//고유 ID
@JsonProperty("uuid")
public String uuid;
}
의문
Q1. 카카오는 액세스 토큰을 알아서 재발급해줄까?
아마 해주지 않는다.
'Solo Project > 소셜로그인+JWT' 카테고리의 다른 글
[최종] Spring OAuth2.0 client + 카카오 (로그인, 로그아웃) + JWT (0) | 2024.08.31 |
---|---|
[ERROR] CORS + SOP + preflight (0) | 2024.08.06 |