beaniejoy / dongne-cafe-api

☕️ kotlin & spring boot application (toy project) / siren order service for local cafe
2 stars 1 forks source link

JWT 인증/인가 방식 개선 #73

Closed beaniejoy closed 11 months ago

beaniejoy commented 1 year ago

flow

refresh_token은 db table 관리방식으로 선택

  1. 로그인 인증시

    • 인증시 access_token, refresh_token 2개 동시 발급(만료기간은 access는 1시간, refresh는 14일 이런 식으로)
    • db table에 user_id, refresh_token 내용 저장
    • 둘다 클라이언트에 response로 내려보내준다. (refresh는 최초 로그인 때만 발급)
  2. api 요청에 대한 인가(access_token만 대상)

    • api 요청시 Authorization header에 access_token 값 담아서 요청
    • 유효한 토큰인 경우 api 정상 처리
    • 만료된 경우 만료응답 처리(access_token 만료만 대상, 프론트단에서 갱신 요청하도록 유도)
  3. 인증토큰 갱신(access_token 갱신 목표)

    • 토큰 만료응답을 받은 경우 클라이언트단에 저장되어있던 refresh_token, access_token 같이 전송
    • access_token, refresh_token 기본적인 검증 필요
    • access refresh 만료 여부 체크, access_token, refresh_token 동일한 user_id를 담고 있는지 체크
    • exception 반환 케이스
    • 둘 다 만료상태가 아닌 경우, 둘 다 만료상태인 경우(갱신불가)
    • 요청 헤더로 들어온 refresh의 user_id로 Table 조회했을 때 refresh와 값 비교해서 다른 경우
    • refresh가 만료된 경우(refresh는 갱신하지 않는 것으로)
    • 갱신 케이스
    • access(유효), refresh(유효): BusinessException 반환(갱신 불가 예외, but 200 ok status)
    • access(만료), refresh(유효): access 갱신
    • access(유효), refresh(만료): BusinessException 반환(갱신 불가 예외, but 200 ok status)
    • access(만료), refresh(만료): 둘 다 만료된 것이기에 인증 오류(다시 로그인부터 진행되도록 유도)
    • 갱신된 access token만 response에 담아 저장
    • 갱신시
    • access_token으로 AuthToken Entity 조회 후 refresh_token으로 memberId, authorities 값 받아서 access_token 신규 생성

생각해볼거리

수정 사항

테이블 추가

CREATE TABLE `auth_tokens` (
    `token_id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'refresh token ID',
    `member_id` bigint unsigned NOT NULL COMMENT '회원 ID',
    `access_token` varchar(200) NOT NULL COMMENT 'access 전용 token',
    `refresh_token` varchar(200) NOT NULL COMMENT 'refresh 전용 token',
    `created_at` datetime NOT NULL COMMENT '토큰 등록날짜',
    `updated_at` datetime NULL COMMENT '토큰 변경날짜',
    PRIMARY KEY (`token_id`),
    UNIQUE KEY `uk_accesstoken` (`access_token`),
    UNIQUE KEY `uk_refreshtoken` (`refresh_token`),
    KEY `member_id` (`member_id`),
    FOREIGN KEY (`member_id`) REFERENCES `members` (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;