feat: API 토큰 관리 시스템 구현 (액세스/리프레시 토큰 분리)

- AuthService: 토큰 발급/갱신 통합 관리
- RefreshController: POST /api/v1/refresh 엔드포인트 추가
- 액세스 토큰 2시간, 리프레시 토큰 7일 (.env 설정)
- TOKEN_EXPIRED 에러 코드로 프론트엔드 자동 리프레시 지원
- 리프레시 토큰 일회성 사용 (보안 강화)
- Swagger 문서 Auth 태그로 통합
This commit is contained in:
2025-11-10 11:17:32 +09:00
parent 657623fef5
commit 798d5149ea
13 changed files with 639 additions and 12 deletions

View File

@@ -48,20 +48,19 @@ public function login(Request $request)
return response()->json(['error' => '아이디 또는 비밀번호가 올바르지 않습니다.'], 401);
}
// 인증토큰 생성
$token = $user->createToken('front-app')->plainTextToken;
// 선택: DB에 신규 token 저장
$USER_TOKEN = hash('sha256', $user->mb_id.date('YmdHis'));
$user->remember_token = $USER_TOKEN;
$user->save();
// 액세스 + 리프레시 토큰 발급
$tokens = \App\Services\AuthService::issueTokens($user);
// 사용자 정보 조회 (테넌트 + 메뉴 포함)
$loginInfo = \App\Services\MemberService::getUserInfoForLogin($user->id);
return response()->json([
'message' => '로그인 성공',
'user_token' => $token,
'access_token' => $tokens['access_token'],
'refresh_token' => $tokens['refresh_token'],
'token_type' => $tokens['token_type'],
'expires_in' => $tokens['expires_in'],
'expires_at' => $tokens['expires_at'],
'user' => $loginInfo['user'],
'tenant' => $loginInfo['tenant'],
'menus' => $loginInfo['menus'],

View File

@@ -0,0 +1,41 @@
<?php
namespace App\Http\Controllers\Api\V1;
use App\Http\Controllers\Controller;
use App\Http\Requests\Api\V1\RefreshRequest;
use App\Services\AuthService;
use Illuminate\Http\JsonResponse;
class RefreshController extends Controller
{
/**
* 리프레시 토큰으로 새로운 액세스 토큰을 발급합니다.
*
* @param RefreshRequest $request
* @return JsonResponse
*/
public function refresh(RefreshRequest $request): JsonResponse
{
$refreshToken = $request->validated()['refresh_token'];
// 리프레시 토큰으로 새로운 토큰 발급
$tokens = AuthService::refreshTokens($refreshToken);
if (! $tokens) {
return response()->json([
'error' => __('error.refresh_token_invalid_or_expired'),
'error_code' => 'TOKEN_EXPIRED',
], 401);
}
return response()->json([
'message' => __('message.token_refreshed'),
'access_token' => $tokens['access_token'],
'refresh_token' => $tokens['refresh_token'],
'token_type' => $tokens['token_type'],
'expires_in' => $tokens['expires_in'],
'expires_at' => $tokens['expires_at'],
]);
}
}