#はじめに
WebAPIの利用する際にWebAPIのアクセスに対するセキュリティを担保するために、アクセストークンを利用します。本ドキュメントでは、アクセストークンが必要なWebAPIにアクセスするために必要なアクセストークンをAADより入手する方法と、WebAPIにアクセストークンをセットして呼び出す方法に関して記述しています。
#アクセストークンの取得
アクセストークンをAAD(Azure Active Directory)より取得します。PowerShellで通常はバッチ処理などを作成すると思います。普通のアプリケーションの場合、ユーザーの認証をAADで行い、そのユーザーのアクセストークンを利用して各種リソースにアクセスしています。PowerShellのバッチの場合、このユーザーが存在しません。このため、PowerShellの場合、AADのアプリケーションを作成してもらい、そのアプリケーションのアプリケーションIDとシークレットキー(パスワードみたいなもの)をつかって、アクセストークンを利用して、リソースアプリケーション(WebAPIを提供するアプリケーション)にアクセスを行います。
このため、PowerShellからアクセスを行う場合、あらかじめ下記の情報を管理者より入手しておきます。
表1-1 事前に入手する情報
項目 | 内容 | 備考 |
---|---|---|
テナントID | 認証を行うテナントIDです。今回は、シングルテナントを想定しています。 | |
アプリケーションID | PowerShellがアクセストークンを取得するために作成したアプリケーションのID | |
シークレットキー | パスワードみたいなもの | |
スコープID | 利用するリソースアプリケーションのスコープIDを取得します。※1 |
※1 アプリケーションを作成する際に、利用するリソースアプリケーションのスコープ、アプリケーションロールに作成したアプリケーション「API許可」を行っておく必要があります。APIの許可と必要な場合、管理者の承認を実施しておいてもらいます。
##アクセストークンの入手
#アクセストークンを取得するURLを入力します。
$path = "https://login.microsoftonline.com/{TenantId}/oauth2/token"
#ヘッタの情報(これは固定値)
$contentType = 'application/x-www-form-urlencoded'
#Bodyの情報を作ります。
$body = @{grant_type='client_credentials'
scope='{スコープ名}/.default'
client_id='クライアントID'
client_secret='シークレットキー'
}
アクセストークンを取得するためにRestAPIを呼び出します。
#アクセストークンの取得(RestAPIを呼び出します。)
$Result = Invoke-WebRequest -Method POST -Uri $path -body $body -ContentType $contentType
アクセス結果よりトークンを取り出します。
#アクセストークンの取り出し
$Content = ConvertFrom-Json $Result.Content
$AccessToken = $Content.access_token
アクセストークンは、Base64でコンバートされたJSONデーターです。このため、取得したクライアント側でも内容を見ることができます。(Ver2のトークン)
取得したアクセストークンは、下記URLで見ることができます。
https://jwt.ms/
##WebAPIの呼び出し
取得したアクセストークンを利用して、WebAPIを呼び出します。 APIを呼び出すためには、APIのインタフェース仕様書が必要です。
今回は、テスト用に動作させている、ローカルマシンにアクセスしています。
#アクセスするアプリケーションのURLを入力
$apiurl = "https://localhost:44363/api/Values"
#アクセストークンを設定します。
$header = @{
"Authorization" = "Bearer $AccessToken"
"Content-Type" = "application/json"
}
WebAPIを呼び出します。
#APIを呼び出します。
$Response = Invoke-WebRequest -Method Get -Uri $apiurl -Headers $header
今回は、Getアクセスなので、URIにパラメーター等が設定します。
もし、アクセストークンの有効期限などが切れている場合、Invoke-WebRequestコマンドは、エラーを出します。エラーが発生した場合、$Responseに値は、入りません。
#PowerShellのエラーメッセージ
PS C:\work> $Response = Invoke-WebRequest -Method Get -Uri $apiurl -Headers $header
Invoke-WebRequest : {"Message":"この要求に対して承認が拒否されました。"}
発生場所 行:1 文字:13
+ $Response = Invoke-WebRequest -Method Get -Uri $apiurl -Headers $head ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest]、WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
##実際の利用時の注意
通常のPowerShellの場合、1時間も2時間も処理をすることは少ないと思います。上記で取得したベアラートークンは、発行から1時間で有効期限が切れます。このため、長い処理を行う可能性がある場合、トークンの時間切れに対応する必要があります。
しかしながら、WebAPIを呼び出すたびにアクセストークンを取得するコードは、お勧めしません。
だめな例
$oDataAllay | % {
#アクセストークンの取得
#WebAPIの呼び出し
}
このように、呼び出すたびにアクセストークンを取得するコードは、自身のパフォーマンスとAADへの負荷を考えると適切ではありません。
少なくともこのような処理の場合、ループの外側で1回アクセストークンを取得するべきです。
そこで、以下に取得したアクセストークンから、アクセストークンの有効期限(切れる日付)を取得する方法を記載します。
$BreakToken = $AccessToken.Split(".")
$byte = [System.Convert]::FromBase64String($BreakToken[1])
$Tokenpayroad = ConvertFrom-Json([System.Text.Encoding]::Default.GetString($byte))
#expDay Get
$Secound = $Tokenpayroad.exp
$ExpDate = ([datetime]"1970/1/1").AddSeconds($Secound)
上記コードで、$ExpDateにこのアクセストークンの有効期限を取得することができます。注意事項として、このアクセストークンの有効期限は、UTC時間なので、動作しているマシンのタイムゾーンを意識するか、「(Get-Date).ToUniversalTime()」を利用して現在時間を取得してアクセストークンの有効期限を比較してください。