Okta Workflows(以下、Workflows)とアプリケーションのAPIを利用すると、作業の自動化を実現したり、アプリ単体では提供されていない処理を独自に実現することができます。
「Oktaに対するユーザー登録に承認機能を付加する仕組み」を作成してみましたので、この記事ではその内容をご紹介します。

想定される利用シーン

通常、Oktaへの社員の登録は管理者が直接登録したり、人事情報などのID源泉から同期することで行われます。一方、協力会社や契約社員などの役割のユーザーが多数いる環境では、申請・承認フロー付きのユーザー登録が必要とされるケースがあります。

利用するもの

今回は、以下のものを利用して申請フロー付きユーザー作成を実現します。

1.  Google Forms
アンケートを取る際などによく利用される、グーグルの提供するフォームアプリです。今回はこれをユーザー登録の申請画面として利用します。フォームに入力された内容をAPIでOktaに送信するというシンプルな役割を担います。類似のアプリでも自己開発で用意しても構いません。要件に合わせたものを利用することができます。

2. Okta Identity Governance(以下OIG)
OIGの機能の一部であり申請/承認のフローを提供するアクセスリクエストを利用します。この機能の本来の目的はOktaに登録済みのユーザーが、Oktaで管理されているアプリや権限などを申請し、割り当てを受けることです。この機能にも申請入力画面はありますが、Oktaに登録済みのユーザー向けであるためユーザーの新規登録には利用できません。Google Formsを申請画面として利用したのは、このためです。

3. Okta Workflows
上記2つの連携と、今回の目的であるOktaへのユーザー登録を担います。Google Formsに入力された情報をWorkflowsが受け取り、アクセスリクエストの申請を作成します。そして、申請が承認された後ユーザーの登録作業を行うなどの部分をWorkflowsで実装します。

仕組みの解説

仕組みは以下の図のようになっています。

1. Google Formsで作成したユーザーの新規登録画面にユーザーが必要事項を入力します。 2. Google Apps Scriptを利用して、フォームに入力された内容をOkta Workflowsに送信
3. Workflowsは受け取った情報を利用し、OIGに対して申請を行います。
4. OIGの申請フローで指定された承認者が承認を行います。
5. 承認された場合のみ、WorkflowsによってOktaのユーザーが新規作成されます。
6. Okta から申請者宛にアクティベーションのメールが送信され、完了後に利用可能になります。

作成ステップ1 - Google Forms

それでは順番に作成していきたいと思います。まずは、フォームの作成です。Oktaのユーザー登録には、姓(Lastname), 名(Firstname), メールアドレスが最低限必要となりますので、フォームの入力項目として作成します。これに加えて、承認者の判断に必要な情報や、Oktaの属性として登録しておきたい情報を任意に追加することもできます。今回は会社名を追加しました。

 

フォームはこれで完成です。ここでフォームを公開状態にして登録希望者が利用できるようにしますが、このフォームのURLさえわかれば理論上、誰でもアクセスできることを懸念されるかも知れません。

以下は付録情報になりますが、この対策としてユーザー登録情報の入力に先立ち簡易的な
パスワード認証相当の仕組みを設定することができます。

それにはまず、下図のようにセクションを2つにわけセクション1でパスワード(パスワードと混同するなどの問題回避のため名称を認証コードとしました)の入力を”記述式(短文)”タイプで作成します。また、”必須” に設定しておきます。そして、縦に3つ並んだアイコンをクリックすると出るメニューから”回答の検証”をクリックし、入力内容のチェックを追加します。この検証には、”正規表現” かつ ”一致する” を指定して、^と$の間にパスワードにしたい文字列を入力します。(図ではOkta123)この表現は文字列との完全一致を意味しますので、これがパスワードとして働くという仕組みです。

 

作成ステップ2 - Google Apps Script

