分享方式:


教學課程:使用原生驗證在 iOS/macOS 應用程式中新增註冊

適用於具有白色核取符號的綠色圓圈。 iOS (Swift) 具有白色核取符號的綠色圓圈。 macOS (Swift)

本教學課程示範如何使用電子郵件一次性密碼或使用者名稱 (電子郵件) 和密碼註冊使用者,並使用原生驗證收集 iOS/macOS 應用程式中的使用者屬性。

  • 使用電子郵件一次性密碼或使用者名稱 (電子郵件) 和密碼註冊使用者。
  • 在註冊期間收集使用者屬性。
  • 處理註冊錯誤。

必要條件

註冊使用者

若要使用電子郵件一次性密碼或使用者名稱 (電子郵件) 和密碼註冊使用者,請從使用者收集電子郵件,然後將包含電子郵件一次性密碼的電子郵件傳送給使用者。 使用者輸入有效的電子郵件一次性密碼來驗證其使用者名稱。

若要註冊使用者,您需要:

  1. 建立使用者介面 (UI):

    • 收集使用者的電子郵件。 為您的輸入新增驗證,確保使用者輸入有效的電子郵件地址。
    • 如果您使用使用者名稱 (電子郵件) 和密碼註冊,請收集密碼。
    • 從使用者收集電子郵件一次性密碼。
    • 如有需要,請收集使用者屬性。
    • 如果使用者未收到密碼,請重新傳送一次性密碼。
    • 啟動註冊流程。
  2. 在您的應用程式中,新增按鈕,其選取事件會觸發下列程式碼片段:

    @IBAction func signUpPressed(_: Any) {
        guard let email = emailTextField.text else {
            resultTextView.text = "Email or password not set"
            return
        }
    
        nativeAuth.signUp(username: email, delegate: self)
    }
    
    • 要使用 電子郵件一次性密碼註冊使用者,我們使用程式庫的 signUp(username:delegate) 方法,此方法會藉由呼叫傳遞委派物件上的其中一個方法以非同步的方式回應,這個方法必須實作 SignUpStartDelegate 通訊協定。 下列程式碼會啟動使用者註冊流程:

      nativeAuth.signUp(username: email, delegate: self)
      

      signUp(username:delegate) 方法中,我們會傳遞使用者在電子郵件提交表單提供的電子郵件地址並委派 (實作 SignUpStartDelegate 通訊協定的類別)。

    • 若要使用 電子郵件搭配密碼註冊使用者,請使用下列程式碼片段:

      @IBAction func signUpPressed(_: Any) {
          guard let email = emailTextField.text, let password = passwordTextField.text else {
              resultTextView.text = "Email or password not set"
              return
          }
      
          nativeAuth.signUp(username: email,password: password,delegate: self)
      }
      

      我們使用程式庫的 signUp(username:password:delegate) 方法,藉由對傳遞的委派物件呼叫其中一個方法 (必須實作 SignUpStartDelegate 通訊協定),以非同步方式回應。 下列程式碼會啟動使用者註冊流程:

      nativeAuth.signUp(username: email, password: password, delegate: self)
      

      signUp(username:password:delegate) 方法中,我們會傳遞使用者的電子郵件地址、密碼及委派(實作 SignUpStartDelegate 通訊協定的類別)。

    • 若要實作 SignUpStartDelegate 通訊協定作為類別的延伸模組,請使用:

      extension ViewController: SignUpStartDelegate {
          func onSignUpStartError(error: MSAL.SignUpStartError) {
              resultTextView.text = "Error signing up: \(error.errorDescription ?? "no description")"
          }
      
          func onSignUpCodeRequired(
              newState: MSAL.SignUpCodeRequiredState,
              sentTo: String,
              channelTargetType: MSAL.MSALNativeAuthChannelType,
              codeLength: Int
          ) {
              resultTextView.text = "Verification code sent to \(sentTo)"
          }
      }
      

      呼叫 signUp(username:password:delegate) 或呼叫 signUp(username:delegate) 會導致對 onSignUpCodeRequired()onSignUpStartError() 委派方法。 呼叫 onSignUpCodeRequired(newState:sentTo:channelTargetType:codeLength) 可指出已傳送代碼來驗證使用者的電子郵件地址。 除了一些關於傳送代碼的位置及其所含位數的詳細資料以外,此委派方法還有 SignUpCodeRequiredState 類型的 newState 參數,可讓我們存取兩個新方法:

      • submitCode(code:delegate)
      • resendCode(delegate)

      若要提交使用者提供給我們的代碼,請使用:

      newState.submitCode(code: userSuppliedCode, delegate: self)
      
      • 若要實作 SignUpVerifyCodeDelegate 通訊協定作為類別的延伸模組,請使用:

        extension ViewController: SignUpVerifyCodeDelegate {
            func onSignUpVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignUpCodeRequiredState?) {
                resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
            }
        
            func onSignUpCompleted(newState: SignInAfterSignUpState) {
                resultTextView.text = "Signed up successfully!"
            }
        }
        

        submitCode(code:delegate) 接受委派參數,且我們必須在 SignUpVerifyCodeDelegate 通訊協定中實作必要的方法。 在最常見的案例,我們會收到對 onSignUpCompleted(newState) 的呼叫,表示使用者已註冊,且流程已完成。

