ペチパーノート

WEB開発系Tipsブログです。

Laravel 定数を使うのは.envだけではダメ

.envにも書いて

API_URL=https://example.jp/list

config/xxx.phpにも書く(configでenvから取得する)

<?php

return [
    'api_url' => env('API_URL'),
];

使いたいところでconfig()で取得する

public function __construct()
{
    $this->api_url = config('api_url');
    $this->http_method = 'post';
    $this->client = new Client();
…
}

Laravel サービスコンテナとサービスプロバイダ

結構難しい。ぼんやりと。

サービスコンテナ

  • Laravelはモデル等のクラスをコントローラでnewしなくてよい
  • コントローラの引数に書いてやればよい (注入)
  • それを実現するのがサービスコンテナ。サービスとは”特定の機能を持ったクラス”のことである

  • サービスコンテナはクラスのインスタンスを作ってくれるマシーンである

  • このようにメソッドの引数にクラスを指定するだけでインスタンスが使えるようになる機能を「メソッドインジェクション」と呼ぶ。これはサービスコンテナの最も強力で多用する機能である
  • サービスコンテナにクラスをバインド(登録)する。という。
  • サービスコンテナからクラスをリゾルブ(解決)する。という。(インスタンスが取得できた状態)

サービスプロバイダ

  • 起動時にサービスコンテナへバインドをする仕組み
  • サービスプロバイダはconfig/app.phpに列挙されている

Laravelのfacade(ファサード)とは?

こちらが大変参考になった。

ファサードとは、クラスをインスタンス化しなくてもstaticメソッドのようにメソッドを実行できるようにしてくれる機能のこと。

【Laravel】ファサードとは?何が便利か?どういう仕組みか? - Qiita

GOFデザインパターンとは関係ないのね。

ファサードの作成はこちらが参考になる。

[Laravel] Facade作成の流れ - Qiita

Laravelのシーディング

シーディングとは初期データ登録の仕組みのこと

php artisan make:seeder PeopleTableSeeder

これでdatabses/seeds/PeopleTableSeeder.phpができる
このファイルに初期データ登録処理をかく

これだけでは使えないのでDatabaseSeeder.phpに登録する

    public function run()
    {
        $this->call(PeopleTableSeeder::class);
    }

実行するとデータが登録される

php artisan db:seed

WebAuthn APIのパラメータ調査

認証器の登録

