# How-to Guide - OAuth 2.0 証明書付きの認可コードグラント

OAuth 2.0 認可コードフローは、WorkatoがAPIに認証する際に特定のユーザーを模倣する方法です。これは、ユーザーが最初に接続しようとするときにブラウザのポップアップを介してユーザーの同意を取得することで行われます。このPKCEバリアントでは、認可URLにチャレンジが提示され、最終的なトークン交換リクエストには検証者が提示される追加の検証ステップがあります。

# サンプルコネクタ - Dropbox

{
  title: "Dropbox pkce",

  connection: {
    fields: [
      { name: 'client_id' },
      { name: 'client_secret' }
    ],
    authorization: {
      type: "oauth2",

      client_id: lambda do |connection|
        connection['client_id']
      end,

      client_secret: lambda do |connection|
        connection['client_secret']
      end,
      
      pkce: lambda do |verifier, challenge|
        {
          verifier: verifier,
          challenge: challenge,
          challenge_method: "S256"
        }
      end,

      authorization_url: lambda do |connection|
        "https://www.dropbox.com/oauth2/authorize?client_id=#{connection['client_id']}&response_type=code"
      end,

      token_url: lambda do |_connection|
        "https://api.dropbox.com/oauth2/token"
      end,

      apply: lambda do |_connection, access_token|
        headers('Authorization': "Bearer #{access_token}")
      end
    },
  },

  test: lambda do |_connection|
    post("https://api.dropboxapi.com/2/check/app", {})
  end,

  #More connector code here
}

# Step 1 - 接続フィールドの定義

このコンポーネントは、接続を確立しようとするユーザーに表示するフィールドをWorkatoに指示します。認証コードグラントとPKCEの場合、ユーザーがDropboxの開発者コンソールで生成したクライアントIDとクライアントシークレットが必要です。

これは、fieldsキーで行われ、配列のハッシュを受け入れます。この配列の各ハッシュは、個別の入力フィールドに対応します。

    fields: [
      {
        name: 'client_id',
        optional: false
      },
      {
        name: 'client_secret',
        optional: false,
        control_type: 'password'
      }
    ],

TIP

フィールドを定義する際には、少なくともnameキーを指定する必要があります。optionalhintcontrol_typeなどの追加の属性を使用すると、これらのフィールドの他の側面をカスタマイズすることができます。クライアントシークレットのような機密情報には、control_typeとしてpasswordを使用することを忘れないでください。

Workatoで入力フィールドを定義する方法について詳しく学びましょう。

# Step 2 - 認可タイプの定義

このコンポーネントは、接続を確立するために入力フィールドから受け取った値をWorkatoにどのように処理するかを指示します。これは、authorizationキーを介して処理されます。このキーでは、まず認可のtypeを定義します。この場合、認可コードグラントフローと同様にoauth2を使用する必要があります。

      type: "oauth2",

# Step 3 - クライアントID、クライアントシークレット、およびPKCEパラメータの定義

これらのコンポーネントは、後でSDKフレームワークがクライアントID、クライアントシークレット、およびPKCEパラメータとして使用する内容を指定します。

      client_id: lambda do |connection|
        connection['client_id']
      end,

      client_secret: lambda do |connection|
        connection['client_secret']
      end,
      
      pkce: lambda do |verifier, challenge|
        {
          verifier: verifier,
          challenge: challenge,
          challenge_method: "S256"
        }
      end,

この例では、クライアントIDとシークレットのユーザーの入力を、それぞれ関連するclient_idclient_secretのラムダにマッピングします。これは、fieldsで定義したハッシュで表されるユーザーの入力を示すハッシュであるconnection引数を使用して行われます。

次に、pkceラムダも定義する必要があります。これは、これがPKCE付きの認可コードグラントフローであることを示す重要なマーカーです。このラムダでは、verifierchallengeに対応する2つの引数を受け取ります。これらの引数をそのまま使用し、例に示すようにpkceラムダの出力として渡すことができます。