次は、Google Forms に入力された内容をWorkflowsに送るためのApps Scriptの作成です。まずは、フォームに入力された内容を取得し、その内容をHTTP POSTメソッドで送信するスクリプトを作成します。以下は、動作確認済みのサンプルです。Apps Script へはフォーム作成画面の右上の点が縦に3つ並んだアイコンをクリックするとアクセスできます。

function submitRequest(e) {

 // 設定

 const apiUrl = "YOUR_API_ENDPOINT_HERE"; // APIエンドポイントのURL


 // フォームの回答を取得

 const formResponses = e.response.getItemResponses();

 let formData = {};


 // 各回答を対応する質問のタイトルと紐付ける 

 formResponses.forEach(response => {

     formData[response.getItem().getTitle()] = response.getResponse();

 });


 // 必要なデータを抽出して変数名を変換

 const payload = {

     email: formData['メールアドレス'],

     lastname: formData['姓'],

     firstname: formData['名'],

     company: formData['会社名'] };


 // APIエンドポイントにデータを送信

 try {

     const options = {

         'method': 'post',

         'contentType': 'application/json',

         'payload': JSON.stringify(payload)

     };

     const response = UrlFetchApp.fetch(apiUrl, options);

     Logger.log("API Response: " + response.getContentText());

 } catch (error) {

     Logger.log("API Error: " + error);

 }

}


フォームへの入力内容を、YOUR_API_ENDPOINT_HERE 部分に入力したURLに送る単純なものですが、そのままだとフォームの入力項目タイトルが変数の値として日本語のまま使われるので(Workflowsはそのままでも対応できますが)、プログラムらしく4つの名称をそれぞれ email, lastname, firstname, company に置き換えてから送るようにしてあります。

Code.gs の内容を上記のスクリプトに差し替えて、フロッピーマークを押して保存します。

そして、フォームが提出された時にこのスクリプトが動作するように設定します。左のメニューから目覚まし時計マークのメニュー「トリガー」をクリックします。「トリガーを追加」を押し、画像のメニューがでたら、「実行する関数を選択」には submitRequest、「イベントのソース」は フォームから、「イベントの種類」は フォーム送信時を指定し保存します。これでフォームの送信時にスクリプト submitRequest が自動で動作し、入力内容をWorkflowsに送る準備ができました。

※ステップ3で、スクリプトのYOUR_API_ENDPOINT_HEREの部分を Workflows の API エンドポイントURLに差し向けるように修正します。

作成ステップ3 - Workflows 試作

本格的な実装の前に、Apps Scriptの設定を終わらせるため、そしてWorkflowsが正しく情報を受け取れるかの確認のために、まずはWorkflowsでデータを受け取る部分だけを作成します。

新しいフローを追加し、イベントカードで API Endpoint を選択します。設定ダイアログが表示されたら「Secure with client token」を選択しクローズします。続いてこのイベントカードのbodyのセクションに、フォームから受け取る情報の変数を作成します。変数名は、ステップ2で作成したApp Scriptの「// 必要なデータを抽出して変数名を変換」部分にある変数名になります。したがって、下図のように email、lastname、firstname、company を作成します。この他にフォームに入力する情報を追加をした場合は、Apps Script とこのイベントカードの変数も同じように追加が必要です。

ここまで完了したら、Save ボタンでフローを保存します。名称は適宜つけてください。保存が完了したら、フロー有効化とログの保存の2つのラジオボタンを有効化し作成は完了です。

保存後、イベントカードの下にある </> マークをクリックして、Invoke URL をコピーします。これが、Workflows が外部アプリからAPIでデータを受け取るためのURLです。Apps Scriptの編集画面に戻り、YOUR_API_ENDPOINT_HEREの部分をこのURLで置き換えてください。フロッピーマークを押して更新内容を保存するのをお忘れなく。

さて、ここまでの作業の結果を確認します。Google Formsで作成したフォーム作成画面で、公開ボタンを押します。回答者ビューに 「リンクを知っている全員」を選んで「公開」をクリックすれば公開完了です。色が変わった「公開」ボタンを押し、回答用のリンクを表示します。URLが表示されたら、「コピー」を押してURLをコピーします。これが、登録者に案内するURLです。

