웹뷰 작업 중 쿠키에 토큰이 셋팅되지 않는 문제가 발생해서, 로그인부터 사용자 인증, 토큰 생성 및 검증 등 클라이언트와 서버 간 JWT 토큰을 공유하는 프로세스를 자세하게 짚고 넘어가려고 한다.
JWT (JSON Web Token)은 JSON 포맷으로 된 토큰 기반 인증 시스템임. JWT는 주로 클라이언트와 서버 간 인증을 위해 사용됨. JWT는 3개의 부분으로 나뉨:
ID와 비밀번호를 사용하여 사용자를 인증하는 기본적인 과정임. 사용자는 로그인 시 이메일과 비밀번호를 입력하고, 서버는 이를 사용하여 해당 사용자가 누구인지 확인함.
Laravel에서는 Auth 클래스를 사용하여 이를 쉽게 처리할 수 있음. 예를 들어:
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
// 인증 성공
return response()->json(['message' => 'Logged in']);
}
// 인증 실패
return response()->json(['error' => 'Unauthorized'], 401);
}
Auth::attempt($credentials)는 사용자가 제공한 자격증명이 데이터베이스에 있는 값과 일치하는지 확인하고, 일치하면 인증이 성공함.
사용자가 인증에 성공하면 서버는 JWT 토큰을 생성하여 클라이언트에게 전달함. 이 토큰은 이후 사용자 인증을 위한 인증 토큰으로 사용됨.
JWT 토큰에는 인증된 사용자에 대한 정보를 담을 수 있음. 예를 들어, 사용자 ID와 이메일을 페이로드에 담을 수 있음.
use Tymon\JWTAuth\Facades\JWTAuth;
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
$user = Auth::user(); // 인증된 사용자 정보
$token = JWTAuth::fromUser($user); // JWT 토큰 생성
return response()->json(['token' => $token]);
}
return response()->json(['error' => 'Unauthorized'], 401);
}
위 코드에서 JWTAuth::fromUser($user)는 사용자 객체를 기반으로 JWT 토큰을 생성함.
JWT 토큰을 쿠키에 담아서 클라이언트로 전송할 수 있음. 이 방법은 클라이언트가 자동으로 쿠키를 서버에 포함시켜 보내도록 함.
응답을 보낼 때 Set-Cookie 헤더를 사용하여 JWT 토큰을 쿠키에 저장하도록 할 수 있음. 예를 들어:
return response()->json(['message' => 'Logged in successfully'])
->cookie('access_token', $token, 60, '/', null, true, true);
위 코드에서 쿠키는 다음과 같이 설정됨:
서버에서 쿠키를 설정할 때는 response()->cookie() 메서드를 사용하여 자동으로 Set-Cookie 헤더를 클라이언트에게 보냄. 이렇게 하면 클라이언트는 응답을 받을 때 쿠키에 저장된 JWT 토큰을 자동으로 사용할 수 있음.
쿠키를 설정할 때는 보안, 만료 기간 등 다양한 옵션을 설정할 수 있음. 주요 옵션은 다음과 같음:
JWT 토큰의 유효성 검사는 토큰의 서명을 통해 이루어짐. JWT는 서버의 비밀 키를 사용하여 서명을 만들고, 클라이언트가 보낸 토큰이 서명된 내용과 일치하는지 확인함. 이를 통해 토큰이 변조되지 않았는지 확인할 수 있음.
use Tymon\JWTAuth\Facades\JWTAuth;
public function authenticate(Request $request)
{
try {
$user = JWTAuth::parseToken()->authenticate(); // 토큰 파싱 후 사용자 인증
return response()->json(['user' => $user]);
} catch (\Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
return response()->json(['error' => 'Token has expired'], 401);
} catch (\Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
return response()->json(['error' => 'Invalid token'], 401);
} catch (\Tymon\JWTAuth\Exceptions\JWTException $e) {
return response()->json(['error' => 'Token not provided'], 401);
}
}