新しいことにはウェルカム

技術 | 電子工作 | ガジェット | ゲーム のメモ書き

Azure Active Directoryのシングルサインオン(SSO)で、アプリにログインできない時の対処方法

シングルサインオン(SSO)サービスに興味があって、一時期色々サービスを試していました。

www.kwbtblog.com

Office365のユーザーをキーとしてログインしたかったので、結局Azure Active DirectoryのSSOを使うことにしました。用途としては、主にTableauのログインに使っています。

問題発生

設定してから1ヶ月ほど経ったころに、Tableauにログインできなくなることがチラホラ起こるようになりました。

具体的には、Tableauのログインページからログインしようとしても、すぐに元のTableauのログインページに戻ってログインができません。

色々試したところ、一度Office365をログアウトして、再度Office365にログインすると直りました。

Tableauに問い合わせ

いかにも他でも起こっていそうな事象だったので、TableauにWebで問い合わせると、すぐに電話がかかってきて、下記の記事を教えて頂きました。早い!

原因

Office365にログインすると、トークンが発行され、そのトークンはブラウザに保存されて再利用され、次回以降のログインが不要になります。

しかし、トークンが永久に使えるとセキュリティー的に問題があるため、トークンには有効期限が決まっていて、有効期限が切れた場合は再度ログインして、トークンを新しく取得し直します。

今回Tableauにログインできなくなったのは、Tableauのトークンの有効期限が、Azure Active Directory の有効期限より短かったためでした。

Azure Active Directoryではまだ期限が切れておらず有効なトークンなのに、Tableauでは期限切れとなっているため無効なトークンとして弾かれ、ログインできなくなっていました。

Azure Active Directoryのトークンの有効期限は90日、一方Tableauの有効期限は24日なため、丁度SSOを使い始めてからログインできない現象が起こり始めた時期と一致します。

対処方法

Azure Active Directoryでは、SSOしたいアプリ毎にトークンの有効期限を設定できるので、その有効期限をTableauと同じ24日に設定することにより、Tableuの有効期限が切れた時に再ログインが発生して、 トークンが更新されるようにします。

設定方法は、サポートで教えて頂いた記事の中にもリンクがあるのですが、下記のマイクロソフトのドキュメントを参考にしました。

docs.microsoft.com

ここでは、自分がハマった点も踏まえて、ザックリやり方を記します。

準備

PowerShellモジュールのインストール

残念なことに、トークンの有効期限の設定はAzureポータル上では行えず、PowerShellのAzure ADモジュールを使ってコマンドで設定します。

なので、まず最初に、「Azure AD PowerShellモジュール」をインストールします。

Azure Active Directoryへ接続

次に、PowerShellからAzure Active Directoryに接続します。その時、接続先Azure Active Directoryとして、テナントIDを指定して接続します。

PS> Connect-AzureAD -TenantId xxxx

テナントIDは、Azure Active Directoryのポータルから[プロパティ]-[ディレクトリID]で確認できます。

これでAzure Active Directoryに対してコマンドが発行できるようになります。

構成

具体的な手順に進む前に、Azure Active Directoyの用語と構成について簡単に説明します。

アプリケーションとサービスプリンシパル

同じサービスに対するSSOでも、複数のアプリを作成して、個別に設定することができます。

例えばTableauの場合、複数のサイトが持てるので、サイト毎にアプリを追加して、追加したアプリ個々に対して設定をします。

このTableauなどといった、大本の雛形になるサービスのことを「アプリケーション」とよび、個々に作成したアプリのことを「サービスプリンシパル」と呼びます。

そして、トークンの有期限は、「アプリケーション」ではなく、追加したアプリ、つまり「サービスプリンシパル」に対して行います。

ポリシー

サービスプリンシパルに直接トークンの有効期限の設定をすることはできません。

代わりに、トークンの有効期限を定義したポリシーを作成し、 そのポリシーを、設定したい「サービスプリンシパル」に割り当てることにより、サービスプリンシパルのトークンの有効期限を設定します。