別のタブやブラウザでこのURLにアクセスし必要事項の入力が完了したら、送信をクリックしてフォームを提出します。ここで、Workflows の実行履歴を確認してください。body の部分にフォームの内容が入っていれば成功です。データを受け取ることができました。このフローは後ほど中身を作っていきますが、OIGの設定を先に行う必要があるので一旦このままおいておきます。

※認証コードが一緒に送られていますが、Apps Script をカスタマイズして含めないようにすることも可能です。

作成ステップ4 - ユーザー作成用Workflows 作成

実際の処理とは順番が前後しますが、最終的な処理であるユーザー作成を行うWorkflowsを先に作成しておきます。次のステップ5の設定でこのフローを指定する必要があるからです。

先ほどとは別のフローになりますので、まずは新しいフローを作成します。イベントカードにはDelegeted flowを指定します。そして、ステップ3で作成したフローと全く同じように変数を追加します。次に、アクションカードで Okta の Create User を配置します。Input 項目にはグレーアウト表示されているデフォルト項目に加えて、必要なものを選択します。今回はステップ1のGoogle Forms で会社名を入力するようにしていますので、その情報を保存する属性としてOrganizationを選択しました。

次にイベントカードの変数を使って、Create User の変数部分を埋めていきます。Username と Primary email には email、 First name には firstname、Last name には lastname とし、Organization には company をドラッグアンドドロップで配置します。
Activate はユーザーを作成後すぐにアクティブにするかを決める項目です。ここでは True としました。

このフローはこれで完了です。ステップ3と同様にセーブと有効化を行っておきます。 

作成ステップ5 - アクセスリクエスト

このステップではアクセスリクエストからWorkflowsを呼び出すための設定が必要になります。こちらのページの ”Oktaでのロールとリソースの構成” の手順で、ステップ4で作成したフローが実行できるように設定してください。

また、”Okta Access Requestsの構成” が未設定の場合は設定が必要です。
※このステップで作成するRequest Typeを管理するTeamに対して、フロー実行権の割り当てが必要です。もしTeamを別途作りたい場合は予め作成してから行って下さい。

では承認フローを担うアクセスリクエストを設定します。承認フローはリクエストタイプとリソースカタログという2種類の仕組みがありますが、前者を利用します。Okta管理者としてダッシュボードから「Okta Access Requests」アプリにアクセスしたら、メニューから Request Types を展開、Team を選んで Create Request Type ボタンから作成を開始します。

まずはGoogle Formsで作成した入力項目と同じ入力項目(Question)を作成します。フォームでは4つの項目を作りましたので、図のようにこちらも4つの項目になっています。

 

続けて、承認(Approval)を追加します。適当な文章を入力し、承認者を指定します。承認者は自由に設定してください。

最後はWorkflowsを実行(Action>Run a workflows)を追加します。こちらも適当な文章を入力し、実行するフロー(Select the workflow)としてステップ4で作成したフロー(この例ではCreate an  Okta User)を指定します。フローを選択すると、フローが受け取ることのできる変数が表示されるので、それぞれにQuestionで作った項目をマッピングします。

最後にこのWorkflowsが申請が承認された場合のみ実行するように設定します。Logic のタブをクリックし、”Only show this task if(このタスクに進む条件)” を選択、承認(さきほどApprovalを追加した時に入力したテキストが名称になっています) をおよび、is approved を選択します。

あとはセーブすれば完了です。まだこの画面は残したまま次のステップを別のブラウザタブなどで開いてください。

作成ステップ6 - Workflows に必要な収集

まずは、ステップ5で作成した申請をWorkflowsから利用するために、必要な情報を収集しておきます。必要な情報は3種類です。

