Laravel Sanctumとは?最新の認証システムを詳しく解説
Laravel Sanctumは、SPAやモバイルアプリケーション、APIトークンベースの認証を簡単に実装できるLaravelの公式パッケージです。シンプルで軽量な認証システムでありながら、モダンなWeb開発に必要な機能を完備しています。
モダンなAPI認証の課題を解決するSanctumの特徴
現代のWeb開発では、以下のような認証に関する課題が存在します:
- 複数プラットフォームへの対応
- Webアプリケーション(SPA)
- モバイルアプリケーション
- サードパーティAPIクライアント
- セキュリティ要件の複雑化
- クロスサイトリクエストフォージェリ(CSRF)対策
- クロスオリジンリソース共有(CORS)の適切な設定
- トークンの安全な管理
Sanctumは、これらの課題に対して以下の特徴で解決を提供します:
- 2つの認証システムの統合
- トークンベースのAPI認証
- SPAのためのクッキーベースセッション認証
- シンプルな実装
// トークン発行の例
$token = $user->createToken('token-name');
// API認証の例
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
- 柔軟なトークン管理
- 複数デバイスでの同時ログイン対応
- トークンへの権限付与機能
- トークンの有効期限設定
従来のパスポートとの決定的な違いと選択基準
Laravel Passportと比較した際の主な違いは以下の通りです:
| 機能 | Sanctum | Passport |
|---|---|---|
| アーキテクチャ | 軽量・シンプル | OAuth2完全準拠 |
| セットアップ | 最小限の設定 | 比較的複雑 |
| 用途 | SPAとAPIの統合認証 | 本格的なOAuth2サーバー |
| パフォーマンス | 高速 | やや重い |
| データベース | 最小限のテーブル | 複数テーブルが必要 |
選択基準のポイント:
- Sanctumを選ぶべき場合:
- シンプルなAPI認証が必要
- SPAとAPIの統合認証を実装したい
- パフォーマンスを重視する
- 開発速度を優先する
- Passportを選ぶべき場合:
- OAuth2の完全な機能が必要
- サードパーティアプリケーションへの認証提供
- 既存のOAuth2システムとの統合
まとめると、Laravel Sanctumは、モダンなWeb開発における認証の課題を、シンプルさと高機能性のバランスを取りながら解決する優れたソリューションです。特にSPAやモバイルアプリケーションとの連携を前提とした開発では、その真価を発揮します。
Laravel Sanctumのセットアップ方法を徹底解説
Laravel Sanctumの導入は、適切な手順で行うことで、安全で確実なセットアップが可能です。ここでは、環境要件の確認から初期設定まで、段階的に解説します。
必要な環境要件と依存関係の確認
Sanctumを導入する前に、以下の要件を満たしているか確認しましょう:
- 必須要件
- PHP 7.3以上
- Laravel 8.0以上
- データベース(MySQL 5.7+, PostgreSQL 9.6+等)
- 推奨環境設定
// php.ini の推奨設定 session.cookie_httponly = 1 session.cookie_secure = 1 session.cookie_samesite = "Lax"
- フロントエンド要件(SPA利用時)
- CORSの設定が可能なサーバー環境
- セッションクッキーを処理できるクライアント
Composer での Sanctum インストールと初期設定
- パッケージのインストール
composer require laravel/sanctum
- Sanctumの設定ファイルとマイグレーションファイルの公開
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
- 必要なミドルウェアの登録
// app/Http/Kernel.php
protected $middlewareGroups = [
'web' => [
// ...
],
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
マイグレーションの実行と設定ファイルのカスタマイズ
- データベースマイグレーションの実行
php artisan migrate
これにより、以下のテーブルが作成されます:
personal_access_tokens: APIトークンの管理用テーブル
- 設定ファイルのカスタマイズ
// config/sanctum.php
return [
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
'guard' => ['web'],
'expiration' => null, // トークンの有効期限(分)
'middleware' => [
'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
],
];
- セキュリティ設定の調整
// config/cors.php
return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true, // 重要: SPAで必須
];
セットアップ完了後の動作確認:
// routes/api.php
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
// テスト用コマンド
php artisan test
これでLaravel Sanctumの基本的なセットアップは完了です。エラーが発生した場合は、以下の点を確認してください:
- データベース接続設定の確認
- マイグレーションの実行状態
- 環境変数(.env)の設定
- CORSの設定(SPA利用時)
- ミドルウェアの登録状態
セットアップが完了したら、次のステップとしてユーザー認証の実装に進むことができます。
実践的なAPI認証の実装手順
Laravel Sanctumを使用したAPI認証の実装について、実践的な手順とベストプラクティスを解説します。
権限ベース認証の基本実装方法
- Userモデルの準備
// app/Models/User.php
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
// トークンに付与できる権限の定義
public static $tokenAbilities = [
'read',
'write',
'delete'
];
}
- トークン発行処理の実装
// app/Http/Controllers/Auth/TokenController.php
class TokenController extends Controller
{
public function createToken(Request $request)
{
$request->validate([
'token_name' => 'required|string',
'abilities' => 'array|in:' . implode(',', User::$tokenAbilities)
]);
$token = $request->user()->createToken(
$request->token_name,
$request->abilities ?? ['*']
);
return response()->json([
'token' => $token->plainTextToken,
'expires_at' => now()->addDays(config('sanctum.expiration_days'))
]);
}
public function revokeToken(Request $request)
{
// 現在のトークンを無効化
$request->user()->currentAccessToken()->delete();
return response()->json(['message' => 'Token revoked successfully']);
}
}
ユーザー登録・ログインAPIのエンドポイント作成
- ユーザー登録API
// app/Http/Controllers/Auth/RegisterController.php
class RegisterController extends Controller
{
public function register(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8|confirmed'
]);
$user = User::create([
'name' => $validated['name'],
'email' => $validated['email'],
'password' => Hash::make($validated['password'])
]);
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json([
'user' => $user,
'access_token' => $token,
'token_type' => 'Bearer'
], 201);
}
}
- ログインAPI
// app/Http/Controllers/Auth/LoginController.php
class LoginController extends Controller
{
public function login(Request $request)
{
$credentials = $request->validate([
'email' => 'required|email',
'password' => 'required'
]);
if (!Auth::attempt($credentials)) {
return response()->json([
'message' => 'Invalid login credentials'
], 401);
}
$user = $request->user();
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json([
'user' => $user,
'access_token' => $token,
'token_type' => 'Bearer'
]);
}
}
セキュアなセキュリティ管理とベストプラクティス
- トークン有効期限の管理
// config/sanctum.php
return [
'expiration' => 60 * 24, // 24時間
'token_prefix' => env('SANCTUM_TOKEN_PREFIX', 'sanctum_'),
];
// app/Providers/AuthServiceProvider.php
public function boot()
{
Sanctum::authenticateAccessTokensUsing(function ($token, $isValid) {
if ($isValid && $token->created_at->lte(now()->subDays(7))) {
return false;
}
return $isValid;
});
}
- セキュリティヘッダーの設定
// app/Http/Middleware/SecurityHeaders.php
class SecurityHeaders
{
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('X-Content-Type-Options', 'nosniff');
$response->headers->set('X-Frame-Options', 'DENY');
$response->headers->set('X-XSS-Protection', '1; mode=block');
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
return $response;
}
}
- レート制限の実装
// routes/api.php
Route::middleware(['auth:sanctum', 'throttle:60,1'])->group(function () {
Route::post('/actions/sensitive', 'ActionController@sensitive');
});
セキュリティのベストプラクティス:
- トークン管理
- 適切な有効期限の設定
- 未使用トークンの定期的なクリーンアップ
- トークンの権限スコープの最小化
- エラーハンドリング
// app/Exceptions/Handler.php
public function render($request, Throwable $exception)
{
if ($exception instanceof AuthenticationException) {
return response()->json([
'error' => 'Unauthenticated',
'message' => 'Please login to access this resource'
], 401);
}
return parent::render($request, $exception);
}
- セキュリティチェックリスト
- SSL/TLS通信の強制
- セキュリティヘッダーの設定
- レート制限の実装
- 適切なバリデーションの実装
- エラーメッセージの適切な制御
この実装により、セキュアで保守性の高いAPI認証システムを構築することができます。
SPAとモバイルアプリの認証対応
Laravel Sanctumは、SPAとモバイルアプリの両方に対して、シームレスな認証体験を提供します。ここでは、それぞれのプラットフォームに対する具体的な実装方法を解説します。
CORSの設定とCSRF保護の実装
- CORSの基本設定
// config/cors.php
return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => [
'http://localhost:3000',
'http://localhost:8080',
'https://your-frontend-domain.com'
],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true, // 重要: 必ずtrueに設定
];
- CSRF保護の設定
// app/Http/Middleware/VerifyCsrfToken.php
protected $except = [
'sanctum/csrf-cookie',
'api/mobile/*' // モバイルAPIのエンドポイント
];
- セッション設定の調整
// config/session.php
return [
'domain' => env('SESSION_DOMAIN', null),
'secure' => env('SESSION_SECURE_COOKIE', true),
'same_site' => 'lax',
];
VueとReactとの連携方法
- Vueでの実装例
// Vue 3での実装
import axios from 'axios'
axios.defaults.withCredentials = true
const login = async (email, password) => {
// CSRF保護の初期化
await axios.get('/sanctum/csrf-cookie')
try {
const response = await axios.post('/api/login', {
email,
password
})
// ログイン成功時の処理
localStorage.setItem('user', JSON.stringify(response.data.user))
return response.data
} catch (error) {
console.error('Login failed:', error)
throw error
}
}
// API呼び出しの例
const fetchUserData = async () => {
try {
const response = await axios.get('/api/user')
return response.data
} catch (error) {
if (error.response.status === 401) {
// 未認証時の処理
router.push('/login')
}
}
}
- Reactでの実装例
// React実装例
import axios from 'axios'
const api = axios.create({
baseURL: process.env.REACT_APP_API_URL,
withCredentials: true,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null)
const [loading, setLoading] = useState(true)
const login = async (email, password) => {
await axios.get('/sanctum/csrf-cookie')
const response = await api.post('/login', {
email,
password
})
setUser(response.data.user)
return response.data
}
const logout = async () => {
await api.post('/logout')
setUser(null)
}
// 認証状態の確認
useEffect(() => {
const checkAuth = async () => {
try {
const response = await api.get('/api/user')
setUser(response.data)
} catch (error) {
setUser(null)
} finally {
setLoading(false)
}
}
checkAuth()
}, [])
return (
<AuthContext.Provider value={{ user, login, logout, loading }}>
{children}
</AuthContext.Provider>
)
}
モバイルアプリでの認証の実装例
- iOS Swift実装例
class APIClient {
static let baseURL = "https://api.your-domain.com"
static var token: String?
static func login(email: String, password: String) async throws -> User {
let url = URL(string: "\(baseURL)/api/login")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let body = ["email": email, "password": password]
request.httpBody = try JSONSerialization.data(withJSONObject: body)
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw APIError.invalidResponse
}
let loginResponse = try JSONDecoder().decode(LoginResponse.self, from: data)
token = loginResponse.token
return loginResponse.user
}
static func authenticatedRequest<T: Decodable>(_ endpoint: String) async throws -> T {
guard let token = token else { throw APIError.unauthorized }
let url = URL(string: "\(baseURL)/api/\(endpoint)")!
var request = URLRequest(url: url)
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
return try JSONDecoder().decode(T.self, from: data)
}
}
- Android Kotlin実装例
class ApiService {
private val retrofit = Retrofit.Builder()
.baseUrl("https://api.your-domain.com")
.addConverterFactory(GsonConverterFactory.create())
.client(createOkHttpClient())
.build()
private fun createOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor { chain ->
val original = chain.request()
val request = original.newBuilder()
.header("Accept", "application/json")
.method(original.method, original.body)
.apply {
UserPreferences.token?.let {
header("Authorization", "Bearer $it")
}
}
.build()
chain.proceed(request)
}
.build()
}
suspend fun login(email: String, password: String): LoginResponse {
return retrofit.create(ApiInterface::class.java)
.login(LoginRequest(email, password))
.also {
UserPreferences.token = it.token
}
}
}
これらの実装により、SPAやモバイルアプリからのセキュアな認証が可能になります。実装時の注意点として:
- セキュリティ考慮事項
- トークンの安全な保存
- HTTPS通信の強制
- トークンの有効期限管理
- リフレッシュトークンの実装
- エラーハンドリング
- ネットワークエラー
- 認証エラー
- トークン期限切れ
- ユーザー体験の最適化
- オフライン対応
- 自動ログイン
- セッション維持
実際の運用に向けた重要な設定と注意点
本番環境でLaravel Sanctumを運用する際の重要な設定と、実際の運用で発生しやすい問題への対処方法を解説します。
本番環境でのセキュリティ設定
- 環境変数の適切な設定
# .env SESSION_SECURE_COOKIE=true SESSION_DOMAIN=.your-domain.com SANCTUM_STATEFUL_DOMAINS=your-frontend-domain.com SESSION_LIFETIME=120 SANCTUM_EXPIRATION=60
- セキュリティヘッダーの設定
// app/Http/Middleware/SecurityHeadersMiddleware.php
class SecurityHeadersMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('X-Frame-Options', 'DENY');
$response->headers->set('X-Content-Type-Options', 'nosniff');
$response->headers->set('X-XSS-Protection', '1; mode=block');
$response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
$response->headers->set('Content-Security-Policy', "default-src 'self'");
if (app()->environment('production')) {
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
}
return $response;
}
}
- 適切なログ設定
// config/logging.php
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily', 'slack'],
'ignore_exceptions' => false,
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'days' => 14,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Laravel Log',
'emoji' => ':boom:',
'level' => env('LOG_LEVEL', 'critical'),
],
]
パフォーマンス最適化のためのキャッシュ戦略
- トークンキャッシュの実装
// app/Providers/AuthServiceProvider.php
use Illuminate\Support\Facades\Cache;
public function boot()
{
Sanctum::authenticateAccessTokensUsing(function ($token, $isValid) {
$cacheKey = 'sanctum_token_' . $token->id;
return Cache::remember($cacheKey, now()->addMinutes(5), function () use ($token, $isValid) {
return $isValid && !$token->expired();
});
});
}
- 不要トークンの定期クリーンアップ
// app/Console/Commands/CleanupTokens.php
class CleanupTokens extends Command
{
protected $signature = 'sanctum:cleanup';
public function handle()
{
// 期限切れトークンの削除
$expiredTokens = PersonalAccessToken::where('created_at', '<', now()->subDays(30))
->orWhere('last_used_at', '<', now()->subDays(7))
->delete();
// 使用されていないトークンの削除
$unusedTokens = PersonalAccessToken::whereNull('last_used_at')
->where('created_at', '<', now()->subDays(1))
->delete();
$this->info('Cleaned up expired and unused tokens.');
}
}
- レート制限の最適化
// routes/api.php
Route::middleware(['auth:sanctum', 'throttle:api'])->group(function () {
// 通常のAPI制限
Route::get('/user', function () {
return auth()->user();
})->middleware('throttle:60,1');
// 重要な操作の制限
Route::post('/sensitive-operation', [Controller::class, 'handle'])
->middleware('throttle:3,1');
});
トラブルシューティングと一般的な問題の解決方法
- 認証エラーの診断と対処
// app/Exceptions/Handler.php
public function render($request, Throwable $exception)
{
if ($exception instanceof AuthenticationException) {
Log::debug('Authentication failed', [
'ip' => $request->ip(),
'user_agent' => $request->userAgent(),
'headers' => $request->headers->all()
]);
return response()->json([
'error' => 'Unauthenticated',
'debug_info' => app()->environment('local') ? [
'cookies_present' => $request->cookies->all() ? 'yes' : 'no',
'token_present' => $request->bearerToken() ? 'yes' : 'no',
] : null
], 401);
}
return parent::render($request, $exception);
}
- よくある問題と解決方法 問題 原因 解決方法 CORS エラー ドメイン設定の不一致
config/cors.phpのallowed_originsを確認 トークン認証失敗 セッション設定の問題SESSION_DOMAINとSANCTUM_STATEFUL_DOMAINSを確認 パフォーマンス低下 トークン数の増大 定期的なクリーンアップジョブを実行 - デバッグ用のヘルパー関数
// app/Helpers/AuthDebugger.php
class AuthDebugger
{
public static function diagnose(Request $request)
{
$issues = [];
if (!$request->secure() && app()->environment('production')) {
$issues[] = 'HTTPS is not enabled';
}
if (!$request->cookies->has(config('session.cookie'))) {
$issues[] = 'Session cookie is missing';
}
if (!in_array($request->getHost(), config('sanctum.stateful'))) {
$issues[] = 'Domain is not in stateful domains list';
}
return $issues;
}
}
運用時の重要なチェックポイント:
- 定期的な監視項目
- アクティブトークン数
- 認証失敗率
- レート制限ヒット数
- セッションストアのサイズ
- セキュリティ監査項目
- 不正アクセスの検知
- トークンの使用パターン
- 異常なリクエストパターン
- パフォーマンス監視
- レスポンスタイム
- データベース負荷
- キャッシュヒット率
これらの設定と対策により、本番環境での安定した運用が可能になります。
Laravel Sanctumを使った認証システムの発展的な使い方
Sanctumの基本機能を拡張し、より高度な認証システムを構築するための実装方法を解説します。
マルチデバイス対応の実装方法
- デバイス情報の管理
// database/migrations/create_user_devices_table.php
public function up()
{
Schema::create('user_devices', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->string('device_name');
$table->string('device_type');
$table->string('push_token')->nullable();
$table->timestamp('last_active_at');
$table->timestamps();
});
}
// app/Models/UserDevice.php
class UserDevice extends Model
{
protected $fillable = [
'device_name',
'device_type',
'push_token',
'last_active_at'
];
protected $casts = [
'last_active_at' => 'datetime'
];
}
- デバイス認証の拡張
// app/Http/Controllers/Auth/DeviceController.php
class DeviceController extends Controller
{
public function register(Request $request)
{
$validated = $request->validate([
'device_name' => 'required|string',
'device_type' => 'required|in:ios,android,web',
'push_token' => 'nullable|string'
]);
$device = auth()->user()->devices()->create([
'device_name' => $validated['device_name'],
'device_type' => $validated['device_type'],
'push_token' => $validated['push_token'],
'last_active_at' => now()
]);
$token = auth()->user()->createToken(
$device->device_name,
['*'],
now()->addYear()
);
return response()->json([
'token' => $token->plainTextToken,
'device' => $device
]);
}
public function listDevices()
{
return auth()->user()->devices()
->orderBy('last_active_at', 'desc')
->get();
}
public function revokeDevice($deviceId)
{
$device = auth()->user()->devices()->findOrFail($deviceId);
$device->delete();
// 関連するトークンの削除
auth()->user()->tokens()
->where('name', $device->device_name)
->delete();
return response()->json(['message' => 'Device removed successfully']);
}
}
トークンの有効期限と自動更新の実装
- トークン管理の拡張
// app/Models/Concerns/HasAdvancedTokens.php
trait HasAdvancedTokens
{
public function createTokenWithRefresh($name, array $abilities = ['*'])
{
$token = $this->createToken($name, $abilities, now()->addHours(2));
$refreshToken = Str::random(64);
Cache::put(
"refresh_token_{$refreshToken}",
$token->accessToken->id,
now()->addDays(30)
);
return [
'access_token' => $token->plainTextToken,
'refresh_token' => $refreshToken,
'expires_in' => 7200
];
}
public function refreshToken($refreshToken)
{
$tokenId = Cache::get("refresh_token_{$refreshToken}");
if (!$tokenId) {
throw new AuthenticationException('Invalid refresh token');
}
$oldToken = $this->tokens()->find($tokenId);
if (!$oldToken) {
Cache::forget("refresh_token_{$refreshToken}");
throw new AuthenticationException('Token not found');
}
// 新しいトークンの発行
$newToken = $this->createTokenWithRefresh(
$oldToken->name,
$oldToken->abilities
);
// 古いトークンの削除
$oldToken->delete();
Cache::forget("refresh_token_{$refreshToken}");
return $newToken;
}
}
- 自動更新の実装
// app/Http/Middleware/CheckTokenExpiration.php
class CheckTokenExpiration
{
public function handle($request, Closure $next)
{
if (!$request->user() || !$request->user()->currentAccessToken()) {
return $next($request);
}
$token = $request->user()->currentAccessToken();
// トークンの有効期限が近い場合は自動更新
if ($token->created_at->addHours(1)->isPast()) {
$newToken = $request->user()->createToken(
$token->name,
$token->abilities,
now()->addHours(2)
);
$response = $next($request);
return $response->header('New-Token', $newToken->plainTextToken);
}
return $next($request);
}
}
カスタムガードとポリシーの活用方法
- カスタムガードの実装
// app/Auth/Guards/SanctumDeviceGuard.php
class SanctumDeviceGuard extends TokenGuard
{
protected function validateToken($token)
{
if (!parent::validateToken($token)) {
return false;
}
$device = UserDevice::where('device_name', $token->name)
->where('user_id', $token->tokenable_id)
->first();
if (!$device) {
return false;
}
$device->update(['last_active_at' => now()]);
return true;
}
}
// config/auth.php
'guards' => [
'sanctum-device' => [
'driver' => 'sanctum-device',
'provider' => 'users',
],
]
- 高度なポリシーの実装
// app/Policies/DevicePolicy.php
class DevicePolicy
{
public function manageSensitiveData(User $user, UserDevice $device)
{
// デバイスが信頼できる場合のみ許可
return $device->last_active_at->diffInDays() < 30 &&
$device->user_id === $user->id;
}
public function revokeOtherDevices(User $user, UserDevice $device)
{
// プライマリデバイスのみに許可
return $device->is_primary && $device->user_id === $user->id;
}
}
- アクセス制御の実装例
// routes/api.php
Route::middleware(['auth:sanctum-device'])->group(function () {
Route::post('/sensitive-data', function (Request $request) {
$device = UserDevice::where('device_name', $request->user()
->currentAccessToken()->name)
->firstOrFail();
if ($request->user()->cannot('manageSensitiveData', $device)) {
return response()->json([
'message' => 'This device is not authorized for this operation'
], 403);
}
// 処理の実行
});
});
この発展的な実装により、以下のような高度な機能が実現できます:
- セキュリティ強化
- デバイスごとの詳細な権限管理
- 不審なアクセスの検知と防止
- トークンの適切なライフサイクル管理
- ユーザー体験の向上
- シームレスなトークン更新
- デバイス管理機能の提供
- きめ細かいアクセス制御
- 運用管理の効率化
- デバイスアクティビティの監視
- 異常検知の自動化
- トークンライフサイクルの自動管理