Okta - OAuth2.0 Device Authorization Grantの設定とサンプル実装
はじめに
これは、Okta Advent Calendar 2021の記事です。
本記事では、Oktaのデバイスフロー(RFC 8628 OAuth 2.0 Device Authorization Grant)の設定方法および、デバイスフローを利用したSSH接続のサンプル実装について解説します。
デバイスフローはWebブラウザ非搭載のデバイスや、文字入力が困難なデバイスがクライアントとなる場合に、ユーザーの承認に基づいてアクセストークンを発行するための認可フローです。
デバイスフロー自体は比較的新しい仕様ですが、Okta以外にも実装している認可サーバーは複数存在します。
また、デバイスフローを解説している記事も複数あるため、デバイスフロー自体の解説はそちらをご覧ください。
例えば、日本語で全体感も含めてわかりやすく解説されている記事として以下のようなものがあります。
デバイスフローの設定
本記事では以下のガイドをもとに設定を進めていきます。詳細については以下の記事をご参照ください。
事前準備
事前準備として、Oktaの Developerアカウントを用意し、Settings > Features
からOAuth 2.0 Device Authorization Grant
を有効にします。
なお、今回の記事の内容はフリーのアカウントで試すことができます。
アプリケーションの設定
Applications > Applications
からOpenID Connectのアプリケーションとしてデバイスフローの設定を進めていきます。
Create App Integration
からOIDC
とNative Application
をそれぞれ選択します。
つづいて、作成したOIDCのNative Applicationの設定から、Grant TypeとしてDevice Authorization
を選択しておきます。
これで、アプリケーションがデバイスフローを利用できるようになりました。
認可サーバーのポリシー変更
このままだと、認可サーバーのエンドポイントにアクセスできるようになっていないので、ポリシーを変更しておきます。
ここでは、Security > API
から"default"のカスタム認可サーバーのポリシーを変更しています。
ポリシーの変更画面においてDevice Authorization
にチェックを入れておきます。
これで、認可サーバーのエンドポイントにもアクセスできるようになりました。
スマートデバイスの設定
ここまでの設定でデバイスフローが利用できるようになっているので動作確認してみます。
device verification codeのリクエスト
まず、/device/authorize
にアクセスし、verification codeを入手します。
curl --request POST \
--url https://${yourOktaDomain}/oauth2/default/v1/device/authorize \
--header 'Accept: application/json' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=${clientId}' \
--data-urlencode 'scope=openid profile offline_access' | jq
{
"device_code": "4ebdb4de-1f8b-4497-be01-ddfaf83c4e9c",
"user_code": "MHXTFRPK",
"verification_uri": "https://${yourOktaDomain}/activate",
"verification_uri_complete": "https://${yourOktaDomain}/activate?user_code=MHXTFRPK",
"expires_in": 600,
"interval": 5
}
(※レスポンスのパラメーターはRequest the device verification codeから引用)
レスポンスに含まれるverification_uri_complete
のURLにアクセスすると、Oktaのログイン画面に遷移し、ログインすることでデバイスがアクティベートされ、次のステップに進むことができます。
アクセストークン、IDトークン、リフレッシュトークンのリクエスト
上記の手順を実施すると、スマートデバイスは認可サーバーのトークンエンドポイントから各種トークンを取得できるようになります。
以下は、実際に各トークンを取得するためのリクエストになります。
curl --request POST \
--url https://${yourOktaDomain}/oauth2/default/v1/token \
--header 'Accept: application/json' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=${clientId}' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:device_code' \
--data-urlencode 'device_code=${deviceCode}' | jq
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJ ... ",
"scope": "offline_access openid profile",
"id_token": "eyJ ... "
}
これで、Webブラウザ非搭載のデバイス相当がユーザーの承認にもとづいてアクセストークンを取得することができました。
おまけ: Device Authorization Grantを利用したSSH接続
Okta DeveloperというOktaを利用した際のサンプル実装などが配置されるGitHub Organizationに今回紹介したデバイスフローを利用してSSHを可能にするサンプル実装が用意されています。
このサンプル実装はSSH接続をする際に、ID/PWや公開鍵による認証ではなく、デバイスフローを利用して、Oktaで承認したうえで接続するというものになっています。
上記のリポジトリにはDockerfileも用意されており、クライアントIDやOktaのドメインなどを自身のものに置き換えるだけで簡単に動作を試すことができます。
また、一部手順を簡略化したものも用意しているので、単純にDockerで試したいだけであればこちらも利用していただければと思います。
手順通りコンテナを起動し、コンパイルしたPAMモジュールを利用することで、デバイスフローでSSH接続できるようになります。
$ git clone https://github.com/kg0r0/okta-ssh-oauth-example.git
$ cd okta-ssh-oauth-example
$ git checkout feat-dockerfile
$ docker build -t ubuntuwithdeviceflowssh .
$ docker run -d -it -p 1022:22 ubuntuwithdeviceflowssh
$ ssh test@localhost -p 1022
実際にSSHすると、以下のようにhttps://${yourOktaDomain}/activate
にアクセスするよう促されます。
(引用元: https://github.com/oktadev/okta-ssh-oauth-example)
上記の指定のURLにアクセスするとOktaアカウントのログインを要求されるので、ログインした後に、SSH接続開始時に表示されているコードを入力することでSSH接続を完了します。
Discussion