からめもぶろぐ。

俺たちは雰囲気で OAuth をやっている

ドクターイエロー運行予測 2.0.0 を公開しました

ドクターイエロー運行予測というサイトを公開していたのですが jQuery + Knockout.js で作っていたものを React で作り直しました。

preddy.karamem0.dev

基本的にはあまり変わっていないのですがベースの UI ライブラリに Fluent UI を使ったのでどことなく MIcrosoft Teams っぽいです。あとやっと React が書き慣れてきた感じがします。

Capreze 1.7.0 を公開しました

Capreze 1.7.0 を公開しました。
Capreze は画面キャプチャ用のウィンドウ リサイズ ツールです。ウィンドウを正確なサイズにリサイズしてくれます。

github.com

複数ディスプレイ環境における解像度の違いに対応しました。これまでは起動時に表示されるディスプレイの解像度にしたがってオフセットを計算していたのですが、ウィンドウを別のディスプレイに移動したときにオフセットが再計算されるようになりました。複数ディスプレイ環境でも正確にオフセットを考慮してウィンドウをリサイズしてくれます。

Azure AD アプリケーションの accessTokenAcceptedVersion を指定したときの JWT の aud の挙動について

Azure AD アプリケーションのアクセス トークンの中身について accessTokenAcceptedVersion を指定したときの JWT の aud の挙動に違いがあったのでメモです。

前提条件

サーバーとなる Azure AD アプリケーションを登録します。アプリケーション ID URL を「api://{{appid}}」のように作成して適当にスコープを追加します。

f:id:karamem0:20210730211844p:plain

この Azure AD アプリケーションへにアクセスするためのクライアントになる Azure AD アプリケーションを登録します。[API のアクセス許可] でサーバーのアプリケーションへのアクセス許可を追加します。

f:id:karamem0:20210730212242p:plain

これで準備は完了です。以下のようにリクエストを投げるとトークンを取得することができます。*1 scope に アプリケーション ID URL を指定するのがポイントです。

POST /6c4c0561-a8bb-4706-9cc9-3ba9b66aca3d/oauth2/v2.0/token
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

grant_type=password
&scope=api://fef0e665-3890-4797-bfe5-658589da1adb/.default
&client_id=a95306e4-14f1-4389-b0f5-24feb7f3c744
&client_secret=pFy5...
&username=someone@example.com
&password=Fzsr...

検証結果

まずは accessTokenAcceptedVersion が 1 または null の場合です。docs には null の場合は 1 になると書いてあるので同じと考えていいでしょう。

docs.microsoft.com

取得したトークンをデコードします。aud にはアプリケーション ID URL が入っているのがわかります。

{
  "aud": "api://fef0e665-3890-4797-bfe5-658589da1adb",
  "iss": "https://sts.windows.net/6c4c0561-a8bb-4706-9cc9-3ba9b66aca3d/",
  ...
  "ver": "1.0"
}

次に accessTokenAcceptedVersion を 2 にしてトークンを取得します。scope にアプリケーション ID URL を指定しているのですが、aud にはアプリケーション ID が入ります。

{
  "aud": "fef0e665-3890-4797-bfe5-658589da1adb",
  "iss": "https://login.microsoftonline.com/6c4c0561-a8bb-4706-9cc9-3ba9b66aca3d/v2.0",
  ...
  "ver": "2.0"
}

まとめ

何が困るかというと Azure Web App を作って自前で (Easy Auth じゃなくて) Azure AD 認証を適用したときに aud の値を検証するのですが、これが違って入ってくると割と困るんですよね。アプリケーション ID URL がくると思ってたらアプリケーション ID がくるので認証が通らなくてなんでだと悩むという。というか悩みました。いまのところ、一部を除きどちらのバージョンでも特に問題なさそうなので、特別な理由がなければ既定値の null のままでいい気がします。

*1:見やすさのために改行しています。

Capreze 1.6.0 を公開しました

Capreze 1.6.0 を公開しました。
Capreze は画面キャプチャ用のウィンドウ リサイズ ツールです。ウィンドウを正確なサイズにリサイズしてくれます。

github.com

設定ファイルまわりの挙動を変更しました。シリアル化に使用するライブラリを Newtonsoft.Json から System.Text.Json に変更しています。*1 あと設定ファイルの保存先が変更になっています。

*1:とはいっても Microsoft.AppCenter が Newtonsoft.Json に依存しているので配布パッケージには含まれるという。悲しみしかない。

PnP PowerShell を任意のアクセス許可で実行する

PnP PowerShell を最初に実行したときに Admin Consent を要求されるのですがアクセス許可の一覧がエグくてびっくりします。

f:id:karamem0:20210702123653p:plain

f:id:karamem0:20210702123807p:plain

さすがにこれは許可しづらいので、もうちょっとアクセス許可を制限した上で PnP PowerShell を使いたいです。方法はいくつかあります。

SharePoint アドインを使用する

アドインの登録方法をはじめ詳しい手順はこちらが詳しいです。

jpspsupport.github.io

クライアント ID とクライアント シークレットを使ってログインできます。

Connect-PnPOnline -Url https://{{tenantname}}.sharepoint.com -ClientId {{clientid}} -ClientId {{clientsecret}}

注意するべき点として、既定では使えないテナントがあるそうです。

2020 年夏頃以降に新規作成したテナントにおいて、アプリ専用トークンが既定で無効化されている場合があります。

Azure AD アプリケーションを使用する

委任されたアクセス許可

委任されたアクセス許可 (ユーザーとしてログイン) の場合、以下の方法が可能です。

Connect-PnPOnline -Url https://{{tenantname}}.sharepoint.com -Tenant {{tenantid}} -ClientId {{clientid}} -DeviceLogin

Tenant パラメーターはマルチテナント アプリケーションの場合は不要です。

注意するべき点として、Azure AD アプリケーションがパブリック クライアント フローを許可している必要があります。許可していない場合、以下のエラーが発生します。

AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'.

アプリケーションのアクセス許可

アプリケーションのアクセス許可の場合、クライアント シークレットを使うことはできず、証明書によるログインが必須になります。

Connect-PnPOnline -Url https://{{tenantname}}.sharepoint.com -Tenant {{tenantid}} -ClientId {{clientid}} -CertificatePath {{certificatepath}} -CertificatePassword {{certificatepassword}}

アクセス トークン

取得済みのアクセス トークンを使ってログインすることもできます。

Connect-PnPOnline -Url https://{{tenantname}}.sharepoint.com -Tenant {{tenantid}} -AccessToken {{accesstoken}}

まとめ

ドキュメントにすべて書いてあるのですがちょいちょい不親切なんですよね。

github.com

そもそも Scope を指定できるようにしてほしいと思ったら、Register-PnPAzureADApp を使って必要なアクセス許可を持つアプリを簡単に作ってね、ということらしいです。理屈はわかるけどいまいちな気がしますね。

github.com