はじめに
iOSアプリからAzureのサービスへアクセスしたい場面はよくあります。
ただ、モバイアルプリにAPIキーや共有キー、クライアントシークレットのような秘密情報を埋め込む構成は、できるだけ避けたいです。
そこで今回は、MSAL(Microsoft Authentication Library)を使ってiOSアプリからMicrosoft Entra IDにサインインし、アクセストークンを取得してAzureへアクセスする構成を試しました。MSALは様々なプラットフォーム向けに提供されており、iOS/macOS向けにも提供されています。
この記事では「iOSアプリに秘密情報を埋め込まず、トークンベースでAzureへアクセスする」という考え方をメインに説明します。具体例としてAzure Mapsを使いますが、主題はAzure Maps固有の話ではなく、MSAL + EntraIDによるセキュアアクセスの実装パターンです。 Azure MapsはMicrosoft Entra ID認証とRBAC(ロールベースアクセス制御)をサポートしているため、このテーマの具体例として扱いやすいサービスです。
なぜMSALを使うのか
iOSアプリでEntra ID認証を行いたい場合、MSALは非常に有力な選択肢です。Microsoft LearnのiOSチュートリアルでも、MSALをiOSアプリへ追加し、アプリ登録情報を使って認証を構成する流れが案内されています。
MSALを使うことで、次のような流れをアプリに組み込めます。
- ユーザをMicrosoft Entra IDにサインインさせる
- アクセストークンを取得する
- そのトークンを使って、保護されたAzureサービスへアクセスする
つまり、アプリに固有の秘密情報を持たせるのではなく、ユーザの認証結果として取得したトークンを使う、という構成にできます。これが今回やりたいことの中心です。
セキュアアクセスの基本方針
今回の基本方針はシンプルです。
- アプリに秘密情報を埋め込まない
共有キーやクライアントシークレットをアプリバイナリに入れると、解析や漏洩のリスクがあります。Azure Mapsのshared keyについても、Microsoftは機密情報として扱うべきと案内しています。1 - Microsoft Entra IDからアクセストークンを取得する
モバイルアプリ側ではMSALを使ってサインインを行い、Azure サービスを呼び出すためのアクセストークンを取得します。 - Azure 側ではRBAC/IAMで権限管理する
Azure MapsのようにMicrosoft Entra IDとRBACを組み合わせられるサービスであれば、誰がそのリソースにアクセスできるか、をAzure側で管理できます。これは共有キーを広く配る運用よりも管理しやすいです。
Azure 側の準備
本記事では、Entra IDの同一テナント内で完結するシナリオを前提にします。具体的にはiOSアプリは対象テナントに登録され、ユーザはそのテナントのアカウントでサインインし、Azure Mapもそのテナントに関連づいたAzure サブスクリプション上に作成されているものとします
Entraポータルでアプリを登録する
アプリケーションの登録
まずはEntraポータルへログインしEntra IDにiOSアプリを登録します。
「アプリの登録」→「新規登録」で以下の画面に遷移します。
アプリケーションの登録画面で以下のように入力し、登録します。
- 名前
- 任意(今回はHowToEntraIos)
- アカウントの種類
- シングルテナントのみ
- リダイレクトURI
- 省略
ここでリダイレクトURIを省略するのは、アプリケーション登録後にプラットフォームを指定してリダイレクトURIを登録した方が良いからです。
リダイレクトURIの追加
アプリケーション登録後、登録したアプリのページが表示されるので、Authentication(Preview)を選択し、「リダイレクトURIの追加」を選択してください。
ここでiOSまたはmacOSを選択してください。
バンドルIDの入力欄があるので、今回作成するiOSアプリのバンドルIDを登録してください。
ここでは「org.ukky.HowToEntraIos」とします。
ここで表示されたリダイレクトURIをアプリで使用します。
Azure Mapsの設定
ロール割り当ての追加
今回利用するAzure Maps アカウントのページから「アクセス制御(IAM)」→「追加」→「ロールの割り当ての追加」を選択し、ロールの割り当ての追加画面に遷移します。
ロールとして「Azure Maps データ閲覧者」を選択し、メンバーとして、今回対象となるユーザ、または、グループを選択します。
これでAzure側の準備は整いました。
iOS アプリの実装
今回のサンプルアプリは以下のHowToEntraIosリポジトリのazuremaplibreブランチで作成しています。
ライブラリの準備
Swift Package Managerで以下を指定します
- MSAL
- MapLibreSwiftUI
- https://github.com/maplibre/swiftui-dsl
- Azure MapsのネイティブSDKは廃止されたため、今回はMapLibreを使用して、Azure Maps Tiles APIから取得したTile情報を表示します。
各種設定
Azureと連携する内容はplistにまとめると管理が楽です。
HowToEntraIos/Resources/AuthenticationConfig.plistで設定例をまとめています。
リポジトリ上は本情報をそのまま載せるのは好ましくないため、コミット対象とせず、登録した項目がわかるようにexampleファイルを配置しています。
| 設定名 | 説明 |
|---|---|
| CLIENT_ID | Entraポータルで登録したアプリケーション(HowToEntraIos)の概要で確認できる「アプリケーション(クライアント)ID」 |
| TENNANT_DOMAIN | 今回の対象テナントのドメイン(例:example.onmicrosoft.com) |
| REDIRECT_URI | アプリケーションの登録でリダイレクトURIの登録で、表示されたURI(例:msauth.org.ukky.HowToEntraIos://auth) |
| SCOPES | このEntra認証でアクセス対象とするスコープを配列で指定する。今回はAzure Mapsとして「https://atlas.microsoft.com/user_impersonation」を指定 |
| AZURE_MAPS_CLIENT_ID | Azure Maps アカウントの概要にある「クライアントID」を指定 |
ここで大事なのは、CLIENT_IDとAZURE_MAPS_CLIENT_IDは別物だということです。
前者はEntraに登録したiOSアプリのClientID、後者はAzure MapsアカウントのClientIDです。Azure MapsのEntra認証では、後者をx-ms-client-idに設定します。
設定ファイルから認証情報を読み込む
前述で設定したplistを読み込みアプリ内に情報を提供するAuthenticateionConfig.swiftを作成しています。
以下のようにplistの情報を読み込んでいます。
static func load() throws -> AuthenticationConfig {
guard let url = Bundle.main.url(forResource: "AuthenticationConfig", withExtension: "plist") else {
throw ConfigError.missingFile
}
let data = try Data(contentsOf: url)
return try PropertyListDecoder().decode(AuthenticationConfig.self, from: data)
}
MSALでサインインしてトークンを取得する
| サインイン | 認証セッションを開く | 認証 |
|---|---|---|
![]() |
![]() |
![]() |
サインインボタンが押されると、以下のシーケンスで認証処理が実行されます。
アプリ → MSAL SDK 呼び出し
SignIn ボタンタップから各層を経由し、MSAL SDK の「MSALPublicClientApplication#acquireToken」を呼び出すまでの流れを以下に示します。
MSALPublicClientApplicationは前述のAuthenticationConfig.plistに格納した設定情報を元に初期化したMSALPublicClientApplicationConfigにより初期化する。
「MSALPublicClientApplication#acquireToken」のパラメータであるMSALWebviewParametersにはwebviewTypeを指定します。defaultの場合、OSのバージョンによって最適な認証方法が選択されます。2
Entra ID 認証 → ユーザ情報取得
MSAL SDK が Entra ID と通信し、認証結果を受け取ってから
AuthenticatedUser を生成して UI に反映するまでの流れを以下に示します。
MSALで認証後にAzureMapsに接続する
SignIn 成功後に setupMapAuthentication が呼ばれ、
MSAL でアクセストークンを取得し MapLibre の HTTP ヘッダに設定するまでの流れを示します。
トークン取得
サイレント認証でアクセストークンを取得する流れを以下に示します。
サイレント認証失敗時はインタラクティブ認証にフォールバックします。
アプリ起動時もaccessToken取得済みであれば、「MSALPublicClientApplication#acquireTokenSilent」によるサイレント認証を行うようにし、無駄に認証セッションが表示されるのを防ぎましょう。
MapLibre へのトークン設定
取得したアクセストークンを以下のようにMapLibreのHTTPヘッダに設定し、Azure Maps タイルを認証付きで取得可能とします。
"Authorization": "Bearer \(token)", //アクセストークン
"x-ms-client-id": azureMapsClientId //AzureMapsのクライアントID
その流れを示します。
MapLibreは標準でタイル取得時にカスタムヘッダを付与する仕組みがないため、カスタムURLプロトコルを実装して、特定のURL(atlas.microsoft.com)のみヘッダを付与する仕組みが必要です。今回はAzureMapsAuthProtocol.swiftを作成しました。
まとめ
MSALを使うことで、iOSアプリからEntra IDにサインインし、アクセストークンを取得してAzure へアクセスする流れを実践できます。これは、モバイルアプリに秘密情報を埋め込まずにAzure接続したい時の実用的なパターンです。
今回は具体例としてAzure Mapsを使いました。Azure MapsはEntra IDとRBACに対応しており、Bearerトークンとx-ms-client-idを使ったアクセスが可能です。このアクセス方法はAzureで提供されている他のサービスにも有効なものが多いです。
「アプリにキーを埋め込むのは避けたい」「iOSから安全にAzureにアクセスしたい」と考えているなら、この構成はかなり有力だと考えます。