在註冊期間收集使用者屬性

無論您是使用電子郵件一次性密碼或使用者名稱 (電子郵件) 及密碼註冊使用者,您都可以在建立使用者帳戶之前收集使用者屬性。 signUp(username:attributes:delegate) 方法,接受屬性作為參數。

  1. 若要收集使用者屬性,請使用下列程式碼片段:

    let attributes = [
        "country": "United States",
        "city": "Redmond"
    ]
    
    nativeAuth.signUp(username: email, attributes: attributes, delegate: self)
    

    signUp(username:attributes:delegate)ignUp(username:password:attributes:delegate) 會導致呼叫 onSignUpCodeRequired()onSignUpStartError() 委派方法,或導致呼叫 onSignUpAttributesInvalid(attributeNames: [String]) (若已在委派中實作)。

  2. 若要將 SignUpStartDelegate 通訊協定實作為類別的延伸模組,請使用下列程式碼片段:

    extension ViewController: SignUpStartDelegate {
        func onSignUpStartError(error: MSAL.SignUpStartError) {
            resultTextView.text = "Error signing up: \(error.errorDescription ?? "no description")"
        }
    
        func onSignUpCodeRequired(
            newState: MSAL.SignUpCodeRequiredState,
            sentTo: String,
            channelTargetType: MSAL.MSALNativeAuthChannelType,
            codeLength: Int
        ) {
            resultTextView.text = "Verification code sent to \(sentTo)"
        }
    
        func onSignUpAttributesInvalid(attributeNames: [String]) {
           resultTextView.text = "Invalid attributes  \(attributeNames)"
        }
    }
    

    如果屬性無效,則會呼叫方法 onSignUpAttributesInvalid(attributeNames: [String])。 在此情況下,我們會向使用者顯示無效的屬性清單。 否則,會呼叫 onSignUpCodeRequired(newState:sentTo:channelTargetType:codeLength) 以指出已傳送代碼來驗證使用者的電子郵件地址。 除了程式碼收件者及程式碼位數等詳細資料之外,此委派方法還有一個 SignUpCodeRequiredState 類型的 newState 參數,這可讓我們存取兩個新方法:

    • submitCode(code:delegate)
    • resendCode(delegate)

跨一或多個頁面的使用者屬性

若要將屬性分散到一或多個頁面,我們必須將我們想要收集的屬性設定為客戶身分識別和存取管理 (CIAM) 租用戶設定中的必要屬性。

