Meerkit
Meerkit
HomeDocsComponentsAPI
GitHub

Getting Started

5
IntroductionInstallationProject StructureThemingDeployment

CLI

6
CLI Overviewinit & setupstart, stop & openstatus, check, env & logsdbadd, test & update

Core Concepts

5
AuthenticationRoles & PermissionsData ModelLogin LockoutSecurity

Guides

3
Protect a pageAdd a roleCall your own API

Components

24

사용자 화면12

Login FormSignup FormEmail VerificationTerms AgreementGoogle LoginPassword ResetProfile & PasswordNicknameAuth DialogProfile ImageUser AvatarUser Menu

관리자 화면6

Member TableMember DirectoryMember AI UsageMember AI Usage HistoryRole ManagerRole Select

공통5

Address FieldFile DropzoneLoadingDateRoute Guards

AI Components

4
AI Prompt InputThinking IndicatorAPI Key InputVoice

API

6
OverviewHealthAuthUsers · 내 정보Users · 관리자LLM

Reference

2
Hooks & StateFAQ

Authentication

회원가입, 로그인, 토큰 흐름과 보안 규칙을 설명합니다.

인증은 짧게 사는 액세스 토큰과 쿠키에 담긴 리프레시 토큰 두 가지로 이루어집니다.

Token strategy

토큰저장 위치수명용도
Access token메모리 (Zustand, persist 안 함)짧음API 요청의 Authorization 헤더
Refresh tokenhttpOnly 쿠키김액세스 토큰 재발급
  • 액세스 토큰은 localStorage에 저장하지 않습니다. XSS로 읽히는 것을 막기 위해 메모리에만 둡니다.
  • 리프레시 토큰은 httpOnly 쿠키라 자바스크립트에서 읽을 수 없습니다.
  • /api 프록시로 프론트와 백엔드가 같은 도메인처럼 동작하므로 쿠키 방식이 잘 맞습니다.

Sign-up flow

사용자가 회원가입 화면에 정보 입력
        ↓
프론트에서 입력값 검증 (필수, 이메일 형식, 비밀번호 8자 이상)
        ↓
POST /auth/signup
        ↓
서버: 아이디·이메일 중복 확인
        ↓
서버: 비밀번호 해시 (Argon2) 후 users 저장, 기본 역할 부여
        ↓
가입 완료 → 프론트가 이어서 자동 로그인
가입 화면에는 역할 선택이 없습니다. 일반 사용자가 스스로 MASTER를 지정할 수 없도록, 기본 역할은 항상 서버가 부여합니다.

Login & refresh

  1. POST /auth/login이 액세스 토큰을 응답하고 리프레시 쿠키를 설정합니다.
  2. 프론트가 토큰을 스토어에 저장하고, GET /users/me로 내 정보를 가져옵니다.
  3. 이후 모든 요청에 Authorization: Bearer ...가 자동으로 붙습니다.
  4. 요청이 401을 받으면 POST /auth/refresh로 토큰을 갱신하고 원래 요청을 한 번 재시도합니다.
  5. 새로고침하면 MeerkitProvider가 리프레시 쿠키로 세션을 복원합니다.

단일 갱신

여러 요청이 동시에 401을 받아도 갱신 요청은 한 번만 보냅니다. 나머지는 그 결과를 기다렸다가 새 토큰으로 재시도합니다.

src/meerkit/api/client.ts
let refreshing: Promise<string | null> | null = null;

api.interceptors.response.use(undefined, async (error) => {
  const original = error.config;
  if (error.response?.status !== 401 || original._retried) {
    return Promise.reject(error);
  }
  original._retried = true;
  refreshing ??= refreshAccessToken().finally(() => (refreshing = null));
  const token = await refreshing;
  if (!token) return Promise.reject(error);
  original.headers.Authorization = `Bearer ${token}`;
  return api(original);
});

Logout

  1. 사용자가 로그아웃을 누르면 POST /auth/logout으로 서버의 리프레시 토큰을 폐기합니다.
  2. 서버 응답과 관계없이 프론트는 메모리의 액세스 토큰을 지우고 내 정보 캐시를 비웁니다.
  3. 화면은 로그인 전 상태로 돌아가고, 보호된 화면은 로그인 안내를 보여 줍니다.

Session restore

액세스 토큰은 메모리에만 있어서 새로고침하면 사라집니다. 대신 앱이 시작될 때 리프레시 쿠키로 POST /auth/refresh를 한 번 호출해 로그인 상태를 되살립니다.

상황결과
리프레시 쿠키 유효새 액세스 토큰을 받아 로그인 상태 복원
쿠키 없음·만료로그인 전 상태로 시작 (오류 표시 없음)
다른 탭에서 로그아웃다음 요청에서 갱신이 실패하며 로그아웃 상태가 됨

What the screen shows

상황화면 동작
가입 성공자동 로그인 후 모달이 닫힘
아이디·이메일 중복폼 아래에 서버 메시지 표시, 모달 유지
로그인 실패폼 아래에 오류 메시지 표시
보호된 화면에 비로그인으로 접근로그인 안내와 로그인 버튼 표시
권한이 없는 화면접근 권한이 없습니다 표시
비활성화·삭제된 계정로그인 차단 (서버가 거절)
연속 로그인 실패남은 시도 안내 후 한도에 닿으면 잠금과 카운트다운
약관 미동의필수 약관에 모두 동의해 주세요 오류, 요청은 나가지 않음

Password policy

  • 프론트는 8자 이상만 검사합니다. 복잡도(대소문자, 숫자, 특수문자) 규칙은 서버 정책으로 정하세요.
  • 비밀번호는 입력 후 화면 어디에도 다시 표시하거나 저장하지 않습니다.
  • 비밀번호 찾기·재설정과 비밀번호 변경은 제공됩니다 (Password Reset, Profile & Password 참고).

Related features

기능설명페이지
로그인 잠금n번 연속 실패하면 m분 잠금. 새로고침해도 유지Login Lockout
이메일 인증 (선택)가입 시 인증번호로 이메일 확인Email Verification
비밀번호 재설정이메일 링크로 새 비밀번호 설정Password Reset
내 정보·비밀번호 변경로그인한 사용자가 직접 수정Profile & Password
약관 동의가입 시 필수·선택 약관 동의Terms Agreement

Not included yet

  • 소셜 로그인, 2단계 인증
  • 모든 기기에서 로그아웃
  • 감사 로그

Security rules

  • 비밀번호는 원문을 저장하지 않고 Argon2 같은 안전한 해시로만 저장합니다.
  • 응답에 password_hash를 포함하지 않습니다.
  • 사용자 정보 수정은 본인 또는 허용된 관리자만 가능합니다. 서버에서 검증합니다.
  • 다른 사용자의 데이터를 조회하거나 삭제하지 못하도록 서버에서 권한을 확인합니다.
  • 계정 탈퇴는 바로 지우지 않고 deactivated_at을 기록해 막습니다. 보관 기간(기본 1년)이 지나면 서버가 개인정보를 지우고 deleted_at을 기록합니다.
  • 시드 관리자 계정은 로컬 테스트 전용이며 .env는 커밋하지 않습니다.
add, test & updateRoles & Permissions
© Meerkit. All rights reserved.GitHub