このアプリは Microsoft Entra(CIAM/B2C)でのサインイン(サインアップ/サインイン ユーザーフロー)を MSAL for Android で実装し、Compose でログイン/ログアウトとユーザー情報表示を行います。
主なポイント
- ユーザーフローは 1 つ(B2C_1_signupsignin)。専用のサインアップボタンはありません。
- 設定は msal_config.json(res/raw)に集約。auth_config.json は不要・未使用です。
- Redirect URI は Android の
msauth://<packageName>/<signatureHash>を使用します。 - AndroidManifest の BrowserTabActivity に Intent-filter を設定済み。
android:path="/${msalSignatureHash}"は環境変数で差し込みます。
- macOS / Android Studio (最新推奨)
- JDK 21(プロジェクト設定に合わせています)
- Azure Entra External ID(CIAM)テナントでアプリ登録済み
- app/src/main/res/raw/msal_config.sample.json … サンプル設定(コミット対象)
- app/src/main/res/raw/msal_config.json … 実ファイル(機微情報、Git ignore 推奨)
- app/src/main/AndroidManifest.xml … MSAL BrowserTabActivity の Intent-filter 定義
- app/build.gradle.kts … 環境変数から
msalSignatureHashを Manifest プレースホルダーに注入
Android の Redirect URI で必要です。既存の keystore(例: /Users/nakasho/Secret/xxxxxxxx.jks)から計算します。
- keystore 情報(Alias/Password)を把握する
- Alias: 例
howtoentra(実際の値を使用) - Keystore パス:
/Users/nakasho/Secret/xxxxxxxx.jks
- ハッシュ算出(macOS, keytool + openssl)
- 証明書の公開鍵を取り出し → SHA1 → Base64
keytool -exportcert \
-alias <ALIAS> \
-keystore /Users/nakasho/Secret/xxxxxxxx.jks \
-storepass <KEYSTORE_PASSWORD> \
| openssl sha1 -binary \
| openssl base64出力例: h2kwXXDzCdz66scitl3UyZ5g5tM=
- Redirect URI での表記
- Azure 側の登録や URL には URL エンコードされることがあります(
=→%3Dなど)。 - AndroidManifest の
android:pathには「エンコード前(生の Base64)」を入れます。
ビルド時に Manifest の <data android:path="/${msalSignatureHash}"/> へ注入します。
- シェル(zsh)での設定例(~/.zshrc 等)
export MSAL_SIGNATURE_HASH="h2kwXXDzCdz66scitl3UyZ5g5tM="
# 署名に独自 keystore を使う場合(任意: Debug/Release 両方で使用)
export ANDROID_JKS_PATH="/Users/nakasho/Secret/xxxxxxxx.jks"
export ANDROID_JKS_PASSWORD="<keystore-password>"
export ANDROID_JKS_ALIAS="<alias>"
export ANDROID_JKS_KEY_PASSWORD="<key-password-or-same-as-store>"- Android Studio の Run/Debug 構成でも環境変数を設定できます。
- 設定後は
source ~/.zshrcで反映してください。
サンプルからコピーし、プレースホルダを実値に置換します。
- コピー
cp app/src/main/res/raw/msal_config.sample.json app/src/main/res/raw/msal_config.json- 値の置換
<CLIENT_ID>: CIAM で登録したモバイルアプリのアプリケーション(クライアント)ID<REDIRECT_URI>:msauth://org.ukky.howtoentra/<URLエンコード済みSignatureHash>- 例:
msauth://org.ukky.howtoentra/h2kwXXDzCdz66scitl3UyZ5g5tM%3D
- 例:
<AUTHORITY_URL>: ユーザーフローの Authority- 形式(CIAM, ユーザーフローあり):
https://<domain>.ciamlogin.com/<tenant>.onmicrosoft.com/<policy>/- 例:
https://howtoentra.ciamlogin.com/howtoentra.onmicrosoft.com/B2C_1_signupsignin/
- 形式(CIAM, ユーザーフローあり):
サンプルの構造(要点):
account_mode: "SINGLE"authorities[0].type: "CIAM"authorities[0].authority_url: 上記の Authority URL
- Git 管理
msal_config.jsonは Git 追跡しないでください(.gitignore 推奨)msal_config.sample.jsonはコミット済みです
- アプリ登録(CIAM テナント)
- プラットフォーム: Android を追加
- パッケージ名:
org.ukky.howtoentra - 署名ハッシュ:
h2kwXXDzCdz66scitl3UyZ5g5tM=(生の Base64) - これにより Redirect URI
msauth://org.ukky.howtoentra/<エンコード済みハッシュ>が自動登録されます
- ユーザーフロー:
B2C_1_signupsigninを有効 - スコープ: OIDC 基本(openid, profile)。独自 API を呼ぶ場合は
api://<APP_ID>/<scope>を公開し、msal_config.jsonではなくコード側でスコープを指定してトークン取得します
- AndroidManifest.xml(抜粋)
com.microsoft.identity.client.BrowserTabActivityの Intent-filter を定義<data android:scheme="msauth" android:host="org.ukky.howtoentra" android:path="/${msalSignatureHash}"/>
- app/build.gradle.kts
manifestPlaceholders["msalSignatureHash"] = System.getenv("MSAL_SIGNATURE_HASH") ?: ""- 署名設定(任意の keystore を環境変数で指定可能)
- Hilt(DI)
- Gradle プラグイン適用済み
- Application クラスは
@HiltAndroidApp、Activity は@AndroidEntryPointが必要(未設定なら追加してください)
- 環境変数を設定(MSAL_SIGNATURE_HASH は必須)
msal_config.jsonを設置し、CLIENT_ID/REDIRECT_URI/AUTHORITY_URL を正に設定- Android Studio から実行
- 画面
- 未ログイン時: Entra ID(メール)入力フィールド+「ログイン」ボタン
- ログイン後: ログイン済みの旨、取得したユーザー情報表示、ログアウトボタン
- Intent filter for: BrowserTabActivity is missing
- Manifest に BrowserTabActivity の定義が必要(本プロジェクトは定義済み)
android:pathに生の Signature Hash が正しく注入されているか(MSAL_SIGNATURE_HASH が空だと一致しません)
- The redirect URI in the configuration file doesn't match…(期待値と受信値が一致しない)
msal_config.jsonのredirect_uri(URLエンコード済み)と、Azure 側の登録 URI が一致しているか確認- パッケージ名/署名ハッシュの組み合わせが一致しているか
- keystore を変更したらハッシュも変わります(再計算が必要)
- MsalDeclinedScopeException
- 要求スコープが公開/同意されていない。CIAM で独自 API を作成し、API 側でスコープ公開→アプリに付与してください
- Hilt: Expected @AndroidEntryPoint to have a value… / Plugin 忘れ
plugins { alias(libs.plugins.hilt.android) }があるか、@HiltAndroidApp/@AndroidEntryPointが付与されているか確認
- auth_config.json は本プロジェクトでは使用していません(削除可)。設定は msal_config.json に統合しています
- CIAM トークンは Azure Storage のデータプレーンには直接使えません。Blob へはワークフォース テナントのトークンか、バックエンド経由を検討してください
- API 呼び出しで Bearer トークンが必要な場合は、MSAL で
api://<APP_ID>/<scope>やhttps://graph.microsoft.com/.default等のスコープを指定してアクセストークンを取得し、Authorization: Bearer <token>を付与します
MIT License