콘텐츠로 이동

로그인과 토큰 인증

App Backend의 회원 인증은 이메일·비밀번호와 HMAC 서명 JWT를 사용합니다. access token은 REST 자원 접근용이고 refresh token은 재발급 전용입니다. 둘은 type 클레임으로 구분되며 refresh token을 Bearer 인증으로 사용할 수 없습니다.

로그인과 refresh 회전

sequenceDiagram
    participant C as 클라이언트
    participant A as App Backend
    participant DB as PostgreSQL

    C->>A: POST /v1/auth/login<br/>email + password
    A->>DB: blind index로 회원 조회
    A->>A: Argon2id 비밀번호 검증
    A->>A: HMAC access(30분) + refresh(14일) 생성
    A->>DB: refresh 원문 SHA-256 해시 저장
    A-->>C: accessToken + refreshToken

    C->>A: POST /v1/auth/refresh<br/>refreshToken
    A->>A: 서명·issuer·만료·type 검증
    A->>DB: 토큰 해시와 활성 상태 조회
    A->>DB: 기존 refresh 폐기
    A->>A: 새 access + refresh 생성
    A->>DB: 새 refresh 해시 저장
    A-->>C: 회전된 토큰 쌍

JWT 계약

  • 서명: HMAC 대칭키. client-secret의 Ed25519 키와 별도입니다.
  • issuer: sohri-app-backend
  • subject: 이메일이 아닌 member.id UUID 문자열
  • access TTL: 1,800초(30분)
  • refresh TTL: 1,209,600초(14일)
  • 공통 클레임: jti, iss, sub, type, iat, exp
  • access token: roles 포함
  • refresh token: 권한 없이 재발급에만 사용

jti는 같은 초에 같은 회원에게 발급해도 토큰 문자열과 저장 해시가 충돌하지 않도록 매번 새 UUID를 사용합니다. refresh 원문은 DB에 저장하지 않고 SHA-256 해시만 저장합니다.

Socket 인증과 혼동하지 마세요

이 HMAC access JWT는 App Backend의 REST 인증 토큰입니다. Socket Backend가 이를 검증하거나 소비한다는 계약은 없습니다. 실시간 세션에는 Ed25519 client-secret을 사용합니다.

REST 사용

Authorization: Bearer <access-token>

공개 인증 경로는 POST /v1/auth/signup, /login, /refresh입니다. 보호 자원에 토큰이 없거나 잘못되면 401, 인증은 됐지만 역할·워크스페이스 권한이 부족하면 403을 반환합니다.

회원 탈퇴는 활성 refresh token을 모두 폐기합니다. 다만 이미 발급된 access token을 별도 deny-list로 즉시 폐기하는 구조는 아니므로 짧은 access TTL이 노출 창을 제한합니다.

워크스페이스 헤더와 역할 규칙은 워크스페이스와 테넌시, 운영 키 배선은 보안과 현재 격차를 참고하세요.