認証・認可
NoraBear PackageのAuthModuleは、OpenAPIセキュリティ定義に基づく認証・認可機能を提供します。
概要
AuthModuleの主な機能:
- OpenAPIの
securitySchemes定義を読み取り、自動的に認証要否を判定 - JWT、Session Cookie、Aura.Sessionなどの認証方式をサポート
@Authenticatedアノテーションで認証を強制@Authorizeアノテーションでロール/パーミッションベースの認可- ユーザー定義のAuthContextクラスによる柔軟な認証情報管理
基本的な使い方
AuthContextの定義
まず、認証コンテキストクラスを定義します:
<?php
readonly class MyAuthContext
{
public function __construct(
public string $userId,
public string $scheme,
public array $roles = [],
public array $permissions = []
) {}
public function getRoles(): array
{
return $this->roles;
}
public function getPermissions(): array
{
return $this->permissions;
}
}
AuthModuleの設定
次に、AuthModuleをインストールします:
<?php
use Ray\Di\AbstractModule;
use NoraLib\Auth\Validator\JWTValidator;
use NoraLib\Auth\Validator\AuraSessionValidator;
use NoraBear\Package\Auth\Module\AuthModule;
class AppModule extends AbstractModule
{
protected function configure(): void
{
// 認証バリデーターを設定
$validators = [
new JWTValidator(
secretKey: $this->appMeta->appDir . '/var/conf/jwt_secret.key',
algorithm: 'HS256'
),
new AuraSessionValidator(
sessionSegment: 'auth'
),
];
// AuthModuleをインストール
$this->install(new AuthModule(
authContextClass: MyAuthContext::class,
validators: $validators
));
}
}
リソースへの適用
@Authenticated
アノテーションで認証を要求します:
<?php
use BEAR\Resource\ResourceObject;
use NoraLib\Auth\Annotation\Authenticated;
use NoraBear\Package\Annotation\JsonRest;
class Users extends ResourceObject
{
#[JsonRest]
#[Authenticated]
public function onGet(): static
{
// 認証済みユーザーのみアクセス可能
$this->body = ['users' => $this->userRepository->findAll()];
return $this;
}
}
認可(Authorization)
ロールベース認可
@Authorize
アノテーションでロールを要求します:
<?php
use NoraLib\Auth\Annotation\Authenticated;
use NoraLib\Auth\Annotation\Authorize;
class Users extends ResourceObject
{
#[JsonRest]
#[Authenticated]
#[Authorize(roles: ['admin'])]
public function onDelete(string $id): static
{
// 管理者のみ削除可能
$this->userRepository->delete($id);
$this->code = 204;
return $this;
}
}
パーミッションベース認可
<?php
#[Authenticated]
#[Authorize(permissions: ['user:write', 'user:delete'])]
public function onDelete(string $id): static
{
// user:writeとuser:deleteの両方が必要
$this->userRepository->delete($id);
$this->code = 204;
return $this;
}
認可モード
mode
パラメータで認可条件を指定できます:
<?php
// いずれか1つのロールがあればOK(デフォルト)
#[Authorize(roles: ['admin', 'moderator'], mode: 'any')]
// すべてのロールが必要
#[Authorize(roles: ['admin', 'verified'], mode: 'all')]
// パーミッションも同様
#[Authorize(permissions: ['user:read', 'user:write'], mode: 'all')]
OpenAPI統合
OpenAPIスキーマでセキュリティ要件を定義
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
sessionAuth:
type: apiKey
in: cookie
name: PHPSESSID
paths:
/users:
get:
security:
- bearerAuth: []
- sessionAuth: []
delete:
security:
- bearerAuth: [admin]
OpenAPIAuthBridgeの使用
OpenAPIスキーマから認証要件を読み取ります:
<?php
use NoraBear\Package\OpenAPI\Bridge\OpenAPIAuthBridge;
use cebe\openapi\Reader;
$schema = Reader::readFromYamlFile('openapi.yaml');
$bridge = new OpenAPIAuthBridge($schema);
// 認証が必要かチェック
if ($bridge->requiresAuthentication('/users', 'get')) {
// 認証処理
}
// 必要な認証スキームを取得
$schemes = $bridge->getRequiredSchemes('/users', 'get');
// ['bearerAuth', 'sessionAuth']
認証バリデーター
JWTValidator
JWT(JSON Web Token)認証を提供します:
<?php
use NoraLib\Auth\Validator\JWTValidator;
$validator = new JWTValidator(
secretKey: '/path/to/jwt_secret.key',
algorithm: 'HS256'
);
SessionValidator
PHPネイティブセッション認証を提供します:
<?php
use NoraLib\Auth\Validator\SessionValidator;
$validator = new SessionValidator();
AuraSessionValidator
Aura.Session認証を提供します:
<?php
use NoraLib\Auth\Validator\AuraSessionValidator;
$validator = new AuraSessionValidator(
sessionSegment: 'auth'
);
カスタムバリデーター
独自の認証ロジックを実装できます:
<?php
use NoraLib\Auth\AuthValidatorInterface;
use Psr\Http\Message\ServerRequestInterface;
class CustomValidator implements AuthValidatorInterface
{
public function getSchemeName(): string
{
return 'custom';
}
public function validate(ServerRequestInterface $request): array
{
// カスタム認証ロジック
$token = $request->getHeaderLine('X-Custom-Token');
if (!$this->isValidToken($token)) {
throw new AuthenticationException('Invalid token');
}
return [
'userId' => $this->extractUserId($token),
'scheme' => 'custom',
'roles' => $this->extractRoles($token),
'permissions' => $this->extractPermissions($token),
];
}
}
エラーハンドリング
認証失敗
認証が失敗すると AuthenticationException
がスローされます(HTTP 401)。
認可失敗
認可が失敗すると AuthorizationException
がスローされます(HTTP 403)。
JsonRestInterceptorとの統合
JsonRestInterceptorと組み合わせることで、統一されたエラーレスポンスを返せます:
{
"info": {
"status": "error",
"message": "Authentication required"
},
"payload": null
}
ベストプラクティス
-
複数の認証方式をサポート
JWTとセッション認証の両方を設定することで、APIとWebアプリケーションの両方に対応できます。
-
AuthContextは readonly クラスに
不変性を保つため、AuthContextはreadonly classとして定義することを推奨します。
-
最小権限の原則
必要最小限のロールやパーミッションのみを要求しましょう。
-
ログ出力の活用
AuthInterceptorはログ出力をサポートしています。LoggerInterfaceをバインドして認証イベントを記録しましょう。
-
テストでの認証スキップ
テスト環境では、DummyValidatorを使用して認証をスキップできます。
関連項目
- はじめに - 基本的な使い方
- NoraLib Auth - 認証・認可ライブラリ
- NoraLib Utils - ユーティリティライブラリ