NoraBear Package API Documentation

認証・認可

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
}

ベストプラクティス

  1. 複数の認証方式をサポート

    JWTとセッション認証の両方を設定することで、APIとWebアプリケーションの両方に対応できます。

  2. AuthContextは readonly クラスに

    不変性を保つため、AuthContextはreadonly classとして定義することを推奨します。

  3. 最小権限の原則

    必要最小限のロールやパーミッションのみを要求しましょう。

  4. ログ出力の活用

    AuthInterceptorはログ出力をサポートしています。LoggerInterfaceをバインドして認証イベントを記録しましょう。

  5. テストでの認証スキップ

    テスト環境では、DummyValidatorを使用して認証をスキップできます。

関連項目

  • はじめに - 基本的な使い方
  • NoraLib Auth - 認証・認可ライブラリ
  • NoraLib Utils - ユーティリティライブラリ

Search results