共用方式為


使用 Azure AD B2C 在您自己的 iOS Swift 應用程式中啟用驗證

這很重要

自 2025 年 5 月 1 日起,Azure AD B2C 將不再可供新客戶購買。 在我們的常見問題中深入瞭解

本文說明如何將 Azure Active Directory B2C (Azure AD B2C) 驗證新增至您自己的 iOS Swift 行動應用程式。 瞭解如何整合 iOS Swift 應用程式與適用於 iOS 的 Microsoft 驗證連結庫 (MSAL)。

使用本文搭配 在範例 iOS Swift 應用程式中設定驗證,將範例 iOS Swift 應用程式取代為您自己的 iOS Swift 應用程式。 完成本文中的指示之後,您的應用程式會透過 Azure AD B2C 接受登入。

先決條件

檢閱使用 Azure AD B2C 在 iOS Swift 應用程式中設定驗證範例中的必要條件和整合指示。

建立 iOS Swift 應用程式專案

如果您還沒有 iOS Swift 應用程式,請執行下列步驟來設定新的專案:

  1. 開啟 Xcode,然後選取 [ 檔案>>專案]。
  2. 針對 iOS 應用程式,選取 [iOS>應用程式],然後選取 [ 下一步]。
  3. 針對 選擇您新專案的選項,請提供以下事項:
    1. 產品名稱,例如 MSALiOS
    2. 組織識別碼,例如 contoso.com
    3. 針對 介面,選取 分鏡腳本
    4. 針對 生命週期,選取 UIKit 應用程式代理
    5. 針對 [ 語言],選取 [ Swift]。
  4. 選取 下一步
  5. 選取要在其中建立應用程式的資料夾,然後選取 [ 建立]。

步驟 1:安裝 MSAL 程式庫

  1. 使用 CocoaPods 安裝 MSAL 程式庫。 在與專案 .xcodeproj 檔案相同的資料夾中,如果 podfile 檔案不存在,請建立空白檔案,並將它命名為 podfile。 將下列程式代碼新增至 podfile 檔案:

    use_frameworks!
    
    target '<your-target-here>' do
       pod 'MSAL'
    end
    
  2. <your-target-here>取代為您的項目名稱(例如MSALiOS)。 如需詳細資訊,請參閱 Podfile 語法參考

  3. 在終端機視窗中,移至包含 Podfile 檔案的資料夾,然後執行 Pod 安裝以安裝 MSAL 連結庫。

  4. 執行 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 配置。 您的應用程式會在 URL 架構中接聽來自 Azure AD B2C 的回呼。

在 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 識別提供者的相關信息。 應用程式會使用此資訊來建立與 Azure AD B2C 的信任關係。
  • 包含驗證程式代碼來驗證使用者、取得令牌,以及驗證它們。

UIViewController選擇用戶驗證的位置。 在您的專案中,將程式與 GitHub 中提供的程式代碼合併。

步驟 4:設定 iOS Swift 應用程式

新增驗證碼之後,請使用您的 Azure AD B2C 設定來設定 iOS Swift 應用程式。 Azure AD B2C 識別提供者設定是在 UIViewController 上一節中選擇的類別中設定。

若要瞭解如何設定 iOS Swift 應用程式,請參閱 使用 Azure AD B2C 在範例 iOS Swift 應用程式中設定驗證

步驟 5:執行及測試行動應用程式

  1. 使用 連線 iOS 裝置的模擬器建置並執行專案。
  2. 選取 [登入],然後使用您的 Azure AD B2C 本機或社交帳戶註冊或登入。
  3. 成功驗證之後,您會在導覽列中看到您的顯示名稱。

步驟 6:自定義程式碼建置組塊

本節說明啟用 iOS Swift 應用程式驗證的程式代碼建置組塊。 它會列出 UIViewController 的方法,並討論如何自定義程式代碼。

步驟 6.1:具現化公用用戶端應用程式

公用用戶端應用程式不受信任,無法安全地保留應用程式秘密,而且它們沒有客戶端密碼。 在 viewDidLoad 中,使用公用用戶端應用程式物件具現化 MSAL。

下列 Swift 代碼段示範如何使用組態物件初始化 MSAL MSALPublicClientApplicationConfig

組態物件會提供 Azure AD B2C 環境的相關信息。 例如,它會提供用戶端標識碼、重新導向 URI 和授權單位,以建置對 Azure AD B2C 的驗證要求。 如需設定對象的相關信息,請參閱 設定範例行動應用程式

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 代碼段會初始化 webViewParameters 類別成員,並使用系統網頁檢視。 如需詳細資訊,請參閱 自定義適用於 iOS/macOS 的瀏覽器和 WebViews

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會傳回resulterror物件。 使用此閉包來:

  • 在驗證完成後,使用資訊更新行動應用程式UI。
  • 使用存取令牌呼叫 Web API 服務。
  • 處理驗證錯誤(例如,當使用者取消登入流程時)。

步驟 6.3:呼叫 Web API

若要呼叫 令牌型授權 Web API,應用程式需要有效的存取令牌。 應用程式會執行下列動作:

  1. 取得具有 Web API 端點所需許可權(範圍)的存取令牌。
  2. 使用下列格式,將存取令牌作為持有者的憑證傳遞到 HTTP 要求的授權標頭中:
Authorization: Bearer <access-token>

當使用者 以互動方式進行驗證時,應用程式會在關閉時 acquireToken 取得存取令牌。 針對後續的 Web API 呼叫,請使用靜默取得令牌 ( acquireTokenSilent ) 方法,如本節所述。

方法 acquireTokenSilent 會執行下列動作:

  1. 它會嘗試從令牌快取擷取具有要求範圍的存取令牌。 如果令牌存在且尚未過期,則會傳回令牌。
  2. 如果令牌不存在於令牌快取中或已過期,MSAL 函式庫會嘗試使用刷新令牌來取得新的存取令牌。
  3. 如果重新整理令牌不存在或已過期,則會傳回例外狀況。 在此情況下,您應該提示使用者 以互動方式登入

下列代碼段示範如何取得存取權杖:

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)")
}
}

後續步驟

學習怎麼做: