適用対象:
外部テナント (詳細)
このチュートリアルでは、ネイティブ認証を使用して、iOS アプリでメールのワンタイム パスコードまたはユーザー名とパスワードを使用してユーザーをサインインおよびサインアウトする方法を説明します。
このチュートリアルでは、次の操作を行います。
- メールのワンタイム パスコードまたはユーザー名 (メール アドレス) とパスワードを使ってユーザーのサインインを行います。
- ユーザーのサインアウト。
- サインイン エラーを処理する
[前提条件]
- チュートリアル: ネイティブ認証用に iOS アプリを準備します。
- パスワード付きメールを使用してサインインする場合は、サインアップおよびサインインのユーザー フローを作成するときに、パスワード付きメールを使用するようにユーザー フローを構成します。
ユーザーのサインイン
メールのワンタイム パスコード フローを使用してユーザーをサインインさせるには、メールをキャプチャし、ユーザーのメールを検証するためのワンタイム パスコードを含むメールを送信します。 有効なワンタイム パスコードを入力すると、アプリはユーザーをサインインさせます。
パスワード付きメール フローを使用してユーザーをサインインさせるには、メール アドレスとパスワードをキャプチャします。 ユーザー名とパスワードが有効な場合、アプリによってユーザーのサインインが行われます。
ユーザーのサインインを行うには、次の操作を行う必要があります。
「ユーザーインターフェース (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)渡されたデリゲート オブジェクトのメソッドの 1 つを呼び出すことによって非同期的に応答する
signIn(parameters:delegate)メソッドは、SignInStartDelegateプロトコルを実装する必要があります。 ユーザーが電子メール送信フォームで提供する電子メール アドレスを含むMSALNativeAuthSignInParametersのインスタンスを渡し、selfを代理人として渡します。パスワード付きメール フローを使用してユーザーをサインインさせるには、次のコード スニペットを使用します。
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パラメータもあります。このパラメータにより、次の 2 つの新しいメソッドにアクセスできます。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)" } }SignInStartDelegateフローを使用する際に プロトコルを実装するには、次のコードスニペットを使用します。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 を使用してアプリで自動化したりできます。
「エイリアスまたはユーザー名を使用してサインインする」の記事の手順を使用して、ユーザーがアプリケーションでユーザー名を使用してサインインできるようにします。
- サインインでユーザー名を有効にします。
- 管理センターでユーザー名を持つユーザーを作成するか、ユーザー名 を 追加して既存のユーザーを更新します。 または、 Microsoft Graph API を使用して、アプリでのユーザーの作成と更新を自動化することもできます。
カスタム クレーム プロバイダーの構成
外部システムからのクレームをアプリに発行されるトークンに追加する場合は、カスタム クレーム プロバイダーを使用します。 カスタム クレーム プロバイダーは、外部システムからクレームを取り込むために、外部 REST API を呼び出すカスタム認証拡張機能で構成されています。
カスタム クレーム プロバイダーの構成の手順に従って、外部システムからのクレームをセキュリティ トークンに追加します。