重要
2025 年 5 月 1 日より、Azure AD B2C は新規のお客様向けに購入できなくなります。 詳細については、FAQ を参照してください。
この記事では、独自の iOS Swift モバイル アプリケーションに Azure Active Directory B2C (Azure AD B2C) 認証を追加する方法について説明します。 iOS Swift アプリケーションを iOS 用 Microsoft 認証ライブラリ (MSAL) と統合する方法について説明します。
この記事では、 サンプルの iOS Swift アプリケーションで認証を構成し、サンプルの iOS Swift アプリを独自の iOS Swift アプリに置き換えて使用します。 この記事の手順を完了すると、アプリケーションは Azure AD B2C 経由のサインインを受け入れます。
[前提条件]
「Azure AD B2C を使用してサンプル iOS Swift アプリで認証を構成する」の前提条件と統合手順を確認します。
iOS Swift アプリ プロジェクトを作成する
iOS Swift アプリケーションがまだない場合は、次の手順を実行して新しいプロジェクトを設定します。
- Xcode を開き、ファイル>New>Project を選択します。
- iOS アプリの場合は、 iOS>App を選択し、[ 次へ] を選択します。
-
新しいプロジェクトの [オプションの選択] で、次の情報を指定します。
-
製品名 (
MSALiOS
など)。 -
組織識別子 (
contoso.com
など)。 - [インターフェイス] で、[ストーリーボード] を選択します。
- ライフ サイクルでは、UIKit アプリ デリゲートを選択します。
- 言語の場合は、[Swift] を選択します。
-
製品名 (
- [次へ] を選択します。
- アプリを作成するフォルダーを選択し、[ 作成] を選択します。
手順 1: MSAL ライブラリをインストールする
CocoaPods を使用して MSAL ライブラリをインストールします。 プロジェクトの .xcodeproj ファイルと同じフォルダーに podfile ファイルが存在しない場合は、空のファイルを作成し、 podfile という名前を付けます。 podfile ファイルに次のコードを追加します。
use_frameworks! target '<your-target-here>' do pod 'MSAL' end
<your-target-here>
をプロジェクトの名前 (たとえば、MSALiOS
) に置き換えます。 詳細については、「 Podfile 構文リファレンス」を参照してください。ターミナル ウィンドウで、 podfile ファイルが格納されているフォルダーに移動し、 ポッドのインストール を実行して MSAL ライブラリをインストールします。
pod install
コマンドを実行すると、<プロジェクト名>.xcworkspace ファイルが作成されます。 Xcode でプロジェクトを再読み込みするには、Xcode を閉じ、 <プロジェクト名>.xcworkspace ファイルを開きます。
手順 2: アプリの URL スキームを設定する
ユーザーが認証されると、Azure AD B2C は、Azure AD B2C アプリケーション登録で構成されたリダイレクト URI を使用して、承認コードをアプリに送信します。
MSAL の既定のリダイレクト URI 形式は msauth.[Your_Bundle_Id]://auth
。 たとえば、 msauth.com.microsoft.identitysample.MSALiOS://auth
します。ここで、 msauth.com.microsoft.identitysample.MSALiOS
は URL スキームです。
この手順では、 CFBundleURLSchemes
配列を使用して URL スキームを登録します。 アプリケーションは、Azure AD B2C からのコールバックの URL スキームをリッスンします。
Xcode で、 Info.plist ファイル をソース コード ファイルとして開きます。
<dict>
セクションで、次の XML スニペットを追加します。
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>msauth.com.microsoft.identitysample.MSALiOS</string>
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>msauthv2</string>
<string>msauthv3</string>
</array>
手順 3: 認証コードを追加する
サンプル コードは、UIViewController
クラスで構成されています。 このクラスは次のようなものです。
- ユーザー インターフェイスの構造を定義します。
- Azure AD B2C ID プロバイダーに関する情報が含まれています。 アプリはこの情報を使用して、Azure AD B2C との信頼関係を確立します。
- ユーザーの認証、トークンの取得、および検証を行う認証コードが含まれています。
ユーザーが認証する UIViewController
を選択します。
UIViewController
で、コードを GitHub で提供されているコードとマージします。
手順 4: iOS Swift アプリを構成する
認証コードを追加したら、Azure AD B2C 設定で iOS Swift アプリを構成します。 Azure AD B2C ID プロバイダーの設定は、前のセクションで選択した UIViewController
クラスで構成されます。
iOS Swift アプリを構成する方法については、「 Azure AD B2C を使用してサンプル iOS Swift アプリで認証を構成する」を参照してください。
手順 5: モバイル アプリを実行してテストする
- 接続された iOS デバイスのシミュレーターを使用して、プロジェクトをビルドして実行します。
- [サインイン] を選択し、Azure AD B2C のローカル アカウントまたはソーシャル アカウントでサインアップまたはサインインします。
- 正常に認証されると、ナビゲーション バーに表示名が表示されます。
手順 6: コード構成要素をカスタマイズする
このセクションでは、iOS Swift アプリの認証を有効にするコード構成要素について説明します。 UIViewController のメソッドの一覧を示し、コードをカスタマイズする方法について説明します。
手順 6.1: パブリック クライアント アプリケーションをインスタンス化する
パブリック クライアント アプリケーションは、アプリケーション シークレットを安全に保持するために信頼されておらず、クライアント シークレットも持っていません。 viewDidLoad で、パブリック クライアント アプリケーション オブジェクトを使用して MSAL をインスタンス化します。
次の Swift コード スニペットは、 MSALPublicClientApplicationConfig
構成オブジェクトを使用して MSAL を初期化する方法を示しています。
構成オブジェクトは、Azure AD B2C 環境に関する情報を提供します。 たとえば、Azure AD B2C への認証要求をビルドするためのクライアント ID、リダイレクト URI、および権限が提供されます。 構成オブジェクトの詳細については、「 サンプル モバイル アプリの構成」を参照してください。
do {
let signinPolicyAuthority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)
let editProfileAuthority = try self.getAuthority(forPolicy: self.kEditProfilePolicy)
let pcaConfig = MSALPublicClientApplicationConfig(clientId: kClientID, redirectUri: kRedirectUri, authority: signinPolicyAuthority)
pcaConfig.knownAuthorities = [signinPolicyAuthority, editProfileAuthority]
self.applicationContext = try MSALPublicClientApplication(configuration: pcaConfig)
self.initWebViewParams()
} catch {
self.updateLoggingText(text: "Unable to create application \(error)")
}
initWebViewParams
メソッドは、対話型認証エクスペリエンスを構成します。
次の Swift コード スニペットは、システム Web ビューを使用して webViewParameters
クラス メンバーを初期化します。 詳細については、「 iOS/macOS 用のブラウザーと WebView をカスタマイズする」を参照してください。
func initWebViewParams() {
self.webViewParameters = MSALWebviewParameters(authPresentationViewController: self)
self.webViewParameters?.webviewType = .default
}
手順 6.2: 対話型承認要求を開始する
対話型承認要求は、ユーザーがシステム Web ビューを使用してサインアップまたはサインインするように求められるフローです。 ユーザーが [サインイン ] ボタンを選択すると、 authorizationButton
メソッドが呼び出されます。
authorizationButton
メソッドは、承認要求に関する関連データを使用してMSALInteractiveTokenParameters
オブジェクトを準備します。
acquireToken
メソッドでは、MSALInteractiveTokenParameters
を使用して、システム Web ビューを使用してユーザーを認証します。
次のコード スニペットは、対話型承認要求を開始する方法を示しています。
let parameters = MSALInteractiveTokenParameters(scopes: kScopes, webviewParameters: self.webViewParameters!)
parameters.promptType = .selectAccount
parameters.authority = authority
applicationContext.acquireToken(with: parameters) { (result, error) in
// On error code
guard let result = result else {
self.updateLoggingText(text: "Could not acquire token: \(error ?? "No error information" as! Error)")
return
}
// On success code
self.accessToken = result.accessToken
self.updateLoggingText(text: "Access token is \(self.accessToken ?? "Empty")")
}
ユーザーが承認フローを成功または失敗で終了した場合、その結果はメソッドのacquireToken
に返されます。
acquireToken
メソッドは、result
オブジェクトと error
オブジェクトを返します。 このクロージャを使用して、次の操作を行います。
- 認証が完了した後、モバイル アプリ UI を情報で更新します。
- アクセス トークンを使用して Web API サービスを呼び出します。
- 認証エラー (ユーザーがサインイン フローをキャンセルした場合など) を処理します。
手順 6.3: Web API を呼び出す
トークンベースの承認 Web API を呼び出すには、アプリに有効なアクセス トークンが必要です。 アプリは次の処理を行います。
- Web API エンドポイントに必要なアクセス許可 (スコープ) を持つアクセス トークンを取得します。
- 次の形式を使用して、HTTP 要求の承認ヘッダーでアクセス トークンをベアラー トークンとして渡します。
Authorization: Bearer <access-token>
ユーザーが 対話形式で認証すると、アプリは acquireToken
クロージャでアクセス トークンを取得します。 後続の Web API 呼び出しでは、このセクションで説明するように、トークンの取得サイレント (acquireTokenSilent
) メソッドを使用します。
acquireTokenSilent
メソッドは、次のアクションを実行します。
- 要求されたスコープを持つアクセス トークンをトークン キャッシュからフェッチしようとします。 トークンが存在し、有効期限が切れていない場合は、トークンが返されます。
- トークンがトークン キャッシュに存在しないか、有効期限が切れている場合、MSAL ライブラリは更新トークンを使用して新しいアクセス トークンを取得しようとします。
- 更新トークンが存在しないか、有効期限が切れている場合は、例外が返されます。 この場合は、 対話形式でサインインするようにユーザーに求める必要があります。
次のコード スニペットは、アクセス トークンを取得する方法を示しています。
do {
// Get the authority using the sign-in or sign-up user flow
let authority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)
// Get the current account from the application context
guard let thisAccount = try self.getAccountByPolicy(withAccounts: applicationContext.allAccounts(), policy: kSignupOrSigninPolicy) else {
self.updateLoggingText(text: "There is no account available!")
return
}
// Configure the acquire token silent parameters
let parameters = MSALSilentTokenParameters(scopes: kScopes, account:thisAccount)
parameters.authority = authority
parameters.loginHint = "username"
// Acquire token silent
self.applicationContext.acquireTokenSilent(with: parameters) { (result, error) in
if let error = error {
let nsError = error as NSError
// interactionRequired means we need to ask the user to sign in. This usually happens
// when the user's Refresh Token is expired or if the user has changed their password
// among other possible reasons.
if (nsError.___domain == MSALErrorDomain) {
if (nsError.code == MSALError.interactionRequired.rawValue) {
// Start an interactive authorization code
// Notice we supply the account here. This ensures we acquire token for the same account
// as we originally authenticated.
...
}
}
self.updateLoggingText(text: "Could not acquire token: \(error)")
return
}
guard let result = result else {
self.updateLoggingText(text: "Could not acquire token: No result returned")
return
}
// On success, set the access token to the accessToken class member.
// The callGraphAPI method uses the access token to call a web API
self.accessToken = result.accessToken
...
}
} catch {
self.updateLoggingText(text: "Unable to construct parameters before calling acquire token \(error)")
}
callGraphAPI
メソッドは、次に示すように、アクセス トークンを取得し、Web API を呼び出します。
@objc func callGraphAPI(_ sender: UIButton) {
guard let accessToken = self.accessToken else {
self.updateLoggingText(text: "Operation failed because could not find an access token!")
return
}
let sessionConfig = URLSessionConfiguration.default
sessionConfig.timeoutIntervalForRequest = 30
let url = URL(string: self.kGraphURI)
var request = URLRequest(url: url!)
request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
let urlSession = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: OperationQueue.main)
self.updateLoggingText(text: "Calling the API....")
urlSession.dataTask(with: request) { data, response, error in
guard let validData = data else {
self.updateLoggingText(text: "Could not call API: \(error ?? "No error information" as! Error)")
return
}
let result = try? JSONSerialization.jsonObject(with: validData, options: [])
guard let validResult = result as? [String: Any] else {
self.updateLoggingText(text: "Nothing returned from API")
return
}
self.updateLoggingText(text: "API response: \(validResult.debugDescription)")
}.resume()
}
手順 6.4: ユーザーをサインアウトする
MSAL を使用してサインアウトすると、アプリケーションからユーザーに関する既知の情報がすべて削除されます。 サインアウト方法を使用してユーザーをサインアウトし、UI を更新します。 たとえば、保護された UI 要素を非表示にしたり、サインアウト ボタンを非表示にしたり、サインイン ボタンを表示したりすることができます。
次のコード スニペットは、ユーザーをサインアウトする方法を示しています。
@objc func signoutButton(_ sender: UIButton) {
do {
let thisAccount = try self.getAccountByPolicy(withAccounts: applicationContext.allAccounts(), policy: kSignupOrSigninPolicy)
if let accountToRemove = thisAccount {
try applicationContext.remove(accountToRemove)
} else {
self.updateLoggingText(text: "There is no account to signing out!")
}
...
} catch {
self.updateLoggingText(text: "Received error signing out: \(error)")
}
}
次のステップ
具体的には、次の方法を学習します。