手順

ポリシー作成

JSONで有効期限の値(今回は24日間)を設定し、New-AzureADPolicyでポリシーを作成します。

create_policy.ps1

$policy_json = @('{
    "TokenLifetimePolicy":{
        "Version":1,
        "MaxInactiveTime":"24.00:00:00",
        "MaxAgeSingleFactor":"24.00:00:00",
        "MaxAgeMultiFactor":"24.00:00:00",
        "MaxAgeSessionSingleFactor":"24.00:00:00",
        "MaxAgeSessionMultiFactor":"24.00:00:00"
    }
}')

$policy_name = 'TableauOnlinePolicy'

New-AzureADPolicy `
    -Definition $policy_json `
    -DisplayName $policy_name `
    -IsOrganizationDefault $false `
    -Type "TokenLifetimePolicy"

スクリプトを書いて実行します。

PS> .\create_policy.ps1

ポリシー割り当て

作成したポリシーをAdd-AzureADServicePrincipalPolicyで、サービスプリンシパルに割り当てます。

ポリシーとサービスプリンシパルはIDで指定する必要があるので、それぞれ名前からオブジェクトを取得して、そのオブジェクトからIDを取り出しています。

attach_policy.ps1

$policy_name = 'TableauOnlinePolicy'

$policy = Get-AzureADPolicy | Where-Object { $_.DisplayName -eq $policy_name }

$sp = Get-AzureADServicePrincipal | Where-Object { $_.DisplayName -eq "Tableau Online" }

Add-AzureADServicePrincipalPolicy -Id $sp.ObjectId -RefObjectId $policy.Id

以上で、アプリ、つまりサービスプリンシパルに有効期限が設定できます。

確認

念の為、ポリシーが作成されて、サービスプリンシパルに割り当てられているか確認します。

check.ps1

$policy_name = 'TableauOnlinePolicy'

$policy = Get-AzureADPolicy | Where-Object { $_.DisplayName -eq $policy_name }
Write-Host $policy

$sp = Get-AzureADServicePrincipal | Where-Object { $_.DisplayName -eq "Tableau Online" }
Write-Host $sp

$sp_policy = Get-AzureADServicePrincipalPolicy -Id $sp.ObjectId
Write-Host $sp_policy

Write-Host $sp_policy.Definition

ポリシー削除

参考までに、サービスプリンシパルのポリシー割り当ての解除と、ポリシー削除方法を記載します。

detach_policy.ps1

$policy_name = 'TableauOnlinePolicy'

$policy = Get-AzureADPolicy | Where-Object { $_.DisplayName -eq $policy_name }

$sp = Get-AzureADServicePrincipal | Where-Object { $_.DisplayName -eq "Tableau Online" }

Remove-AzureADServicePrincipalPolicy -PolicyId $policy.Id -Id $sp.ObjectId

delete_policy.ps1

$policy_name = 'TableauOnlinePolicy'

$policy = Get-AzureADPolicy | Where-Object { $_.DisplayName -eq $policy_name }

Remove-AzureADPolicy -Id ($policy).Id

感想など

SSOのアプリを追加した時に、サービスに合わせて有効期限をよしなに自動設定されているものかと思っていたのですが、そうじゃないんですね。

でも、どんなアプリでもデフォルトの有効期限が90日固定になってしまう仕様だと、Tableau以外のサービスでもログインできなくなるエラーが頻発しそうですが大丈夫なんでしょうかね?

試しにいくつか他のアプリも追加してみたのですが、どれもアプリに適したポリシーの割り当てはされてなさげでした。

Azure CLIではなく、PowerShellで設定するところが、突貫かつ、マイクロソフト的には本当は触って欲しくないけど致し方なく公開しているような雰囲気が漂っていて…。

追々アプリ毎にポリシーが自動で割り当てられて、Azureポータル上で細かい設定ができるようになりそうな雰囲気がしています。