Laravel Fortify
업데이트됨번역일: 2026년 11월 9일
이 페이지는 원문이 업데이트되어 번역이 갱신되었습니다.
- 원문 수정
- 2026년 11월 6일
- 번역 갱신
- 2026년 11월 9일
Laravel Fortify
소개
Laravel Fortify는 Laravel을 위한 프론트엔드 독립형(frontend agnostic) 인증 백엔드 구현체입니다. Fortify는 로그인, 회원가입, 비밀번호 재설정, 이메일 인증 등 Laravel의 모든 인증 기능을 구현하는 데 필요한 라우트와 컨트롤러를 등록해 줍니다. Fortify를 설치한 뒤 route:list Artisan 명령어를 실행하면 Fortify가 등록한 라우트를 확인할 수 있습니다.
Fortify는 자체 사용자 인터페이스를 제공하지 않으므로, 직접 만든 사용자 인터페이스에서 Fortify가 등록한 라우트로 요청을 보내는 방식으로 함께 사용하도록 설계되었습니다. 이 라우트들에 어떻게 요청을 보내는지는 이 문서의 나머지 부분에서 자세히 설명합니다.
NOTE
Fortify는 Laravel의 인증 기능을 더 빠르게 구현하도록 돕는 패키지일 뿐, 반드시 사용해야 하는 것은 아닙니다. 인증, 비밀번호 재설정, 이메일 인증 문서를 참고해 Laravel의 인증 서비스를 직접 다룰 수도 있습니다.
Fortify란?
앞서 설명했듯이 Laravel Fortify는 Laravel을 위한 프론트엔드 독립형 인증 백엔드 구현체입니다. Fortify는 로그인, 회원가입, 비밀번호 재설정, 이메일 인증 등 Laravel의 모든 인증 기능에 필요한 라우트와 컨트롤러를 등록해 줍니다.
Laravel의 인증 기능을 쓰기 위해 Fortify가 꼭 필요한 것은 아닙니다. 인증, 비밀번호 재설정, 이메일 인증 문서를 따라 Laravel의 인증 서비스를 직접 사용하는 방법도 언제든 선택할 수 있습니다.
Laravel을 처음 접한다면 먼저 애플리케이션 스타터 키트를 살펴보는 것도 좋습니다. 스타터 키트는 내부적으로 Fortify를 사용하며, Tailwind CSS로 만든 사용자 인터페이스까지 갖춘 인증 스캐폴딩을 제공합니다. 이를 통해 Laravel의 인증 기능을 익히고 감을 잡을 수 있습니다.
Laravel Fortify는 스타터 키트의 라우트와 컨트롤러를 사용자 인터페이스 없이 패키지 형태로 제공하는 것이라고 이해하면 쉽습니다. 따라서 특정 프론트엔드 방식에 얽매이지 않으면서도 애플리케이션 인증 계층의 백엔드를 빠르게 구축할 수 있습니다.
Fortify는 언제 사용해야 할까요?
Laravel Fortify를 언제 사용하는 것이 적절한지 궁금할 수 있습니다. 우선 Laravel의 애플리케이션 스타터 키트를 사용 중이라면 Fortify를 따로 설치할 필요가 없습니다. 모든 스타터 키트가 이미 Fortify를 사용하고 있으며 완전한 인증 구현을 제공하기 때문입니다.
스타터 키트를 사용하지 않으면서 애플리케이션에 인증 기능이 필요하다면 두 가지 선택지가 있습니다. 인증 기능을 직접 구현하거나, Laravel Fortify로 이 기능들의 백엔드 구현을 제공받는 것입니다.
Fortify를 설치하기로 했다면, 사용자 인터페이스가 이 문서에서 설명하는 Fortify의 인증 라우트로 요청을 보내 사용자를 인증하고 등록하게 됩니다.
Fortify 대신 Laravel의 인증 서비스를 직접 다루기로 했다면 인증, 비밀번호 재설정, 이메일 인증 문서를 따라 구현하면 됩니다.
Laravel Fortify와 Laravel Sanctum
Laravel Sanctum과 Laravel Fortify의 차이를 헷갈려 하는 개발자가 많습니다. 두 패키지는 서로 다르지만 연관된 문제를 해결하므로, Laravel Fortify와 Laravel Sanctum은 배타적이거나 경쟁하는 패키지가 아닙니다.
Laravel Sanctum은 API 토큰을 관리하고, 세션 쿠키나 토큰으로 이미 존재하는 사용자를 인증하는 일만 담당합니다. 회원가입이나 비밀번호 재설정 같은 라우트는 제공하지 않습니다.
API를 제공하거나 싱글 페이지 애플리케이션(SPA)의 백엔드 역할을 하는 애플리케이션의 인증 계층을 직접 구축한다면, 회원가입·비밀번호 재설정 등에는 Laravel Fortify를, API 토큰 관리와 세션 인증에는 Laravel Sanctum을 함께 사용하는 경우도 충분히 있을 수 있습니다.
설치
먼저 Composer 패키지 관리자로 Fortify를 설치합니다.
composer require laravel/fortify다음으로 fortify:install Artisan 명령어로 Fortify의 리소스를 게시(publish)합니다.
php artisan fortify:install이 명령어는 Fortify의 액션들을 app/Actions 디렉터리에 게시하며, 해당 디렉터리가 없으면 새로 생성합니다. 또한 FortifyServiceProvider, 설정 파일, 필요한 모든 데이터베이스 마이그레이션도 함께 게시합니다.
그다음 데이터베이스 마이그레이션을 실행합니다.
php artisan migrateFortify 기능
fortify 설정 파일에는 features 설정 배열이 있습니다. 이 배열은 Fortify가 기본으로 노출할 백엔드 라우트와 기능을 정의합니다. 대부분의 Laravel 애플리케이션에서 제공하는 기본적인 인증 기능에 해당하는 아래 기능만 활성화하는 것을 권장합니다.
'features' => [
Features::registration(),
Features::resetPasswords(),
Features::emailVerification(),
],뷰 비활성화
기본적으로 Fortify는 로그인 화면이나 회원가입 화면처럼 뷰를 반환하도록 만들어진 라우트를 정의합니다. 하지만 JavaScript 기반의 싱글 페이지 애플리케이션을 만든다면 이런 라우트는 필요하지 않을 수 있습니다. 이 경우 애플리케이션의 config/fortify.php 설정 파일에서 views 설정 값을 false로 지정해 이 라우트들을 완전히 비활성화할 수 있습니다.
'views' => false,뷰 비활성화와 비밀번호 재설정
Fortify의 뷰를 비활성화하면서 애플리케이션에 비밀번호 재설정 기능을 구현할 계획이라면, "비밀번호 재설정" 뷰를 보여 주는 password.reset이라는 이름의 라우트를 반드시 직접 정의해야 합니다. Laravel의 Illuminate\Auth\Notifications\ResetPassword 알림이 password.reset 이름 라우트를 이용해 비밀번호 재설정 URL을 생성하기 때문입니다.
인증
먼저 Fortify가 "로그인" 뷰를 어떻게 반환할지 알려 주어야 합니다. Fortify는 화면이 없는(headless) 인증 라이브러리라는 점을 기억하세요. Laravel의 인증 기능이 프론트엔드까지 이미 구현된 형태를 원한다면 애플리케이션 스타터 키트를 사용하면 됩니다.
인증 뷰의 렌더링 로직은 모두 Laravel\Fortify\Fortify 클래스가 제공하는 적절한 메서드로 커스터마이징할 수 있습니다. 보통 이 메서드는 애플리케이션의 App\Providers\FortifyServiceProvider 클래스의 boot 메서드에서 호출합니다. 그러면 Fortify가 이 뷰를 반환하는 /login 라우트를 정의해 줍니다.
use Laravel\Fortify\Fortify;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Fortify::loginView(function () {
return view('auth.login');
});
// ...
}로그인 템플릿에는 /login으로 POST 요청을 보내는 폼이 있어야 합니다. /login 엔드포인트는 문자열 형태의 email / username과 password를 요구합니다. 이메일 / 사용자 이름 필드의 이름은 config/fortify.php 설정 파일의 username 값과 일치해야 합니다. 또한 Laravel이 제공하는 "로그인 상태 유지(remember me)" 기능을 사용하려면 불리언 remember 필드를 함께 전달할 수 있습니다.
로그인 시도가 성공하면 Fortify는 애플리케이션의 fortify 설정 파일에서 home 설정 옵션으로 지정한 URI로 리디렉션합니다. 로그인 요청이 XHR 요청이었다면 200 HTTP 응답이 반환됩니다.
요청이 실패하면 사용자는 로그인 화면으로 다시 리디렉션되며, 유효성 검증 오류는 공유 변수인 $errors Blade 템플릿 변수로 사용할 수 있습니다. XHR 요청의 경우에는 유효성 검증 오류가 422 HTTP 응답과 함께 반환됩니다.
사용자 인증 커스터마이징
Fortify는 제공된 자격 증명과 애플리케이션에 설정된 인증 가드를 기반으로 사용자를 자동으로 조회하고 인증합니다. 하지만 로그인 자격 증명을 인증하는 방식과 사용자를 조회하는 방식을 완전히 직접 제어하고 싶을 때도 있습니다. Fortify에서는 Fortify::authenticateUsing 메서드로 이를 간단히 구현할 수 있습니다.
이 메서드는 들어오는 HTTP 요청을 전달받는 클로저를 인자로 받습니다. 클로저는 요청에 담긴 로그인 자격 증명을 검증하고, 해당하는 사용자 인스턴스를 반환해야 합니다. 자격 증명이 올바르지 않거나 사용자를 찾을 수 없다면 클로저에서 null 또는 false를 반환해야 합니다. 보통 이 메서드는 FortifyServiceProvider의 boot 메서드에서 호출합니다.
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Laravel\Fortify\Fortify;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Fortify::authenticateUsing(function (Request $request) {
$user = User::where('email', $request->email)->first();
if ($user &&
Hash::check($request->password, $user->password)) {
return $user;
}
});
// ...
}인증 가드
Fortify가 사용하는 인증 가드는 애플리케이션의 fortify 설정 파일에서 변경할 수 있습니다. 다만 설정한 가드는 반드시 Illuminate\Contracts\Auth\StatefulGuard의 구현체여야 합니다. Laravel Fortify로 SPA를 인증하려는 경우에는 Laravel의 기본 web 가드를 Laravel Sanctum과 함께 사용해야 합니다.
인증 파이프라인 커스터마이징
Laravel Fortify는 호출 가능한(invokable) 클래스들로 이루어진 파이프라인을 통해 로그인 요청을 인증합니다. 원한다면 로그인 요청이 거쳐 갈 클래스들의 파이프라인을 직접 정의할 수 있습니다. 각 클래스에는 들어오는 Illuminate\Http\Request 인스턴스를 받는 __invoke 메서드가 있어야 하며, 미들웨어처럼 요청을 파이프라인의 다음 클래스로 넘기기 위해 호출하는 $next 변수도 함께 받습니다.
커스텀 파이프라인을 정의하려면 Fortify::authenticateThrough 메서드를 사용합니다. 이 메서드는 로그인 요청이 거쳐 갈 클래스 배열을 반환하는 클로저를 인자로 받습니다. 보통 이 메서드는 App\Providers\FortifyServiceProvider 클래스의 boot 메서드에서 호출합니다.
아래 예제는 기본 파이프라인 정의로, 이를 출발점 삼아 필요한 부분을 수정할 수 있습니다.
use Laravel\Fortify\Actions\AttemptToAuthenticate;
use Laravel\Fortify\Actions\CanonicalizeUsername;
use Laravel\Fortify\Actions\EnsureLoginIsNotThrottled;
use Laravel\Fortify\Actions\PrepareAuthenticatedSession;
use Laravel\Fortify\Actions\RedirectIfTwoFactorAuthenticatable;
use Laravel\Fortify\Features;
use Laravel\Fortify\Fortify;
use Illuminate\Http\Request;
Fortify::authenticateThrough(function (Request $request) {
return array_filter([
config('fortify.limiters.login') ? null : EnsureLoginIsNotThrottled::class,
config('fortify.lowercase_usernames') ? CanonicalizeUsername::class : null,
Features::enabled(Features::twoFactorAuthentication()) ? RedirectIfTwoFactorAuthenticatable::class : null,
AttemptToAuthenticate::class,
PrepareAuthenticatedSession::class,
]);
});인증 시도 제한(Throttling)
기본적으로 Fortify는 EnsureLoginIsNotThrottled 미들웨어로 인증 시도 횟수를 제한합니다. 이 미들웨어는 사용자 이름과 IP 주소의 조합별로 시도 횟수를 제한합니다.
애플리케이션에 따라서는 IP 주소만으로 제한하는 등 다른 방식이 필요할 수 있습니다. 그래서 Fortify는 fortify.limiters.login 설정 옵션으로 직접 만든 레이트 리미터를 지정할 수 있게 해 줍니다.
커스텀 로그인 레이트 리미터를 설정하면 Fortify가 해당하는 throttle 미들웨어를 로그인 라우트에 자동으로 적용하므로, 이 미들웨어를 직접 붙일 필요가 없습니다.
이 설정 옵션은 애플리케이션의 config/fortify.php 설정 파일에서 확인할 수 있습니다.
NOTE
시도 횟수 제한, 2단계 인증, 외부 웹 애플리케이션 방화벽(WAF)을 함께 사용하면 정상적인 사용자를 가장 견고하게 보호할 수 있습니다.
리디렉션 커스터마이징
로그인 시도가 성공하면 Fortify는 애플리케이션의 fortify 설정 파일에서 home 설정 옵션으로 지정한 URI로 리디렉션합니다. 로그인 요청이 XHR 요청이었다면 200 HTTP 응답이 반환됩니다. 사용자가 애플리케이션에서 로그아웃하면 / URI로 리디렉션됩니다.
이 동작을 더 세밀하게 커스터마이징해야 한다면 LoginResponse와 LogoutResponse 컨트랙트의 구현체를 Laravel 서비스 컨테이너에 바인딩하면 됩니다. 보통 이 작업은 애플리케이션의 App\Providers\FortifyServiceProvider 클래스의 register 메서드 안에서 수행합니다.
use Laravel\Fortify\Contracts\LogoutResponse;
/**
* Register any application services.
*/
public function register(): void
{
$this->app->instance(LogoutResponse::class, new class implements LogoutResponse {
public function toResponse($request)
{
return redirect('/');
}
});
}2단계 인증
Fortify의 2단계 인증 기능을 활성화하면, 사용자는 인증 과정에서 6자리 숫자 토큰을 입력해야 합니다. 이 토큰은 시간 기반 일회용 비밀번호(TOTP)로 생성되며, Google Authenticator 같은 TOTP 호환 모바일 인증 애플리케이션에서 확인할 수 있습니다.
시작하기 전에 애플리케이션의 App\Models\User 모델이 Laravel\Fortify\TwoFactorAuthenticatable 트레이트를 사용하는지 먼저 확인하세요.
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Fortify\TwoFactorAuthenticatable;
class User extends Authenticatable
{
use Notifiable, TwoFactorAuthenticatable;
}다음으로, 사용자가 자신의 2단계 인증 설정을 관리할 수 있는 화면을 애플리케이션에 만들어야 합니다. 이 화면에서는 2단계 인증을 활성화하거나 비활성화할 수 있어야 하고, 2단계 인증 복구 코드를 다시 생성할 수도 있어야 합니다.
기본적으로
fortify설정 파일의features배열은 2단계 인증 설정을 변경하기 전에 비밀번호 확인을 요구하도록 되어 있습니다. 따라서 다음 단계로 넘어가기 전에 애플리케이션에 Fortify의 비밀번호 확인 기능을 구현해야 합니다.
2단계 인증 활성화
2단계 인증을 활성화하려면 애플리케이션에서 Fortify가 정의한 /user/two-factor-authentication 엔드포인트로 POST 요청을 보냅니다. 요청이 성공하면 사용자는 이전 URL로 리디렉션되고, status 세션 변수에 two-factor-authentication-enabled가 설정됩니다. 템플릿에서 이 status 세션 변수를 확인해 적절한 성공 메시지를 표시할 수 있습니다. 요청이 XHR 요청이었다면 200 HTTP 응답이 반환됩니다.
사용자가 2단계 인증을 활성화한 뒤에도 유효한 2단계 인증 코드를 입력해 설정을 "확인"해야 합니다. 따라서 "성공" 메시지에서 2단계 인증 확인이 아직 남아 있음을 안내해야 합니다.
@if (session('status') == 'two-factor-authentication-enabled')
<div class="mb-4 font-medium text-sm">
아래에서 2단계 인증 설정을 마무리해 주세요.
</div>
@endif그다음 사용자가 인증 애플리케이션으로 스캔할 수 있도록 2단계 인증 QR 코드를 표시해야 합니다. Blade로 프론트엔드를 렌더링한다면 사용자 인스턴스의 twoFactorQrCodeSvg 메서드로 QR 코드 SVG를 가져올 수 있습니다.
$request->user()->twoFactorQrCodeSvg();JavaScript 기반 프론트엔드를 만든다면 /user/two-factor-qr-code 엔드포인트로 XHR GET 요청을 보내 사용자의 2단계 인증 QR 코드를 가져올 수 있습니다. 이 엔드포인트는 svg 키를 가진 JSON 객체를 반환합니다.
2단계 인증 확인
사용자의 2단계 인증 QR 코드를 표시하는 것과 함께, 사용자가 유효한 인증 코드를 입력해 2단계 인증 설정을 "확인"할 수 있는 텍스트 입력란도 제공해야 합니다. 이 코드는 Fortify가 정의한 /user/confirmed-two-factor-authentication 엔드포인트로 POST 요청을 보내 Laravel 애플리케이션에 전달합니다.
요청이 성공하면 사용자는 이전 URL로 리디렉션되고, status 세션 변수에 two-factor-authentication-confirmed가 설정됩니다.
@if (session('status') == 'two-factor-authentication-confirmed')
<div class="mb-4 font-medium text-sm">
2단계 인증이 확인되어 정상적으로 활성화되었습니다.
</div>
@endif2단계 인증 확인 엔드포인트에 대한 요청이 XHR 요청이었다면 200 HTTP 응답이 반환됩니다.
복구 코드 표시
사용자의 2단계 인증 복구 코드도 함께 표시해야 합니다. 복구 코드는 사용자가 모바일 기기에 접근하지 못하게 되었을 때 인증할 수 있게 해 줍니다. Blade로 프론트엔드를 렌더링한다면 인증된 사용자 인스턴스를 통해 복구 코드에 접근할 수 있습니다.
(array) $request->user()->recoveryCodes();JavaScript 기반 프론트엔드를 만든다면 /user/two-factor-recovery-codes 엔드포인트로 XHR GET 요청을 보내면 됩니다. 이 엔드포인트는 사용자의 복구 코드가 담긴 JSON 배열을 반환합니다.
사용자의 복구 코드를 다시 생성하려면 애플리케이션에서 /user/two-factor-recovery-codes 엔드포인트로 POST 요청을 보내야 합니다.
2단계 인증으로 인증하기
인증 과정에서 Fortify는 사용자를 애플리케이션의 2단계 인증 확인(challenge) 화면으로 자동 리디렉션합니다. 다만 애플리케이션이 XHR 로그인 요청을 보내는 경우, 인증에 성공했을 때 반환되는 JSON 응답에는 불리언 속성 two_factor를 가진 JSON 객체가 담겨 있습니다. 이 값을 확인해 2단계 인증 확인 화면으로 리디렉션해야 하는지 판단하세요.
2단계 인증 기능을 구현하려면 먼저 Fortify가 2단계 인증 확인 뷰를 어떻게 반환할지 알려 주어야 합니다. Fortify의 모든 인증 뷰 렌더링 로직은 Laravel\Fortify\Fortify 클래스가 제공하는 적절한 메서드로 커스터마이징할 수 있습니다. 보통 이 메서드는 애플리케이션의 App\Providers\FortifyServiceProvider 클래스의 boot 메서드에서 호출합니다.
use Laravel\Fortify\Fortify;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Fortify::twoFactorChallengeView(function () {
return view('auth.two-factor-challenge');
});
// ...
}Fortify가 이 뷰를 반환하는 /two-factor-challenge 라우트를 정의해 줍니다. two-factor-challenge 템플릿에는 /two-factor-challenge 엔드포인트로 POST 요청을 보내는 폼이 있어야 합니다. /two-factor-challenge 액션은 유효한 TOTP 토큰이 담긴 code 필드, 또는 사용자의 복구 코드 중 하나가 담긴 recovery_code 필드를 요구합니다.
로그인 시도가 성공하면 Fortify는 애플리케이션의 fortify 설정 파일에서 home 설정 옵션으로 지정한 URI로 사용자를 리디렉션합니다. 로그인 요청이 XHR 요청이었다면 204 HTTP 응답이 반환됩니다.
요청이 실패하면 사용자는 2단계 인증 확인 화면으로 다시 리디렉션되며, 유효성 검증 오류는 공유 변수인 $errors Blade 템플릿 변수로 사용할 수 있습니다. XHR 요청의 경우에는 유효성 검증 오류가 422 HTTP 응답과 함께 반환됩니다.
2단계 인증 비활성화
2단계 인증을 비활성화하려면 애플리케이션에서 /user/two-factor-authentication 엔드포인트로 DELETE 요청을 보내야 합니다. Fortify의 2단계 인증 엔드포인트는 호출하기 전에 비밀번호 확인이 필요하다는 점을 기억하세요.
패스키
Fortify는 WebAuthn을 이용한 패스키 인증을 지원합니다. 패스키를 사용하면 Face ID, Touch ID, Windows Hello 같은 플랫폼 인증기나 하드웨어 보안 키로 비밀번호 없이 인증할 수 있습니다.
패스키 활성화
먼저 애플리케이션의 fortify 설정 파일에서 passkeys 기능이 활성화되어 있는지 확인합니다.
use Laravel\Fortify\Features;
'features' => [
// ...
Features::passkeys([
'confirmPassword' => true,
]),
],confirmPassword 옵션은 패스키를 등록하거나 삭제하기 전에 Fortify가 비밀번호 확인을 요구할지 여부를 결정합니다.
다음으로 애플리케이션의 App\Models\User 모델이 Laravel\Fortify\Contracts\PasskeyUser를 구현하고 Laravel\Fortify\PasskeyAuthenticatable 트레이트를 사용하는지 확인합니다.
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Fortify\Contracts\PasskeyUser;
use Laravel\Fortify\PasskeyAuthenticatable;
class User extends Authenticatable implements PasskeyUser
{
use Notifiable, PasskeyAuthenticatable;
}Fortify의 패스키 설정 옵션은 애플리케이션의 config/fortify.php 파일에 있는 passkeys 설정 배열로 커스터마이징할 수 있습니다.
'passkeys' => [
'relying_party_id' => parse_url(config('app.url'), PHP_URL_HOST),
'allowed_origins' => [config('app.url')],
'user_handle_secret' => config('app.key'),
'timeout' => 60000,
],NOTE
Fortify는 laravel/passkeys Composer 패키지를 감싸서 대신 설정해 줍니다. Fortify의 패스키 기능을 사용한다면 애플리케이션의 config/fortify.php 파일에서 패스키를 설정해야 합니다. laravel/passkeys 설정 파일을 게시할 필요는 없으며, 그 파일에 정의한 값은 Fortify가 덮어씁니다.
relying_party_id는 애플리케이션의 도메인과 일치해야 합니다. allowed_origins 배열은 패스키 등록과 인증을 완료할 수 있는 브라우저 오리진 목록입니다. user_handle_secret은 식별 가능한 정보를 직접 드러내지 않는 사용자 식별자를 만드는 데 사용되며, 패스키를 여러 번 등록하더라도 같은 사용자로 인식되도록 해 줍니다. timeout 옵션은 패스키 등록 및 인증 작업이 유지될 수 있는 시간을 제어합니다.
Fortify는 패스키 로그인, 확인, 등록 라우트에 전용 패스키 레이트 리미터를 적용합니다. 필요하다면 fortify.limiters.passkeys 설정 옵션과 그에 대응하는 RateLimiter::for(...) 정의로 이를 커스터마이징할 수 있습니다.
JavaScript 클라이언트
브라우저 측 스크립트를 사용하는 Blade 애플리케이션을 포함해 커스텀 프론트엔드를 만든다면 공식 @laravel/passkeys 패키지를 사용할 수 있습니다. 이 패키지는 브라우저의 WebAuthn 절차를 처리하고 Fortify의 패스키 엔드포인트로 요청을 보냅니다.
npm으로 패키지를 설치합니다.
npm install @laravel/passkeys그런 다음 프론트엔드에서 패스키 등록과 검증을 시작할 수 있습니다.
import { Passkeys } from "@laravel/passkeys";
await Passkeys.register({ name: "MacBook Pro" });
await Passkeys.verify();애플리케이션이 커스텀 패스키 엔드포인트 URI를 사용한다면 호출할 때마다 라우트를 재정의할 수 있습니다.
await Passkeys.verify({
routes: {
options: "/passkeys/confirm/options",
submit: "/passkeys/confirm",
},
});
await Passkeys.register({
name: "MacBook Pro",
routes: {
options: "/user/passkeys/options",
submit: "/user/passkeys",
},
});이 패키지는 @laravel/passkeys/react, @laravel/passkeys/vue, @laravel/passkeys/svelte를 통해 React, Vue, Svelte용 헬퍼도 제공합니다.
패스키로 인증하기
패스키로 사용자를 인증하려면 애플리케이션에서 먼저 /passkeys/login/options 엔드포인트로 GET 요청을 보냅니다. 이 엔드포인트는 프론트엔드가 navigator.credentials.get(...)에 전달해야 하는 WebAuthn 챌린지 옵션을 반환합니다.
브라우저가 자격 증명(credential)을 반환하면, 애플리케이션에서 그 자격 증명 페이로드와 함께 /passkeys/login으로 POST 요청을 보냅니다. 불리언 remember 필드를 함께 보낼 수도 있습니다.
요청이 성공하면 Fortify는 설정된 가드로 사용자를 로그인시키고 다음 중 하나를 반환합니다.
- 일반 요청의 경우: 의도한 목적지로 가는 리디렉션 응답
- XHR 요청의 경우:
redirect키가 담긴 JSON 페이로드를 포함한200HTTP 응답
패스키로 비밀번호 확인하기
인증된 세션에 대해, Fortify는 현재 세션의 Laravel 비밀번호 확인 요건을 충족시켜 주는 패스키 확인 엔드포인트를 제공합니다.
패스키로 확인하려면 애플리케이션에서 먼저 /passkeys/confirm/options로 GET 요청을 보냅니다. 이 엔드포인트는 프론트엔드가 navigator.credentials.get(...)에 전달해야 하는 WebAuthn 챌린지 옵션을 반환합니다.
브라우저가 자격 증명을 반환하면, 애플리케이션에서 그 자격 증명 페이로드와 함께 /passkeys/confirm으로 POST 요청을 보냅니다.
요청이 성공하면 Fortify는 현재 세션을 비밀번호 확인 완료 상태로 표시하고 다음 중 하나를 반환합니다.
- 일반 요청의 경우: 의도한 목적지로 가는 리디렉션 응답
- XHR 요청의 경우:
redirect키가 담긴 JSON 페이로드를 포함한200HTTP 응답
패스키 등록
인증된 사용자의 패스키를 등록하려면 애플리케이션에서 먼저 /user/passkeys/options로 GET 요청을 보냅니다. 이 엔드포인트는 프론트엔드가 navigator.credentials.create(...)에 전달해야 하는 WebAuthn 생성 옵션을 반환합니다.
브라우저가 자격 증명을 반환하면, 애플리케이션에서 name 필드와, navigator.credentials.create(...)가 반환한 PublicKeyCredential 객체를 직렬화한 값을 담은 credential 필드와 함께 /user/passkeys로 POST 요청을 보냅니다.
요청이 성공하면 Fortify는 다음 중 하나를 반환합니다.
- 일반 요청의 경우: 세션에
passkey-registered상태가 담긴 이전 페이지로의 리디렉션 응답 - XHR 요청의 경우:
status키와 새로 등록된 패스키의id,name이 담긴 JSON 페이로드를 포함한200HTTP 응답
패스키 삭제
패스키를 삭제하려면 애플리케이션에서 /user/passkeys/{passkey}로 DELETE 요청을 보냅니다.
요청이 성공하면 Fortify는 다음 중 하나를 반환합니다.
- 일반 요청의 경우: 세션에
passkey-deleted상태가 담긴 이전 페이지로의 리디렉션 응답 - XHR 요청의 경우:
status키가 담긴 JSON 페이로드를 포함한200HTTP 응답
회원가입
애플리케이션의 회원가입 기능을 구현하려면 먼저 Fortify가 "회원가입" 뷰를 어떻게 반환할지 알려 주어야 합니다. Fortify는 화면이 없는(headless) 인증 라이브러리라는 점을 기억하세요. Laravel의 인증 기능이 프론트엔드까지 이미 구현된 형태를 원한다면 애플리케이션 스타터 키트를 사용하면 됩니다.
Fortify의 모든 뷰 렌더링 로직은 Laravel\Fortify\Fortify 클래스가 제공하는 적절한 메서드로 커스터마이징할 수 있습니다. 보통 이 메서드는 App\Providers\FortifyServiceProvider 클래스의 boot 메서드에서 호출합니다.
use Laravel\Fortify\Fortify;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Fortify::registerView(function () {
return view('auth.register');
});
// ...
}Fortify가 이 뷰를 반환하는 /register 라우트를 정의해 줍니다. register 템플릿에는 Fortify가 정의한 /register 엔드포인트로 POST 요청을 보내는 폼이 있어야 합니다.
/register 엔드포인트는 문자열 name, 문자열 이메일 주소 / 사용자 이름, password, password_confirmation 필드를 요구합니다. 이메일 / 사용자 이름 필드의 이름은 애플리케이션의 fortify 설정 파일에 정의된 username 설정 값과 일치해야 합니다.
회원가입 시도가 성공하면 Fortify는 애플리케이션의 fortify 설정 파일에서 home 설정 옵션으로 지정한 URI로 사용자를 리디렉션합니다. 요청이 XHR 요청이었다면 201 HTTP 응답이 반환됩니다.
요청이 실패하면 사용자는 회원가입 화면으로 다시 리디렉션되며, 유효성 검증 오류는 공유 변수인 $errors Blade 템플릿 변수로 사용할 수 있습니다. XHR 요청의 경우에는 유효성 검증 오류가 422 HTTP 응답과 함께 반환됩니다.
회원가입 커스터마이징
사용자 유효성 검증과 생성 과정은 Laravel Fortify를 설치할 때 생성된 App\Actions\Fortify\CreateNewUser 액션을 수정해 커스터마이징할 수 있습니다.
비밀번호 재설정
비밀번호 재설정 링크 요청
애플리케이션의 비밀번호 재설정 기능을 구현하려면 먼저 Fortify가 "비밀번호 찾기" 뷰를 어떻게 반환할지 알려 주어야 합니다. Fortify는 화면이 없는(headless) 인증 라이브러리라는 점을 기억하세요. Laravel의 인증 기능이 프론트엔드까지 이미 구현된 형태를 원한다면 애플리케이션 스타터 키트를 사용하면 됩니다.
Fortify의 모든 뷰 렌더링 로직은 Laravel\Fortify\Fortify 클래스가 제공하는 적절한 메서드로 커스터마이징할 수 있습니다. 보통 이 메서드는 애플리케이션의 App\Providers\FortifyServiceProvider 클래스의 boot 메서드에서 호출합니다.
use Laravel\Fortify\Fortify;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Fortify::requestPasswordResetLinkView(function () {
return view('auth.forgot-password');
});
// ...
}Fortify가 이 뷰를 반환하는 /forgot-password 엔드포인트를 정의해 줍니다. forgot-password 템플릿에는 /forgot-password 엔드포인트로 POST 요청을 보내는 폼이 있어야 합니다.
/forgot-password 엔드포인트는 문자열 email 필드를 요구합니다. 이 필드 / 데이터베이스 컬럼의 이름은 애플리케이션의 fortify 설정 파일에 있는 email 설정 값과 일치해야 합니다.
비밀번호 재설정 링크 요청 응답 처리
비밀번호 재설정 링크 요청이 성공하면 Fortify는 사용자를 /forgot-password 엔드포인트로 다시 리디렉션하고, 비밀번호를 재설정할 수 있는 보안 링크가 담긴 이메일을 사용자에게 보냅니다. 요청이 XHR 요청이었다면 200 HTTP 응답이 반환됩니다.
요청이 성공해 /forgot-password 엔드포인트로 다시 리디렉션된 뒤에는 status 세션 변수를 이용해 비밀번호 재설정 링크 요청의 처리 상태를 표시할 수 있습니다.
$status 세션 변수의 값은 애플리케이션의 passwords 언어 파일에 정의된 번역 문자열 중 하나와 일치합니다. 이 값을 커스터마이징하고 싶은데 Laravel의 언어 파일을 아직 게시하지 않았다면 lang:publish Artisan 명령어로 게시한 뒤 수정하면 됩니다.
@if (session('status'))
<div class="mb-4 font-medium text-sm text-green-600">
{{ session('status') }}
</div>
@endif요청이 실패하면 사용자는 비밀번호 재설정 링크 요청 화면으로 다시 리디렉션되며, 유효성 검증 오류는 공유 변수인 $errors Blade 템플릿 변수로 사용할 수 있습니다. XHR 요청의 경우에는 유효성 검증 오류가 422 HTTP 응답과 함께 반환됩니다.
비밀번호 재설정하기
애플리케이션의 비밀번호 재설정 기능을 마무리하려면 Fortify가 "비밀번호 재설정" 뷰를 어떻게 반환할지 알려 주어야 합니다.
Fortify의 모든 뷰 렌더링 로직은 Laravel\Fortify\Fortify 클래스가 제공하는 적절한 메서드로 커스터마이징할 수 있습니다. 보통 이 메서드는 애플리케이션의 App\Providers\FortifyServiceProvider 클래스의 boot 메서드에서 호출합니다.
use Laravel\Fortify\Fortify;
use Illuminate\Http\Request;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Fortify::resetPasswordView(function (Request $request) {
return view('auth.reset-password', ['request' => $request]);
});
// ...
}Fortify가 이 뷰를 표시하는 라우트를 정의해 줍니다. reset-password 템플릿에는 /reset-password로 POST 요청을 보내는 폼이 있어야 합니다.
/reset-password 엔드포인트는 문자열 email 필드, password 필드, password_confirmation 필드, 그리고 request()->route('token')의 값을 담은 token이라는 이름의 hidden 필드를 요구합니다. "email" 필드 / 데이터베이스 컬럼의 이름은 애플리케이션의 fortify 설정 파일에 정의된 email 설정 값과 일치해야 합니다.
비밀번호 재설정 응답 처리
비밀번호 재설정 요청이 성공하면 Fortify는 /login 라우트로 다시 리디렉션하여 사용자가 새 비밀번호로 로그인할 수 있게 합니다. 또한 status 세션 변수가 설정되므로, 로그인 화면에서 재설정이 성공했음을 표시할 수 있습니다.
@if (session('status'))
<div class="mb-4 font-medium text-sm text-green-600">
{{ session('status') }}
</div>
@endif요청이 XHR 요청이었다면 200 HTTP 응답이 반환됩니다.
요청이 실패하면 사용자는 비밀번호 재설정 화면으로 다시 리디렉션되며, 유효성 검증 오류는 공유 변수인 $errors Blade 템플릿 변수로 사용할 수 있습니다. XHR 요청의 경우에는 유효성 검증 오류가 422 HTTP 응답과 함께 반환됩니다.
비밀번호 재설정 커스터마이징
비밀번호 재설정 과정은 Laravel Fortify를 설치할 때 생성된 App\Actions\Fortify\ResetUserPassword 액션을 수정해 커스터마이징할 수 있습니다.
이메일 인증
회원가입 후 사용자가 이메일 주소를 인증해야만 애플리케이션을 계속 이용할 수 있게 하고 싶을 수 있습니다. 먼저 fortify 설정 파일의 features 배열에서 emailVerification 기능이 활성화되어 있는지 확인합니다. 그다음 App\Models\User 클래스가 Illuminate\Contracts\Auth\MustVerifyEmail 인터페이스를 구현하는지 확인해야 합니다.
이 두 가지 준비를 마치면 새로 가입한 사용자는 이메일 주소의 소유를 인증하라는 안내 이메일을 받게 됩니다. 다만 사용자에게 이메일의 인증 링크를 클릭해야 한다고 알려 주는 이메일 인증 화면을 어떻게 표시할지는 Fortify에 알려 주어야 합니다.
Fortify의 모든 뷰 렌더링 로직은 Laravel\Fortify\Fortify 클래스가 제공하는 적절한 메서드로 커스터마이징할 수 있습니다. 보통 이 메서드는 애플리케이션의 App\Providers\FortifyServiceProvider 클래스의 boot 메서드에서 호출합니다.
use Laravel\Fortify\Fortify;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Fortify::verifyEmailView(function () {
return view('auth.verify-email');
});
// ...
}Laravel에 내장된 verified 미들웨어가 사용자를 /email/verify 엔드포인트로 리디렉션하면, Fortify가 이 뷰를 표시하는 라우트를 정의해 줍니다.
verify-email 템플릿에는 이메일로 발송된 인증 링크를 클릭하라고 안내하는 메시지가 포함되어야 합니다.
이메일 인증 링크 재전송
원한다면 애플리케이션의 verify-email 템플릿에 /email/verification-notification 엔드포인트로 POST 요청을 보내는 버튼을 추가할 수 있습니다. 이 엔드포인트가 요청을 받으면 새 인증 링크가 담긴 이메일이 사용자에게 발송되므로, 이전 링크를 실수로 지웠거나 잃어버린 사용자도 새 인증 링크를 받을 수 있습니다.
인증 링크 이메일 재전송 요청이 성공하면 Fortify는 status 세션 변수와 함께 사용자를 /email/verify 엔드포인트로 다시 리디렉션하므로, 작업이 성공했음을 알리는 안내 메시지를 사용자에게 표시할 수 있습니다. 요청이 XHR 요청이었다면 202 HTTP 응답이 반환됩니다.
@if (session('status') == 'verification-link-sent')
<div class="mb-4 font-medium text-sm text-green-600">
새 이메일 인증 링크를 메일로 보내 드렸습니다!
</div>
@endif라우트 보호하기
특정 라우트 또는 라우트 그룹에 접근하려면 사용자가 이메일 주소를 인증해야 한다고 지정하려면, 해당 라우트에 Laravel에 내장된 verified 미들웨어를 연결합니다. verified 미들웨어 별칭은 Laravel이 자동으로 등록하며, Illuminate\Auth\Middleware\EnsureEmailIsVerified 미들웨어의 별칭입니다.
Route::get('/dashboard', function () {
// ...
})->middleware(['verified']);비밀번호 확인
애플리케이션을 만들다 보면 특정 작업을 수행하기 전에 사용자가 비밀번호를 다시 확인해야 하는 경우가 있습니다. 보통 이런 라우트는 Laravel에 내장된 password.confirm 미들웨어로 보호합니다.
비밀번호 확인 기능을 구현하려면 먼저 Fortify가 애플리케이션의 "비밀번호 확인" 뷰를 어떻게 반환할지 알려 주어야 합니다. Fortify는 화면이 없는(headless) 인증 라이브러리라는 점을 기억하세요. Laravel의 인증 기능이 프론트엔드까지 이미 구현된 형태를 원한다면 애플리케이션 스타터 키트를 사용하면 됩니다.
Fortify의 모든 뷰 렌더링 로직은 Laravel\Fortify\Fortify 클래스가 제공하는 적절한 메서드로 커스터마이징할 수 있습니다. 보통 이 메서드는 애플리케이션의 App\Providers\FortifyServiceProvider 클래스의 boot 메서드에서 호출합니다.
use Laravel\Fortify\Fortify;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Fortify::confirmPasswordView(function () {
return view('auth.confirm-password');
});
// ...
}Fortify가 이 뷰를 반환하는 /user/confirm-password 엔드포인트를 정의해 줍니다. confirm-password 템플릿에는 /user/confirm-password 엔드포인트로 POST 요청을 보내는 폼이 있어야 합니다. /user/confirm-password 엔드포인트는 사용자의 현재 비밀번호가 담긴 password 필드를 요구합니다.
입력한 비밀번호가 사용자의 현재 비밀번호와 일치하면 Fortify는 사용자가 접근하려던 라우트로 리디렉션합니다. 요청이 XHR 요청이었다면 201 HTTP 응답이 반환됩니다.
요청이 실패하면 사용자는 비밀번호 확인 화면으로 다시 리디렉션되며, 유효성 검증 오류는 공유 변수인 $errors Blade 템플릿 변수로 사용할 수 있습니다. XHR 요청의 경우에는 유효성 검증 오류가 422 HTTP 응답과 함께 반환됩니다.