パーミッションセット

OAuthパーミッションスコープとセット

このページでは、カスタムLexiconのためのパーミッションセットを定義・公開する方法を説明します。OAuthフローで既存のパーミッションスコープを使用したいだけの場合は、パーミッションリクエストを参照してください。

パーミッションセットについて

OAuthフローはセッションで付与されるアクセスのレベルを表すパーミッション「スコープ」を使用します。ユーザーのアカウントへの広範なアクセスをリクエストするのではなく、atprotoアプリは特定のレコードタイプやAPIエンドポイントに対して細かいパーミッションをリクエストする必要があります。

コアとなるパターンはシンプルです:アプリが必要とするコレクションへのアクセスのみをリクエストする。例えば、アプリが独自のLexiconを使って投稿といいねを作成する場合:

repo:com.example.post repo:com.example.like blob:*/*

これにより、アプリはcom.example.postcom.example.likeコレクションのレコードを作成・更新・削除するパーミッション、およびメディアをアップロードするパーミッションを取得します。ユーザーの認可ダイアログには、transition:genericのような広範なスコープが生み出す不安を感じさせる「ほぼすべてへのアクセス」ではなく、これらの特定のパーミッションが明確に表示されます。

より整理された認可UIのために、関連するパーミッションを人間が読める説明付きのパーミッションセットにまとめることができます。以下のパーミッションセットの設計を参照してください。

クイックスタート

独自のレコードタイプを作成するアプリのための最小限のoauth-client-metadata.jsonの例:

{
  "client_id": "https://example.com/oauth-client-metadata.json",
  "client_name": "My Example App",
  "client_uri": "https://example.com",
  "redirect_uris": ["https://example.com/oauth/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "scope": "atproto repo:com.example.post repo:com.example.like blob:*/*",
  "token_endpoint_auth_method": "none",
  "dpop_bound_access_tokens": true
}

これはアイデンティティ(atproto)、2つのレコードコレクションへの書き込みアクセス、およびメディアアップロードをリクエストします。完全なセットアップガイドについては、About OAuthを参照してください。

最小限のパーミッション

atproto OAuthを使用するアプリ(アイデンティティのみ、データアクセスなし)の絶対最小値:

  • atproto

Blueskyのプロフィールデータも必要な場合:

  • rpc:app.bsky.actor.getProfile?aud=did:web:api.bsky.app#bsky_appview

画像や動画のアップロードが必要な場合:

  • blob:*/*

transition:genericのような粗い粒度の「トランジションスコープ」は引き続きサポートされていますが、細かいパーミッションの採用を推奨します。トランジションスコープの概要については、Authorization Scopesを参照してください。完全な細かいパーミッション仕様については、Permissionsを参照してください。

パーミッションセットの設計

フル機能のクライアントアプリは動作するために多数の細かいパーミッションを必要とします:数十、場合によっては数百の個別のパーミッションが必要です。パーミッション管理を簡素化するために、Lexiconデザイナーは公開するスキーマの一部としてパーミッションの「セット」を定義できます。これらのパーミッションセット自体もLexiconスキーマであり、com.example.authBasicFeaturesのようなネームスペースIDで参照されます。

例えば、アプリケーションはinclude:com.example.authBasicFeatures?aud=did:web:api.example.com%23svc_appviewのようなパーミッションセットをリクエストできます。これはアプリが動作するために必要なパーミッションのセットを定義するLexiconに解決されます:

{
  "lexicon": 1,
  "id": "com.example.authBasicFeatures",
  "defs": {
    "main": {
      "type": "permission-set",
      "title": "Basic App Functionality",
      "detail": "Creation of posts and interactions",
      "permissions": [
        {
          "type": "permission",
          "resource": "repo",
          "collection": ["app.example.post"]
        },
        {
          "type": "permission",
          "resource": "rpc",
          "inheritAud": true,
          "lxm": [
            "app.example.getFeed"
            "app.example.getProfile",
            ...
          ]
        },
      ]
    }
  }
}

app.example.feed.authOnlyPostcom.example.authBasicFeaturesの例にあるauthプレフィックスに注目してください。これはLexiconがパーミッションセットとして使用するよう設計されていることを示す命名規則です。

パーミッションセットは、セット自体と同じNSIDネームスペース下のリソースを参照するパーミッションのみを表現できます。例えば、セットapp.example.feed.authOnlyPostapp.example.feed.postレコードへのパーミッションと、リモートサービスへのapp.example.feed.getPostThread APIエンドポイントリクエストのパーミッションを含めることができます。しかし、app.example.actor.profileへのパーミッションは付与できません。階層で一段上のapp.example.authFullのようなパーミッションセットは、これらすべてのリソースへのパーミッションを含めることができます。

titledetailsフィールドは説明的であり、OAuthフローの一部として表示されます。これらの説明フィールドの国際化がサポートされています。詳細はパーミッションセット仕様を参照してください。

rpcパーミッションにおけるinheritAudの使用により、継承の動作を制御できます。

画像・動画の処理のためのblob:*/*パーミッションはパーミッションセットに含めることができず、常に個別にリクエストする必要があります。

パーミッションセットもLexiconであり、同じツールを使って公開されます。goatを使ってLexiconを作成、リント、公開する方法については、Lexiconの公開を参照してください。

プログレッシブスコープリクエスト

アプリはサインイン時にすべてのパーミッションをリクエストする必要はありません。最小限のスコープから始めて、ユーザーが機能にオプトインするにつれて後からさらにリクエストすることができます。動的なスコープ選択や既存セッションのアップグレードを含む実装パターンについては、OAuth Patternsを参照してください。

参考資料とリソース