我們會呼叫 signUp(username:password:delegate) 而不傳遞任何屬性。 下一個步驟是呼叫 newState.submitCode(code: userSuppliedCode, delegate: self) 以確認使用者的電子郵件。

我們將 SignUpVerifyCodeDelegate 通訊協定實作為類別的延伸模組,但這次除了必要的方法之外,還必須實作選擇性方法 onSignUpAttributesRequired(attributes:newState)

extension ViewController: SignUpVerifyCodeDelegate {
    func onSignUpAttributesRequired(newState: SignUpAttributesRequiredState) {
        resultTextView.text = "Attributes required"
    }

    func onSignUpVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignUpCodeRequiredState?) {
        resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
    }

    func onSignUpCompleted(newState: SignInAfterSignUpState) {
        resultTextView.text = "Signed up successfully!"
    }
}

此委派方法具有類型為 SignUpAttributesRequiredStatenewState 參數,可讓我們存取新的方法:

  • submitAttributes(attributes:delegate)

若要提交使用者提供給我們的屬性,請使用下列程式碼片段:

let attributes = [
    "country": "United States",
    "city": "Redmond"
]

newState.submitAttributes(attributes: attributes, delegate: self)

我們也會實作 SignUpAttributesRequiredDelegate 通訊協定作為類別的延伸模組:

extension ViewController: SignUpAttributesRequiredDelegate {
    func onSignUpAttributesRequiredError(error: AttributesRequiredError) {
        resultTextView.text = "Error submitting attributes: \(error.errorDescription ?? "no description")"
    }

    func onSignUpAttributesRequired(attributes: [MSALNativeAuthRequiredAttribute], newState: SignUpAttributesRequiredState) {
        resultTextView.text = "Attributes required"
    }

    func onSignUpAttributesInvalid(attributeNames: [String], newState: SignUpAttributesRequiredState) {
        resultTextView.text = "Attributes invalid"
    }

    func onSignUpCompleted(newState: SignInAfterSignUpState) {
        resultTextView.text = "Signed up successfully!"
    }
}

當使用者未提供所有必要的屬性,或屬性無效時,會呼叫這些委派方法:

  • onSignUpAttributesInvalid:指出傳送失敗輸入驗證的一或多個屬性。 此錯誤包含 attributeNames 參數,這是開發人員傳送且輸入驗證失敗的所有屬性清單。
  • onSignUpAttributesRequired:表示伺服器需要先傳送一或多個屬性,才能建立使用者帳戶。 當租用戶設定中有一或多個屬性設定為必要時,就會發生這種情況。 此結果包含屬性參數,這是一份 MSALNativeAuthRequiredAttribute 物件清單,其中概述 API 所需使用者屬性的詳細資料。

這兩個委派方法都包含新的狀態參考。 我們使用 newState 參數,以新的屬性再次呼叫 submitAttributes(attributes:delegate)

處理註冊錯誤

註冊期間,並非每個動作都成功。 例如,使用者可能會嘗試使用已在使用中的電子郵件地址來註冊,或提交無效的代碼。

在先前的 SignUpStartDelegate 通訊協定實作中,我們只會在處理 onSignUpStartError(error) 委派函式時顯示錯誤。

若要管理特定錯誤類型來增強使用者體驗,請使用下列程式碼片段:

func onSignUpStartError(error: MSAL.SignUpStartError) {
    if error.isUserAlreadyExists {
        resultTextView.text = "Unable to sign up: User already exists"
    } else if error.isInvalidPassword {
        resultTextView.text = "Unable to sign up: The password is invalid"
    } else if error.isInvalidUsername {
        resultTextView.text = "Unable to sign up: The username is invalid"
    } else {
        resultTextView.text = "Unexpected error signing up: \(error.errorDescription ?? "no description")"
    }
}

選用:在註冊流程之後登入

成功註冊流程之後,您可以登入使用者,而不需要起始登入流程。 請參閱 教學課程:在 iOS/macOS 應用程式 文章內註冊之後登入使用者了解更多資訊。

後續步驟