LoginSignup
11
6

More than 3 years have passed since last update.

OpenAPI 3.0でOAuth2/OpenID Connectの認可を表現したい

Last updated at Posted at 2021-02-23

はじめに

API仕様書いていますか?

この記事を読まれる人は、何かしらAPI仕様やOpenAPI/Swaggerに関わりがあったり、API仕様の認可の仕組みにOAuth2やOpenID Connect(OIDC)を利用することを検討していたりすると思います。
この記事では、OAuth2やOIDCの認可の仕組みを取り入れて、OpenAPI 3.0で定義されている securitySchemessecurity フィールドをどう使って書いていけばいいか説明します。

OpenAPI/Swaggerや、OAuth2、OpenID Connectの各仕様や解説はそれぞれの大元のサイトやRFC、また先達の素晴らしい解説が多くありますので、そちらを参照して貰うとしては、OpenAPI 3.0のSecurity Scheme Objectのリンクを載せておきます。基本的にリンク先に示した箇所周辺のことを説明しています。
- OpenAPI 3.0 SecurityScheme Object

なお、本記事はOpenAPI 3.0.3をもとにしています。

APIリクエストをトークンが必要なことを明示したい

API仕様を設計する上で、リクエストが誰からでも叩けるのはセキュリティ的に好ましくありません。なので、クエリパラメータやヘッダーにアクセストークンを付加してリクエストを送って貰うと考えるとおもいます。

$ curl --request POST \
  --url https://example.com/users \
  --header 'Authorization: Bearer アクセストークン' --data '{"name": "Bob"}'

もしかしたら、Parameter Objectを使って、以下の様に記載するかもしれません。

/users:
    post:
      parameters:
        - schema:
            type: string
          in: header
          name: Authorization
          description: Bearer アクセストークンを付加する

確かに HTTPヘッダに Authroization を付加して、Bearer(署名なし)アクセストークンをここに付加する意図は理解できるかもしれませんが、明確ではありません。

こういう場合は、Security Requirement Object security フィールドを利用します。

/users:
    post:
      security:
        - AuthBearer: []

AuthBearer というのは、Security Scheme Objectで自身で定義するフィールドで、空の配列要素をもっています、空なのは仕様です。この例では、POSTメソッドを表す Path Item Objectの下に Security Requirement Object security を配置していますが、一番の上に security を配置すると、すべてのリクエストに適用されることを意味まします。

AuthBearerは以下の様に定義します。

components:
  securitySchemes:
    AuthBearer:
      type: http
      scheme: bearer
      description: AuthorizationヘッダでBearerアクセストークンを送る場合

type: httpscheme: bearer で、HTTPヘッダで Authorization: Bearer であることを表しています。なお、type: http のとき、 security フィールド時に配列を空にしないといけません。

typehttp 以外にも、 apiKey を指定し、 in: query とするとクエリパラメータで送ることになります。ただし、このときはトークンの種類(例えばBearer)を表すことはできません。

components:
  securitySchemes:
    QueryKey:
      type: apiKey
      description: クエリパラメータでトークンを送る場合
      in: query
      name: access_token

APIリクエストの認可をアクセストークンのスコープで表現したい

あるAPIリクエストを払い出したアクセストークンに紐付けるのは、OAuth2 RFC6749 section 3.3 で定義されている scope で表現することが多いでしょう。OpenAPI3も scope をAPI毎にスコープを明示することができます。

/users:
    post:
      security:
        - OAuth2:
            - 'users:write'

OAuth2 もSecurity Scheme Objectです。配列要素の 'users:write' は、scopeを表すので、 /users というAPIを利用するためには、アクセストークンにこの scope が付加していないとアクセスできないこと(そのような実装が必要)を表します。

OAuth2の認可をAPI仕様に定義したい

Security Scheme Objectを利用します。OAuth2には多くの認可フローがありますが、今回はWebアプリケーション開発する上で一番一般的だと思う Authorization Code Flow の定義をしてみます。

components:
  securitySchemes:
    OAuth2:
      type: oauth2
      description: Authorization Code Flowの各エンドポイントを定義します
      flows:
        authorizationCode:
          authorizationUrl: '/oauth2/authorize'
          tokenUrl: '/oauth2/token'
          refreshUrl: '/oauth2/refresh'
          scopes:
            'users:read': ユーザー情報の取得
            'users:write': ユーザー情報の編集

authorizationUrl などは相対パス(relative path)として記載していますが、ホストが異なる場合は、URLをhttpsからすべて書くとよいでしょう。ここで OAuth2 を定義することで、先ほど説明した Security Requirement Object security に指定できるようになります。さらに、 scopes フィールドには、カスタムscopeも可能なので、自身で定義したスコープのうち、アクセストークンが認可する scope を列挙します。この scopes フィールドで列挙したもののうち、APIに紐付けるスコープを Security Reqirement Objectの OAuth2 の配列要素として記載します。

/users:
    post:
      security:
        - OAuth2:
            - 'users:write'
        - AuthBearer: []

OpenID Connect Discovery 1.0で参照!

認可において、OpenID Connect Discovery 1.0の .well-know/configuration から情報を取得して貰うようにする場合は、 type"openIdConnect" を利用します。

components:
  securitySchemes:
    OIDC:
      type: openIdConnect
      description: OpenID Providerの設定を取得するためのURI。OpenID Connect Discovery 1.0で定義
      openIdConnectUrl: 'https://example.com/.well-known/openid-configuration'

openIdConnectUrl から得られるメタデータにも "scopes_supported" でscopeの定義がありますので、Security Requirement Objectに OIDC を記載して、scopeを列挙できます。

/users:
    post:
      security:
        - OIDC:
            - 'users:write'
        - AuthBearer: []

最後に

記載する量はたいしたことありませんが、これによりAPIリクエストのセキュリティ要件がより明確になります。
API設計者のみなさんのイケてるAPI設計の一助になれば。

11
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
6