チュートリアル: ネイティブ認証を使用してiOS アプリにサインアップを追加する
適用対象: iOS (Swift) macOS (Swift)
このチュートリアルでは、ネイティブ認証を使用して iOS/macOS アプリで、メールのワンタイム パスコードまたはユーザー名 (メールアドレス) とパスワードの組み合わせを使用してユーザーをサインアップし、ユーザー属性を収集する方法について説明します。
- メールのワンタイム パスコードまたはメール アドレスとパスワードの組み合わせを使用してユーザーを登録します。
- サインアップ中にユーザー属性を収集します。
- サインアップ エラーを処理します。
前提条件
- チュートリアル: ネイティブ認証用に iOS アプリを準備します。
- サインアップ中にユーザ属性を収集する場合は、「サインアップとサインインのユーザー フローを作成するときにユーザー属性を構成します。
ユーザーをサインアップする
メールのワンタイム パスコードまたはメール アドレスとパスワードの組み合わせを使用してユーザーをサインアップするには、ユーザーからメール アドレスを収集し、メールのワンタイム パスコードを含むメールをユーザーに送信します。 ユーザーは、有効なメールのワンタイム パスコードを入力し、ユーザー名を検証します。
ユーザーをサインアップするには、次の操作を行う必要があります。
以下にユーザー インターフェイス (UI) を作成します。
- ユーザーからメール アドレスを収集します。 ユーザーが有効なメール アドレスを入力していることを確認するために、入力に検証を追加します。
- ユーザー名 (メール アドレス) とパスワードでサインアップした場合、パスワードを収集します。
- ユーザーからメールのワンタイム パスコードを収集します。
- 必要に応じて、ユーザー属性を収集します。
- ユーザーがコードを受信しなかった場合にワンタイム パスコードを再送信します。
- サインアップ フローを開始します。
アプリで、select イベントによって次のコード スニペットをトリガーするボタンを追加します。
@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
パラメータもあります。これにより、次の 2 つの新しいメソッドにアクセスできます。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)
メソッドは、パラメーターとして属性を受け取ります。
ユーザー属性を収集するには、次のコード スニペットを使用します。
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])
が実装されている場合はそれが呼び出されます。クラスに拡張機能として
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
パラメーターがあります。これにより、次の 2 つの新しいメソッドにアクセスできます。submitCode(code:delegate)
resendCode(delegate)
1 つ以上のページで属性を使用する。
属性を 1 つ以上のページに分散させるには、顧客 ID およびアクセス管理 (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!"
}
}
このデリゲート メソッドには、SignUpAttributesRequiredState
型の newState
パラメータがあり、これを使用して新しいメソッドにアクセスできます。
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
: 送信された 1 つ以上の属性が入力検証に失敗したことを示します。 このエラーには、attributeNames パラメータが含まれています。これは、入力検証に失敗した開発者によって送信されたすべての属性のリストです。onSignUpAttributesRequired
: ユーザー アカウントを作成するには、1 つ以上の属性の送信をサーバーが要求することを示します。 これは、テナント構成で 1 つ以上の属性が必須として設定されている場合に発生します。 この結果には、属性パラメータが含まれています。これは、API に必要なユーザー属性の詳細を示すMSALNativeAuthRequiredAttribute
オブジェクトのリストです。
両方のデリゲート メソッドに新しい状態参照が含まれています。 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 アプリでサインアップ後にユーザーをサインインさせる」の記事をご覧ください。