こんにちは。CData Software Japan リードエンジニアの杉本です。
CData Driver では以下の記事で紹介しているように、現在多くのDriverがOAuth 2.0(以下、OAuthとします)の処理を行う際に、CDataが取得したアプリを通じてログイン処理を行うように構成されています。
https://www.cdata.com/jp/blog/salesforceoauthsupport
しかしながらユースケースによっては、CData Driverを自社のアプリに組み込み、併せて独自にOAuth用アプリを作成し、ユーザーに対して認証・認可プロセスを提示したいといった要望があるかと思います。
そんな時にもCData Driver は簡単にOAuthの認証・認可プロセス用のハンドリングをサポートする機能が存在します。
今回はCData Driverを使ったOAuthの自社アプリ側でハンドリングするための利用方法紹介したいと思います。
なお、今回はCData Office365 Driver および Azure AD を例として解説しています。プログラミング言語としてPythonおよびCData Python Connector を利用していますが、機能としての使い方はODBCやJDBCでも共通です。
https://www.cdata.com/jp/drivers/office365/
また、 OAuth のGrantTypeはAuthorization Code Flowを用いています。APIによってはClient Credentialなどをサポートしているものもあるので、良ければ参考にしてみてください。
https://www.cdata.com/jp/blog/2019-09-19-105417
CData Python Connectorの基本的な使い方は以下の記事を参考にしてみてください。
https://www.cdata.com/jp/blog/python-salesforce-howtouse
※今回の記事では一律OAuthと表記しています。Office365 の場合 OAuth 2.0 が正しい表記ですが、CData Driver ではOAuthの認証・認可のプロセス名としての指定となりますので、2.0・1.0区別をせず、OAuthと表記しました。
OAuth ハンドリングパターン
まずざっくり、CData Driver がサポートするOAuth のハンドリングパターンを紹介します
考え方としてはどこまで自社アプリ側で開発を行い、どこまでCData DriverにOAuthのハンドリングを移譲するかがポイントとなります。
プロセスとしては以下の通りです。
1:認証・認可URLを通じて、Authorization Codeを取得
2:Authorization Codeを元にAccess TokenおよびRefresh Tokenを取得
3:Access Tokenの期限が切れたら、Refresh Tokenを使ってAccess Tokenを更新
これをCData・自社アプリでどこまでカバーするか?によって以下のようにパターンが分かれます。
No
|
Type
|
Authorization Codeの取得
|
Access Tokenの取得
|
Access Tokenの更新
|
1
|
Authorization Codeの取得からAccess Token・Refresh Token の管理まですべてCDataで行うパターン
|
CData
|
CData
|
CData
|
2
|
Authorization Code 取得までパターン
|
自社アプリ
|
CData
|
CData
|
3
|
Access Token 取得までパターン
|
自社アプリ
|
自社アプリ
|
CData
|
4
|
Access Token・Refresh Token すべて自社管理パターン
|
自社アプリ
|
自社アプリ
|
自社アプリ
|
それでは実際に試していきましょう。
Azure AD OAuth アプリの登録
まず、今回はOffice365 Driverを利用するので、OAuthのアプリをAzure ADに登録します。
Azure Active Directory 管理センターに移動し「Azure Active Directory 」→「アプリの登録」→「新規登録」をクリックします。
任意のアプリケーション名を入力し、「任意の組織ディレクトリ内のアカウント」を選択します。これは外部組織のユーザーに対して、認証・認可を要求するためのアプリとするためです。
併せてリダイレクトURIを指定します。今回は擬似的にLocahostで行うので「Web」「 http://localhost:33333」を指定します。ポート番号は開いている任意の番号でOKです。
アプリを作成したらアプリケーションIDを控えておきましょう。
続いてクライアントシークレットを生成します。「証明書とシークレット」から「+新しいクライアントシークレット」を選択し、「説明」・「有効期限」を指定して「追加」をクリックします。
以下のようにクライアントシークレットが生成されるので、こちらの値も控えておきます。
クライアントシークレットを生成したら、このアプリの求めるアクセス許可を設定しましょう。
「APIのアクセス許可」から「+アクセス許可の追加」をクリックし
「Microsoft Graph」を選択
委任されたアクセス許可で必要な許可を選択します。
なお、CData Office365 Driverがデフォルトで必要とするアクセス許可は以下のとおりです。
・https://graph.microsoft.com/group.read.all
・https://graph.microsoft.com/group.readwrite.all
・https://graph.microsoft.com/user.read
・https://graph.microsoft.com/user.readwrite.all
・https://graph.microsoft.com/calendars.readwrite
・https://graph.microsoft.com/contacts.readwrite
・https://graph.microsoft.com/mail.readwrite
https://cdn.cdata.com/help/CXG/jp/py/pg_sp-getoauthauthorizationurl.htm
アクセス許可の設定が完了すれば、OAuthアプリの設定は完了です。
CData Office365 Python Connectorの準備
それではCData側の準備を進めます。今回はCData Office365 Python Connectorを使用するので以下のURLからトライアルバージョンを取得しておきます。
https://www.cdata.com/jp/drivers/office365/download/python/
なお、Pythonのバージョンは「3.9」、CData Python Connectorは「22.0.8257」を使用しました。
「pip install cdata_office365_connector-22.0.8257-cp39-cp39-win_amd64.whl」でインストールを行います。
併せて「C:\Users\ユーザー名\AppData\Local\Programs\Python\Python39\Lib\site-packages\cdata\installlic_office365」にある「install-license.exe」を実行して、ライセンスのインストールを行います。
以上で準備完了です。
Authorization Codeの取得からAccess Token・Refresh Token の管理まですべてCDataで行うパターン
まずは、シンプルにすべてCData側で処理するパターンを確認してみましょう。
これはドキュメントでは「埋め込みクレデンシャル」を用いた手法となっています。
https://cdn.cdata.com/help/CXG/jp/py/pg_oauthembedded.htm
接続プロパティでポイントになるのは「InitiateOAuth」という設定です。このプロパティで「GETANDREFRESH」を指定していると、Authorization Codeの取得からAccess Token・Refresh Token の取得・更新まですべてCData Driverが行うようになります。
https://cdn.cdata.com/help/CXG/jp/py/RSBOffice365_p_InitiateOAuth.htm
それでは、以下のコードを実行してみます。
import cdata.office365 as mod
conn = mod.connect("InitiateOAuth=GETANDREFRESH;")
すると自動でブラウザが立ち上がり、アクセス許可が求められるので、許可しましょう。
以下のようにメッセージが表示されれば接続完了です。
取得したAcces Tokenは以下の「OAuthSettingsLocation」のパスに保存されます。
https://cdn.cdata.com/help/CXG/jp/py/RSBOffice365_p_OAuthSettingsLocation.htm
これでCData Driver が取得したAcces Tokenを使ってAPIにアクセスができます。
conn.execute("SELECT DisplayName, Id FROM Users").fetchall()
※後続のパターンを確認するために都度「OAuthSettingsLocation」のファイルは消しておきます。
Authorization Code 取得までパターン
続いて、Authorization Code の取得までを自社アプリ側で行うパターンを実施してみましょう。とはいえ今回は特別なプログラミングは行わず、認可URLをブラウザに貼り付けて、手動でAuthorization Codeを取得します。
そのためにまず、認可URLを取得しましょう。認可URLは手動で作成しても構いませんが、CData Driver の「GetOAuthAuthorizationURL」というストアドプロシージャを使うと簡単に取得できます。
https://cdn.cdata.com/help/CXG/jp/py/pg_sp-getoauthauthorizationurl.htm
ストアドプロシージャの実行のために、まずConnectionを行います。この時まだAcces Tokenの取得などは行わないので「InitiateOAuth=NONE;」を指定します。併せて、事前に取得しておいたClientIdとClientSecret・そしてCallbackURLを接続文字列に入力します。
import cdata.office365 as mod
conn = mod.connect("InitiateOAuth=NONE;OAuthClientId=70cce521-288a-4080-80d4-ab5ca3d222b1;OAuthClientSecret=8P~8Q~9i~qTg3rG.Ud.jyDcx9Oes1n1ThiG4mbCS;CallbackURL=http://localhost:33333;")
接続後、以下のようにストアドプロシージャを実行し、レスポンスとなる認可URLを採取します。
conn.execute("EXECUTE GetOAuthAuthorizationURL").fetchall()
対象の認可URLをクリックして、アクセス許可を行います。今回はすでにアクセス許可済みなので、そのままAuthorization Codeが取得できます。
Authorization CodeはLocalhostへのコールバックに対する「?code=」で確認できます。
この取得した認可コードを用いて、再度コネクションを張ります。「InitiateOAuth=REFRESH;」でAcces TokenをCData Driverが取得するように構成し、「OAuthVerifier」のプロパティで取得したAuthorization Codeを指定します。
import cdata.office365 as mod
conn = mod.connect("InitiateOAuth=REFRESH;OAuthClientId=70cce521-288a-4080-80d4-ab5ca3d222b1;OAuthClientSecret=8P~8Q~9i~qTg3rG.Ud.jyDcx9Oes1n1ThiG4mbCS;CallbackURL=http://localhost:33333;OAuthVerifier=0.AWsA2q6z5vSIN(取得した認可コードを指定)")
正常に取得できると、以下のようにOAuthSettingsLocationにファイルが生成されます。
ちゃんとAPIアクセスもできました。
このようにAuthorization Codeの取得部分だけを自社アプリで実装すれば、手軽にAcces Tokenの取得処理が実装できます。また、RefreshTokenの管理もCDataが自動的に行なってくれるので楽ですね。
Access Token 取得までパターン
次はAcces Tokenまで取得するパターンを行ってみましょう。
こちらは認可URLを使って、Authorization Codeを取得するところまでは手順が一緒です。
import cdata.office365 as mod
conn = mod.connect("InitiateOAuth=NONE;OAuthClientId=70cce521-288a-4080-80d4-ab5ca3d222b1;OAuthClientSecret=8P~8Q~9i~qTg3rG.Ud.jyDcx9Oes1n1ThiG4mbCS;CallbackURL=http://localhost:33333;")
conn.execute("EXECUTE GetOAuthAuthorizationURL").fetchall()
次にAcces Tokenの取得は「GetOAuthAccessToken」というストアドプロシージャを用いて行います。
https://cdn.cdata.com/help/CXG/jp/py/pg_sp-getoauthaccesstoken.htm
conn.execute("EXECUTE GetOAuthAccessToken Verifier = '0.AWsA2q6z(取得したAuthorization Codeを指定)'").fetchall()
すると、以下のようにAccessToken、ExpiresIn、RefreshTokenの情報がそれぞれ取得できます。
これらの値を用いて「InitiateOAuth=REFRESH;」で接続プロパティに「OAuthAccessToken」「OAuthRefreshToken」「OAuthExpiresIn」を追加します。
import cdata.office365 as mod
conn = mod.connect("InitiateOAuth=REFRESH;OAuthClientId=70cce521-288a-4080-80d4-ab5ca3d222b1;OAuthClientSecret=8P~8Q~9i~qTg3rG.Ud.jyDcx9Oes1n1ThiG4mbCS;CallbackURL=http://localhost:33333;OAuthAccessToken=(取得したAcces Token);OAuthRefreshToken=(取得したRefreshToken);OAuthExpiresIn=(取得したExpiresIn);")
これでOAuthSettingsLocationのファイルが生成されます。
これで以下のようにAPIアクセスが可能になります。
Access Token・Refresh Token すべて自社管理パターン
最後に自社アプリですべてAccess Token・Refresh Tokenを管理するパターンです。
このパターンではAccess Token・Refresh Tokenを自社アプリ側で管理するので、OAuthSettingsLocationにファイルは作成されません。
Access Tokenの取得だけでなく、RefreshTokenの処理もストアドプロシージャで実行し、都度Access Tokenを接続プロパティに指定するパターンです。
import cdata.office365 as mod
conn = mod.connect("InitiateOAuth=NONE;OAuthClientId=70cce521-288a-4080-80d4-ab5ca3d222b1;OAuthClientSecret=8P~8Q~9i~qTg3rG.Ud.jyDcx9Oes1n1ThiG4mbCS;CallbackURL=http://localhost:33333;")
conn.execute("EXECUTE GetOAuthAuthorizationURL").fetchall()
conn.execute("EXECUTE GetOAuthAccessToken Verifier = '0.AWsA2q6z(取得したAuthorization Codeを指定)'").fetchall()
以下のようにストアドプロシージャを用いて、Access TokenのRefreshが可能です。
https://cdn.cdata.com/help/CXG/jp/py/pg_sp-refreshoauthaccesstoken.htm
conn.execute("EXECUTE RefreshOAuthAccessToken OAuthRefreshToken = '0.AWsA2q6z(取得したRefreshTokenを指定)'").fetchall()
接続文字列でアクセストークンを毎回最新のもので指定するのであれば、「InitiateOAuth=NONE;」の指定の元、追加プロパティはAccess Tokenだけでも構いません。
import cdata.office365 as mod
conn = mod.connect("InitiateOAuth=NONE;OAuthAccessToken=(取得したAcces Token);")
もちろん、この状態では以下のようにOAuthSettingsLocationのファイルは生成されません。
RefreshTokenの更新を忘れないように、かつAccess Tokenなどのデータをセキュアに管理することに注意すれば、このようにCData Driverを利用することも可能です。
このパターンではAccess Tokenの取得・Refresh処理などをCData Driverを使わずに実装しても構いません。
おわりに
というわけで、CData Driverを使ったOAuthのハンドリング方法を解説してきました。
かなり細かくチューニングできることが、この記事でイメージいただけたのではないかなと思います。
とはいえ、Access Token・Refresh Tokenの管理はなかなか手間ですので、Authorization Code 取得までパターンが一番手軽ではないかなと思います。
あとは、OAuthSettingsLocationのファイルをどのように管理するか?によって、アプローチを住み分ける形かなと思います。
OAuthSettingsLocationのファイルは例えば顧客名毎で振り分けることも可能なので、そういった点も意識しながら、組み込みを検討されるのが良いかと思います。
また、試していて気になる点、よくわからない点があれば、お気軽にテクニカルサポートまでお問い合わせください。
https://www.cdata.com/jp/support/submit.aspx
関連コンテンツ