# Step 4 - 認可URLとトークンURLの定義

OAuth 2のPKCEバリアントでは、認可URLとトークンURLの2つを指定します。これは通常の認可コードグラントフローと同様です。

  • 認可URL:ユーザーをブラウザのポップアップ経由でリダイレクトして認可を提供する場所です。
  • トークンURL:このコネクタが認可URLから認可コードを受け取った後、アクセストークンを受け取るためにリクエストを送信する場所です。
  authorization_url: lambda do |connection|
    "https://www.dropbox.com/oauth2/authorize"
  end,

  token_url: ラムダ関数を使用して、接続先のURLを定義します。

```ruby
_url: lambda do |connection|
    "https://api.dropbox.com/oauth2/token"
  end,

authorization_urlのラムダ関数を定義する際に、Workatoは自動的に以下のパラメータを渡します:

  • クライアントID
  • リダイレクトURI
  • コードチャレンジ
  • ステート

場合によっては、必要に応じてURLにスコープを追加する必要があります。アプリケーションが事前にリダイレクトURIの登録を要求する場合は、次のURLを使用してください:https://www.workato.com/oauth/callback

token_urlのラムダ関数を定義する際に、Workatoは自動的に以下のパラメータを渡します:

  • クライアントID
  • クライアントシークレット
  • コードベリファイア
  • grant_type

token_urlのリクエストでは、RFCの標準に従い、ペイロードボディに関連情報を含むPOSTリクエストを使用します。Workatoが短期間の認証コードを長期間のアクセストークンと交換する際に、token_urlエンドポイントからのレスポンスにはaccess_tokenrefresh_tokenという2つの主要な値が含まれることを期待しています。以下はサンプルのレスポンスです:

{
  "access_token": "my-authentication-token",
  "token_type": "bearer",
  "expires_in": "seconds-until-expiration",
  "refresh_token": "my-refresh-token",
  "error": "optional-error-message",
  "ref":
  {
    "type": "user",
    "id": USER_ID
  }
}

認証はaccess_tokenrefresh_tokenに関連する値を保存します。

# ステップ5 - 取得したアクセストークンを後続のHTTPリクエストに適用する

applyキーでは、取得したアクセストークンをヘッダー入力として適用します。

access_tokenは、単純にaccess_tokenをパラメータとしてapplyキーに渡すことで取得できます。この引数access_tokenは、token_urlのラムダ関数の出力から自動的に割り当てられます。

    apply: lambda do |connection, access_token|
      headers("Authorization": "OAuth2 #{access_token}")
    end,

接続オブジェクトの利用可能なパラメータとキーについて詳しくは、SDKリファレンス - connectionを参照してください。

# ステップ6 - トークンのリフレッシュ動作の定義

ほとんどの場合、OAuth 2.0認証には短期間のアクセストークンと長期間のリフレッシュトークンがあります。リフレッシュトークンは期限切れにならない場合もあります。

::: warn すべてのAPIがリフレッシュトークン資格情報を発行するわけではないことに注意してください。この要件についてはAPIに確認してください。 :::

アクセストークンが期限切れになった場合、リフレッシュトークンを使用してアクセストークンをリフレッシュするためにコネクタが取るべき動作を定義することができます。

    refresh_on: [401, 403],

    refresh: lambda do |connection, refresh_token|
      response = post("https://api.dropbox.com/oauth2/token").
                    payload(
                      grant_type: "refresh_token",
                      client_id: connection["client_id"],
                      client_secret: connection["client_secret"],
                      refresh_token: refresh_token,
                      redirect_uri: 'https://www.workato.com/oauth/callback'
                    )
      [
        {
          access_token: response["access_token"],
          refresh_token: response["refresh_token"]
        }
      ]   
    end,

アクセストークンをリフレッシュするには、authorizationキーの中で2つのキーを使用する必要があります - refresh_onrefreshです。refresh_onは、HTTPレスポンスコードまたは正規表現文字列を含む配列を受け入れることができます。コネクタのHTTPリクエストがHTTPレスポンスコードのいずれかを受け取るか、ペイロードの本文が正規表現文字列と一致する場合、refreshキーのコードが実行され、新しいアクセストークンを取得しようとします。

refreshキーでは、初期トークンリクエストから受け取ったrefresh_tokenを表す引数にアクセスできます。このラムダ関数の期待される出力は、最初のインデックスが新しいaccess_tokenおよび適用可能な場合の新しいrefresh_tokenを示すハッシュである配列です。これらは、長期間の接続の初期値を更新するために使用されます。

リフレッシュラムダについて詳しくは、SDKリファレンス - authorizationを参照してください。

# ステップ7 - APIのベースURIの設定

このコンポーネントは、APIのベースURLをWorkatoに伝えるものです。このキーはオプションですが、HTTPリクエストを定義する際に相対パスのみを提供することができます。ベースURIの設定方法については、ベースURIの設定を参照してください。

    base_uri: lambda do |connection|
      'https://api.dropboxapi.com'
    end

TIP

このラムダ関数は、connection引数にアクセスすることもできます。これは、APIのベースURIがユーザーのインスタンスに基づいて変更される可能性がある場合に特に便利です。connection引数は、次の形式でアクセスできます:

    base_uri: lambda do |connection|
      "https://#{connection['domain'].com/api}"
    end

# ステップ8 - 接続のテスト

エンドユーザーから収集する必要があるフィールドと、それらのフィールドの入力に対して行う操作を定義したので、接続をテストする必要があります。① way to test this connection. This is handled in the test key.

    test: lambda do
      post("https://api.dropboxapi.com/2/check/app", {})
    end,

このブロックでは、新しく受け取った認証情報を使用してサンプルリクエストを送信するためのエンドポイントを提供する必要があります。もし200 OKのHTTPレスポンスを受け取った場合、接続は成功と表示されます。上記の例では、POSTリクエストを/2/check/appエンドポイントに送信し、受け取ったアクセストークンが有効であれば、200のレスポンスを期待しています。

# Auth code grant PKCE variation

場合によっては、acquireラムダを使用してトークンリクエストを完了する必要がある場合があります。ここでは、同じDropbox接続を使用しているが、acquireラムダを使用している例を示します。

  connection: {
    fields: [
      { name: 'client_id' },
      { name: 'client_secret' }
    ],
    authorization: {
      type: "oauth2",

      client_id: lambda do |connection|
        connection['client_id']
      end,

      client_secret: lambda do |connection|
        connection['client_secret']
      end,
      
      pkce: lambda do |verifier, challenge|
        {
          verifier: verifier,
          challenge: challenge,
          challenge_method: "S256"
        }
      end,

      authorization_url: lambda do |connection|
        "https://www.dropbox.com/oauth2/authorize?client_id=#{connection['client_id']}&response_type=code"
      end,

      acquire: lambda do |connection, auth_code, redirect_uri, verifier|
        response = post("https://api.dropbox.com/oauth2/token",
          grant_type: "authorization_code",
          code: auth_code,
          redirect_uri: redirect_uri,
          client_secret: connection["client_secret"],
          code_verifier: verifier,
          client_id: connection["client_id"]
        ).request_format_www_form_urlencoded

        [
          {
            access_token: response["access_token"],
            refresh_token: response["refresh_token"],
            refresh_token_expires_in: response["expires_in"] # Expiration time of the refresh token from now in seconds
          },
          nil,
          { instance_id: nil }
        ]
      end,

      apply: lambda do |_connection, access_token|
        headers('Authorization': "Bearer #{access_token}")
      end
    },
  },

acquireラムダで受け取る追加の引数verifierは、pkceラムダの出力として渡した同じ検証子に対応することに注意してください。

# Connections SDK reference

connectionキー内の利用可能なキーとそのパラメータについて詳しく知るためには、当社のSDKリファレンスを参照してください。


Last updated: 2024/2/13 16:59:53