1つめはRequest Typeの入力項目(Questions)のIDです。これは少し変わった手順で調査する必要があります。ステップ5のRequest Type編集画面を表示し、ブラウザの開発者ツールを開きます。エレメントを選択するマークをクリックし、一つめのQuestionを選択します。この時、Question の中身のエレメントではなく四角全体が指定される場所をクリックします。すると、開発者ツールの画面で選択した場所に対応したhtml部分の色が変化するので、そこに注目します。このなかで、id=”node-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx” となっているところがIDです。APIではこのうち node- 部分を除いた部分を利用しますので、この部分をメモしておきます。

この作業を繰り返し、4つのQuestion全てのIDを控えておきます。どのIDがどのQuestionのものかわかるようにしておいてください。

2つめは、このRequest Type自体のIDです。ブラウザのURLの部分に表示されているhttps://<subdomain>.okta.com/next/request-types/yyyyyyyyyyyyyyyyyyyyyyyy/edit のうちyで示した部分がIDになっているため、これも同じく控えておきます。

最後に、申請を行うユーザーのOkta IDが必要となるためこれを取得します。といっても、このシナリオはユーザー登録であるため申請者自体は申請時点でOkta上に存在しません。そこで、アクセスリクエストを利用できるユーザーが代理で申請する形式をとる必要があります。APIで申請を作るためのシステムユーザーを作って使うなどするのも一案です。

とりあえずのところは、この Request Type の作成者となっているご自身のアカウントでも良いでしょう。Okta の管理コンソール(Okta Admin Console)にアクセスし、ディレクトリ>ユーザーから対象のアカウントを表示したあと、URLの最後の部分(以下zの部分)が必要なIDです。https://<subdomain>.okta.com/admin/user/profile/view/zzzzzzzzzzzzzzzzzzzz

情報の収集は以上で完了です。次はいよいよWorkflowsを仕上げる最後のステップです。

作成ステップ7 - Workflows の仕上げ

ステップ3で作りかけになっていたフローを仕上げていきます。このフローの役割は、Google Forms からデータを受け取り、それを利用してステップ5で作成したRequest Typeの申請を提出することです。

まず最初に、Object - Construct カードを配置します。Click or drop here to crateと書かれている部分をクリックすると名称の変更、名称をidに変更します(初期値はinput 1)。この変更を確定するともう一つ項目がグレー表示されるため、同じ要領で名称をvalueに変更します。

同じカードを4つ配置し(カードの下部にある複製ボタンを使うと便利です)、それぞれにステップ6で最初に調べた4つのQuestionのIDを入力します。その後、ステップ3でイベントカードに設定しておいた変数 email, lastname, firstname, company をドラッグアンドドロップで value の部分に配置します。Questionの内容とマッチするように紐づけてください。IDを控える際にどのQuestionのものか分かるようにしておいたのはこのためです。

次に List - Constrct カードを配置します。4つのObject - Construct の Outputを一つづつドラッグアンドドロップで配置します。

続いて、新たな Object - Construct カードを配置します。requestTypeId という名称の項目を作り、ステップ6の2番目に調査したRequest Type の ID を入力します。続いて、subject という名称の項目を作って任意の名称を入力します。これは申請の題名となりますので ”ユーザー登録申請” など分かりやすい名称にすると良いでしょう。図のように変数の値を使って題名を工夫することもできます。


続いて、requesterFieldValues という値を作り直前で作った List - Construct カードの結果である list をドラッグアンドドロップで配置します。最後にrequesterUserIdsという項目を作り、データの形式をリストに変更します。入力項目右上の Aa となっているところをクリックし、List にチェックをいれることで変更可能です。ここには、ステップ6で調査した申請者のユーザーIDを入力します。リスト形式に設定したため、複数情報が入力できる表示(+ click to add item)になっていますが、ここでは先ほどの1ユーザーのIDだけでOKです。

さて、なぜこのようなObjectを作ったかというと、アクセスリクエストの申請を行うAPIがこの形式をインプットとして必要としているからです。つまり、APIのドキュメントの要求通りにデータを成形したというわけです。

