適用於:
外部租用戶 (深入瞭解)
本教學課程示範如何使用原生驗證,在iOS/macOS應用程式中使用電子郵件單次密碼或使用者名稱和密碼來登入和註銷使用者。
在本教學課程中,您會:
- 使用電子郵件一次性密碼或使用者名稱(電子郵件)和密碼登入使用者。
- 註銷使用者。
- 處理登入錯誤
先決條件
- 教學課程:準備 iOS/macOS 應用程式以進行原生驗證。
- 如果您想要使用具密碼 的Email 登入,請在 建立您的註冊和登入使用者流程時,將其配置為使用 Email 和密碼。
使用者登入
若要使用 電子郵件單次密碼 流程登入使用者,請擷取電子郵件,並傳送包含一次性密碼的電子郵件,讓使用者驗證其電子郵件。 當使用者輸入有效的單次密碼時,應用程式會將其登入。
若要使用 電子郵件搭配密碼 流程登入使用者,請擷取電子郵件和密碼。 如果使用者名稱和密碼有效,應用程式會登入使用者。
若要登入使用者,您需要:
建立使用者介面 (UI) 以:
- 從使用者收集電子郵件。 將驗證新增至您的輸入,以確保使用者輸入有效的電子郵件位址。
- 如果您使用使用者名稱(電子郵件)和密碼登入,請收集密碼。
- 如果您使用電子郵件一次性密碼登入,請從使用者收集電子郵件一次性密碼。
- 新增按鈕,讓使用者使用電子郵件一次性密碼登入時,重新傳送一次性密碼。
在您的UI中,新增按鈕,其 select 事件會啟動登入,如下列代碼段所示:
@IBAction func signInPressed(_: Any) { guard let email = emailTextField.text else { resultTextView.text = "email not set" return } let parameters = MSALNativeAuthSignInParameters(username: email) nativeAuth.signIn(parameters: parameters, delegate: self) }若要使用 電子郵件單次密碼 流程登入使用者,我們使用下列代碼段:
nativeAuth.signIn(parameters: parameters, delegate: self)signIn(parameters:delegate)方法必須實作SignInStartDelegate通訊協定,此方法會在傳遞的委派物件上呼叫某個方法以進行異步回應。 我們會傳遞MSALNativeAuthSignInParameters的實例,其中包含使用者在電子郵件提交表單中提供的電子郵件位址,並將self作為委派進行傳遞。若要使用 Email 搭配密碼 流程登入使用者,我們會使用下列代碼段:
let parameters = MSALNativeAuthSignInParameters(username: email) parameters.password = password nativeAuth.signIn(parameters: parameters, delegate: self)在
signIn(parameters:delegate)方法中,您會傳遞MSALNativeAuthSignInParameters實例,其中包含使用者提供的電子郵件位址及其密碼,以及符合SignInStartDelegate通訊協定的委派物件。 在這個範例中,我們會傳遞self。若要在使用
SignInStartDelegate流程時實作 通訊協定,請使用下列代碼段:extension ViewController: SignInStartDelegate { func onSignInStartError(error: MSAL.SignInStartError) { resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")" } func onSignInCodeRequired( newState: MSAL.SignInCodeRequiredState, sentTo: String, channelTargetType: MSAL.MSALNativeAuthChannelType, codeLength: Int ) { resultTextView.text = "Verification code sent to \(sentTo)" } }signIn(parameters:delegate)會導致呼叫委派方法。 在最常見的案例中,會呼叫onSignInCodeRequired(newState:sentTo:channelTargetType:codeLength),指出已傳送程式代碼來驗證用戶的電子郵件位址。 除了有關程式碼傳送目的地的一些詳細信息及其位數外,該委派方法還具有一個類型為newState的SignInCodeRequiredState參數,使我們可以存取以下兩個新方法:submitCode(code:delegate)resendCode(delegate)
使用
submitCode(code:delegate)提交使用者以單次密碼形式提供的一次性密碼,請使用下列代碼段:newState.submitCode(code: userSuppliedCode, delegate: self)submitCode(code:delegate)接受一次性密碼和委派參數。 提交程式代碼之後,您必須實作SignInVerifyCodeDelegate通訊協議來驗證單次密碼。若要將
SignInVerifyCodeDelegate通訊協定實作為類別的延伸模組,請使用下列代碼段:extension ViewController: SignInVerifyCodeDelegate { func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) { resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")" } func onSignInCompleted(result: MSALNativeAuthUserAccountResult) { resultTextView.text = "Signed in successfully." let parameters = MSALNativeAuthGetAccessTokenParameters() result.getAccessToken(parameters: parameters, delegate: self) } }在最常見的案例中,我們會收到呼叫
onSignInCompleted(result),指出使用者已登入。 結果可用來擷取access token。getAccessToken(parameters:delegate)接受MSALNativeAuthGetAccessTokenParameters實例和委派參數,我們必須在CredentialsDelegate通訊協定中實作必要的方法。在最常見的情況下,我們接到打給
onAccessTokenRetrieveCompleted(result)的電話,指出使用者已取得access token。extension ViewController: CredentialsDelegate { func onAccessTokenRetrieveError(error: MSAL.RetrieveAccessTokenError) { resultTextView.text = "Error retrieving access token" } func onAccessTokenRetrieveCompleted(result: MSALNativeAuthTokenResult) { resultTextView.text = "Signed in. Access Token: \(result.accessToken)" } }若要在搭配密碼
SignInStartDelegateEmail 時實作 通訊協定,請使用下列代碼段:extension ViewController: SignInStartDelegate { func onSignInStartError(error: MSAL.SignInStartError) { resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")" } func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) { // User successfully signed in } }在最常見的案例中,我們會收到呼叫
onSignInCompleted(result),指出使用者已登入。 結果可用來擷取access token。getAccessToken(parameters:delegate)接受MSALNativeAuthGetAccessTokenParameters實例和委派參數,我們必須在CredentialsDelegate通訊協定中實作必要的方法。在最常見的情況下,我們接到打給
onAccessTokenRetrieveCompleted(result)的電話,指出使用者已取得access token。extension ViewController: CredentialsDelegate { func onAccessTokenRetrieveError(error: MSAL.RetrieveAccessTokenError) { resultTextView.text = "Error retrieving access token" } func onAccessTokenRetrieveCompleted(result: MSALNativeAuthTokenResult) { resultTextView.text = "Signed in. Access Token: \(result.accessToken)" } }
處理登入錯誤
登入期間,並非每個動作都成功。 例如,使用者可能會嘗試使用不存在的電子郵件位址登入,或提交無效的程序代碼。
若要處理
signIn(parameters:delegate)方法中的錯誤,請使用下列代碼段:func onSignInStartError(error: MSAL.SignInStartError) { if error.isUserNotFound || error.isInvalidUsername { resultTextView.text = "Invalid username" } else { resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")" } }若要處理
submitCode()方法中的錯誤,請使用下列代碼段:func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) { if error.isInvalidCode { // Inform the user that the submitted code was incorrect and ask for a new code to be supplied let userSuppliedCode = retrieveNewCode() newState?.submitCode(code: userSuppliedCode, delegate: self) } else { resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")" } }如果使用者輸入不正確的電子郵件驗證碼,錯誤處理程式會包含一個名為
SignInCodeRequiredState的參考,用於提交更新的驗證碼。 在先前的SignInVerifyCodeDelegate通訊協定實作中,我們只會在處理onSignInVerifyCodeError(error:newState)委派函式時顯示錯誤。
讀取 ID 令牌聲明
一旦您的應用程式取得 ID 令牌,您就可以擷取目前帳戶的相關宣告。 若要這樣做,請使用下列代碼段:
func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
let claims = result.account.accountClaims
let preferredUsername = claims?["preferred_username"] as? String
}
您用來存取宣告值的鍵,是您在將使用者屬性新增為令牌宣告時所指定的名稱。
瞭解如何在將使用者特性新增至令牌宣告一文中,將內建和自訂特性新增為令牌宣告。
註銷使用者
若要註銷使用者,請使用您在 MSALNativeAuthUserAccountResult 回呼中收到的 onSignInCompleted 參考,或使用 getNativeAuthUserAccount() 從快取取得任何登入的帳戶,並將參考儲存在 accountResult 成員變數中。
將新的成員變數新增至您的
ViewController類別:var accountResult: MSALNativeAuthUserAccountResult?。成功初始化
viewDidLoad之後,加入此行以更新nativeAuth來檢索任何快取的帳戶:accountResult = nativeAuth.getNativeAuthUserAccount()。更新
signInCompleted處理程式以儲存帳戶結果:func onSignInCompleted(result: MSALNativeAuthUserAccountResult) { resultTextView.text = "Signed in successfully" accountResult = result }新增 [註銷] 按鈕,並使用下列程式代碼來註銷使用者:
@IBAction func signOutPressed(_: Any) { guard let accountResult = accountResult else { print("Not currently signed in") return } accountResult.signOut() self.accountResult = nil resultTextView.text = "Signed out" }
您已成功完成所有必要步驟,以註銷應用程式上的使用者。 建置並執行您的應用程式。 如果一切順利,您應該能夠選取 [註銷] 按鈕以成功註銷。
啟用別名或使用者名稱登入
您可以允許使用電子郵件地址和密碼登入的使用者也使用使用者名稱和密碼登入。 使用者名稱也稱為替代登入識別碼,可以是客戶 ID、帳號,或你選擇使用的其他識別碼作為使用者名稱。
你可以透過 Microsoft Entra 管理中心手動指派使用者名稱給使用者帳號,或透過 Microsoft Graph API 自動化流程。
請使用「 以別名或使用者名稱登入 」文章中的步驟,讓你的使用者能在應用程式中使用使用者名登入:
設定自訂聲明提供者
如果您想將來自外部系統的宣告新增到發行給應用程式的權杖中,請使用 自訂宣告提供者。 自定義宣告提供者是由自定義驗證延伸模組所組成,可呼叫外部 REST API 從外部系統擷取宣告。
請遵循 設定自定義宣告提供者 中的步驟,將外部系統的宣告新增至安全性令牌。