{
  "publicKey": {
    "rp": {
      "id": "localhost",
      "name": "検証用ローカルホスト"
    },
    "user": {
      "id": [101, 100, ...],
      "name": "taro",
      "displayName": "太郎"
    },
    "challenge": [101, 100, ...],
    "pubKeyCredParams": [
      {
        "type": "public-key",
        "alg": -7
      }
    ],
    "timeout": 15000,
    "excludeCredentials": [
      {
        "type": "public-key",
        "id": [101, 100, ...],
        "transports": [
          "usb"
        ]
      }
    ],
    "authenticatorSelection": {
      "authenticatorAttachment": "cross-platform",
      "requireResidentKey": true,
      "userVerification": "preferred"
    },
    "attestation": "none"
  }
}
名前 必須? 説明
rp Object 必須 RP(サーバー)に関する情報
rp.id String 任意 RPサーバーのドメイン。 省略した場合はクライアントが自動設定する。認証器はドメインをパラメータにして秘密鍵を生成するため、ドメイン偽装のフィッシングに耐性がある。サブドメインを許容するため、example.jpを設定するとwww.example.jpでも有効な値となる。
rp.name String 必須 表示用。RPの名称を設定
rp.icon String 任意 表示用。RPの画像URLを設定
- - - -
user Object 必須 ユーザーアカウントの情報
user.id ArrayBuffer 必須 ユーザーID。個人が特定できない最大64バイトのランダム文字列推奨。ユーザーハンドルとも呼ばれる。
user.name String 必須 表示用。アカウントを識別できる名前。メールアドレスや電話番号など
user.displayName String 必須 表示用。ユーザー名
user.icon String 任意 表示用。RPの画像URLを設定
- - - -
challenge ArrayBuffer 必須 登録のリクエストを傍受し、同じリクエストを再送信するリプレイ攻撃を回避するためのワンタイム乱数。16バイト以上のランダム文字列推奨。RPサーバーで生成する
- - - -
pubKeyCredParams Array(Object) 必須 クレデンシャルの生成方法を設定
pubKeyCredParams.n.type String 必須 クレデンシャルの種類。public-key(公開鍵)のみ定義されている
pubKeyCredParams.n.alg number 必須 暗号化アルゴリズムのID。優先度が高い順に設定する。IDはhttps://www.iana.org/assignments/cose/cose.xhtml#algorithmsに記載
- - - -
timeout number 任意 登録操作のタイムアウト(ミリ秒)。15〜120秒推奨。省略の場合、クライアントが初期値を設定
- - - -
excludeCredentials Array(Object) 任意 公開鍵クレデンシャルの生成から除外したいクレデンシャル。アカウントに登録する認証器の二重登録を制限するために設定。RPサーバーからユーザーに登録済みのクレデンシャルを設定
excludeCredentials.n.type String 必須 クレデンシャルの種類。public-key(公開鍵)のみ定義されている
excludeCredentials.n.id ArrayBuffer 必須 除外したいクレデンシャルIDを設定
excludeCredentials.n.transports Array 任意 認証器の接続方法を指定。"usb", "nfc", "ble"(Bluetooth), "internal"(プラットフォーム認証器)が定義されている
- - - -
authenticatorSelection Object 任意 認証器の要求事項
authenticatorSelection.authenticatorAttachment String 任意 認証器の接続方法を指定。"platform"(プラットフォーム認証器), "cross-platform"(ローミング認証器)が定義されている
authenticatorSelection.requireResidentKey Boolean 任意 認証器でレジデンドクレデンシャルを保管するか?デフォルトはfalse。trueに設定するとレジデントクレデンシャル(クレデンシャルIDやユーザー情報)を認証器に保管し、認証でユーザーネームレス認証が使用できる。利用にはFIDO2対応の認証器が必要。U2F対応のみの認証器では利用できない。またWebAuthn APIが対応している必要がある。
authenticatorSelection.userVerification String 任意 認証器に搭載された生体認証やPINでユーザー検証するか?"none"(要求しない), "indirect"(クライアント判断), "direct"(要求する)が定義されている。デフォルトは"none"
- - - -
attestation String 任意 認証器の信頼性に関する情報を要求するか? "none"(要求しない), "indirect"(クライアント判断), "direct"(要求する)が定義されている。デフォルトは"none"。ユーザーが同意すると認証器のレスポンス(attestationObject.attStmt)に認証器に対して発行された証明書が設定される。RPサーバはFIDOアライアンスが管理するデータサービス(MDS)を検索して、認証機の証明書や脆弱性に関する情報を検証できる。
{
    "id": "AeOvdfztlZNrzq0y4shQ4SFCTboIDonJffka-E_...",
    "rawId": [
        100,101,...
    ],
    "type": "public-key",
    "response": {
        "attestationObject": [
            100,101,...
        ],
        "clientDataJSON": {
            "type": "webauthn.create",
            "challenge": "8fnANhz56QB3p9zEBY24kw",
            "origin": "http://localhost",
            "crossOrigin": false,
            "other_keys_can_be_added_here": "do not compare clientDataJSON against a template. See https://goo.gl/yabPex"
        }
    }
}
名前 必須? 説明
id String 必須 rawIDをbase64エンコードした値
rawId ArrayBuffer 必須 生成された公開鍵のID
type String 必須 "public-key"(公開鍵)固定
response Object 必須 生成された公開鍵を含む情報
response.attestationObject ArrayBuffer 必須 生成された公開鍵や、認証器本体の証明書などがCBORフォーマットで入っている
- - - -
response.clientDataJSON Object 必須 WebAuthnAPIのcreate()やget()を呼び出す際に、クライアントから認証器へ渡されたデータ
response.clientDataJSON.type String 必須 "webauthn.create"固定
response.clientDataJSON.challenge String 必須 RPから渡されたchallengeがbase64エンコードされて設定
response.clientDataJSON.origin String 必須 RPサーバのオリジン。オリジンなのでプロトコルやポートが含まれる

認証

{
    "publicKey": {
        "rpId": "localhost",
        "challenge": [
            100,
            10,...
        ],
        "timeout": 60000,
        "allowCredentials": [
            {
                "type": "public-key",
                "transports": [
                    "usb",
                    "nfc",
                    "ble",
                    "internal"
                ],
                "id": [
                    100,
                    101,...
                ]
            }
        ],
        "userVerification": "discouraged",
        "extensions": {
            "txAuthSimple": "Execute order 66"
        }
    }
}
名前 必須? 説明
rpId String 任意 RPのドメイン。省略した場合はクライアントが自動設定
rawId ArrayBuffer 必須 生成された公開鍵のID
challenge ArrayBuffer 必須 登録のリクエストを傍受し、同じリクエストを再送信するリプレイ攻撃を回避するためのワンタイム乱数。16バイト以上のランダム文字列推奨。RPサーバーで生成する
timeout number 任意 登録操作のタイムアウト(ミリ秒)。15〜120秒推奨。省略の場合、クライアントが初期値を設定
- - - -
allowCredentials Array 任意 アカウントに紐付けた認証器のリスト
allowCredentials.type String 必須 クレデンシャルの種類を設定。"public-key"のみ定義
allowCredentials.transports Array 任意 認証器の接続方法を指定。"usb", "nfc", "ble"(Bluetooth), "internal"(プラットフォーム認証器)が定義されている
allowCredentials.id ArrayBuffer 必須 アカウントに紐づけて登録した認証器のクレデンシャルIDを設定
- - - -
userVerification String 任意 認証器に搭載された生体認証やPINでユーザーを検証するかを指定。"required"(必須)、"preferred"(対応していれば要求)、"discouraged"(要求しない)が定義されている。デフォルトは"preferred"
{
    "id": "AeOvdfztlZNrzq0y4shQ4SFCTboIDonJffka-E_...",
    "rawId": [100, 101,...],
    "type": "public-key",
    "response": {
        "authenticatorData": [100, 101,...],
        "clientDataJSON": {
            "type": "webauthn.get",
            "challenge": "Kidrf2zZeC6Cw5XuOMSHVA...",
            "origin": "http://localhost",
        },
        "signature": [
            100, 101,...
        ],
        "userHandle": null
    }
}
名前 必須? 説明
id String 必須 rawIDをbase64エンコードした値
rawId ArrayBuffer 必須 生成された公開鍵のID
type String 必須 "public-key"(公開鍵)固定
response Object 必須 生成された公開鍵を含む情報
response.authenticatorData ArrayBuffer 必須 認証器の信頼性に関する情報が含まれているバイナリデータ。決められたbyte数でパースすることでパラメータを取得できる。さらに、authenticatorDataの中に、attestedCredentialDataというパラメータがあり、認証器の情報や公開鍵の情報が含まれている。これもバイナリで表現されており、利用時にauthenticatorDataと同様に、パースする必要がある。rpIdHash(32bytes), flags(1bytes), signCount(4bytes), attestedCredentialData.AAGUID(16bytes), attestedCredentialData.credentialIdLength(2bytes), attestedCredentialData.credentialId(credentialIdLengthバイト), attestedCredentialData.credentialPublicKey
response.clientDataJSON ArrayBuffer 必須 登録と同じ値
response.signature ArrayBuffer 必須 認証器の秘密鍵による署名。署名はRPサーバに登録された公開鍵で検証する
response.userHandle ArrayBuffer 必須 設定されていた場合は、RPサーバで登録時に指定したuser.idと一致するかを検証する

OpenID Connect (OIDC)の概要理解

  • ソーシャルログインの仕組みの標準仕様
  • FacebookやYahoo側をプロバイダと呼ぶ
  • IDトークンは認証情報のトークン (認証されたという事実とユーザーの属性情報を各所に引き回すため)
  • IDトークンを発行する係はOpenIDプロバイダー
  • IDトークンはJWTの拡張
  • OpenID プロバイダーになるつもりがなければ、OpenID Connect を実装する必要はない
  • ただし金融業界などの高いセキュリティが求められるAPIOpenID Connectのサポートが求められる