最後に、Okta - Custom API Action のカードを配置します。上記のAPIドキュメントに従って、Reqeust Type は POST を指定します。次に表示される Input / Output の表示項目設定で、Input の Body を追加するのを忘れないようにします。
Relative URL に /governance/api/v1/requests を入力、そしてBodyには先ほど作ったデータつまり直前のObject - Construct の Output をドラッグアンドドロップで配置します。

これでフロー全体は以下の図の通りとなり、完成です。セーブをお忘れなく。

完成

これで完成です。以下の手順で動かしてみてください。
1. Google Form の利用者URLへアクセスし必要事項を入力し提出
2. アクセスリクエストで承認者に指定しておいたアカウントでOktaにログイン
3. Okta Access Request アプリを開き、申請を確認後承認
4. Okta の管理コンソールにアクセスしてユーザーが作成されたことを確認
5. (オプション)フォームに入力したアドレスのメールを確認してアクティベーション

うまく行きましたでしょうか?問題がある場合は流れを追って原因を探します。

トラブルシュート

ここでは主要な確認すべきポイントを順を追って挙げていきます。

・Google Forms が正しく動かない
Apps Script が正しく動作しているか確認します。Apps Script を開き、左のメニューの下から2番目の「実行数」を開きます。実行結果が表示され、ステータスで問題の有無を確認できます。”完了”となっていればひとまず問題ありませんが、”失敗しました” になっていた場合はその実行結果をクリックしてログを確認します。スクリプトに誤りがある場合などはこれを頼りに修正が必要ですが、Exception: You do not have permission to call FormApp.getActiveForm のエラーがでている場合は、下にあるClick here to provide permission をクリックして認証を行い権限を付与して解決します。

・申請処理の Workflows に問題がある
フローの Flow History を表示して、問題箇所を特定します。フォームに入力したデータが正しく成形され、最後の Custom API Action に渡されているか確認します。
Custom API Action で 400 Bad Request などのエラーが発生している場合、エラーの詳細を表示しBodyの部分をクリックして展開すると errorSummary: が表示されますので、これを頼りに正しく設定ができていない箇所を特定します。

これが 403 Forbidden エラーの場合は、エラーの header を開きます。error="insufficient_scope" となっている場合、このAPIを利用するための権限設定が不足しています。以下の手順で修正してください。

1. 管理コンソール(Admin Console)で、Okta Workflows OAuth アプリを開く
2. Okta API のスコープを表示し、okta.governance.accessRequests.manage を付与
3. Workflows の Connections を表示し、Okta のコネクターで Reauthorize(右から2つ目の丸まった矢印アイコン)を開始
4. Client ID、 Client Secret、 Domain を入力して Reauthorize。このうち最初の2つは管理コンソールの、Okta Workflows OAuth アプリのサインオンタブの中で確認できます。

・承認要求が送られてこない
作成したRequest Typeを有効化し忘れていないか確認してください。また、申請処理のWorkflows でRequesterUserIdsに入力したユーザーがこのRequest Typeを利用できる設定になっているか確認してください。Oktaの管理コンソールでOkta Access Request アプリが割り当てられていること、そしてRequest TypeのAudienceに入っている必要があります。

・ユーザー作成Workflowsに問題がある
Flow History を表示して、問題箇所を特定します。といってもとても単純なフローなため問題があるとすれば、正しく値が与えられていないことぐらいのはずです。Username と Primary email はメールアドレス形式でなくてはなりません。ここに問題がある場合はGoogle Formへの入力時に正しい形式入力を入力してください。また、Google Formsでは入力項目をメールアドレス形式に限定する設定も可能ですので、これを利用するとこのような問題の発生は予め防ぐことができます。

おわりに

「Oktaに対するユーザー登録に承認機能を付加する仕組み」を実現してみました。日常的に新たなアプリや権限を要求する際に利用することになるOktaのアクセスリクエストで承認を行うことで、承認者にとって分かりやすい体験になっていると思います。