다음을 통해 공유


자습서: 네이티브 인증을 사용하여 iOS 앱에서 로그인 및 로그아웃 추가

이 자습서에서는 네이티브 인증을 사용하여 iOS 모바일 앱에서 전자 메일 일회용 암호 또는 사용자 이름 및 암호를 사용하여 사용자를 로그인하고 로그아웃하는 방법을 보여 줍니다.

이 자습서에서는 다음을 하는 방법을 알아볼 수 있습니다.

  • 메일 일회용 암호 또는 사용자 이름(메일)과 암호를 사용하여 사용자를 로그인합니다.
  • 사용자를 로그아웃합니다.
  • 로그인 오류 처리

필수 조건

사용자 로그인

메일 일회용 암호 흐름을 사용하여 사용자를 로그인하려면 메일을 수집하고 사용자가 메일을 확인하는 데 필요한 일회용 암호가 포함된 메일을 보냅니다. 사용자가 유효한 일회용 암호를 입력하면 앱에서 사용자가 로그인됩니다.

암호 흐름이 있는 전자 메일을 사용하여 사용자를 로그인하려면 전자 메일 및 암호를 캡처합니다. 사용자 이름과 암호가 유효한 경우 앱에서 사용자가 로그인됩니다.

사용자를 로그인하려면 다음을 수행해야 합니다.

  1. 다음을 위한 UI(사용자 인터페이스)를 만듭니다.

    • 사용자로부터 메일을 수집합니다. 사용자가 유효한 메일 주소를 입력했는지 확인하기 위해 입력에 대해 유효성 검사를 추가합니다.
    • 사용자 이름(메일)과 암호로 로그인하는 경우 암호를 수집합니다.
    • 메일 일회용 암호로 로그인하는 경우 사용자로부터 메일 일회용 암호를 수집합니다.
    • 전자 메일 일회용 암호로 로그인하는 경우 사용자가 일회성 암호를 다시 보낼 수 있도록 하는 단추를 추가합니다.
  2. UI에서 다음 코드 조각과 같이 선택 이벤트가 로그인을 시작하는 단추를 추가합니다.

        @IBAction func signInPressed(_: Any) {
        guard let email = emailTextField.text else {
            resultTextView.text = "email not set"
            return
        }
    
        nativeAuth.signIn(username: email, delegate: self)
    }
    

    이메일 일회용 암호 흐름을 사용하여 사용자를 로그인하려면 다음 코드 조각을 사용합니다.

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

    전달된 대리자 개체에서 메서드 중 하나를 호출하여 비동기적으로 응답하는 메서드는 signIn(username:delegate) 프로토콜을 SignInStartDelegate 구현해야 합니다. 사용자가 메일 제출 양식에 제공하는 메일 주소를 전달하고 self를 대리인으로 전달합니다.

    암호 흐름이 있는 전자 메일을 사용하여 사용자를 로그인하려면 다음 코드 조각을 사용합니다.

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

    signIn(username:password:delegate) 이 메서드에서는 사용자가 제공한 이메일 주소와 암호를 전달하고 프로토콜을 준수하는 대리자 개체를 SignInStartDelegate 전달합니다. 이 예제에서는 .를 전달합니다 self.

  3. 이메일 일회용 암호 흐름을 사용할 때 프로토콜을 구현 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(username:delegate)을 호출하면 대리자 메서드가 호출됩니다. 가장 일반적인 시나리오에서는 사용자의 메일 주소를 확인하기 위해 코드가 전송되었음을 나타내기 위해 onSignInCodeRequired(newState:sentTo:channelTargetType:codeLength)가 호출됩니다. 코드가 전송된 위치 및 코드에 포함된 자릿수에 대한 세부 정보와 함께 이 대리자 메서드에는 SignInCodeRequiredState 형식의 newState 매개 변수도 있으며 이를 통해 다음과 같은 두 가지 새로운 메서드에 액세스할 수 있습니다.

    • 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."
            result.getAccessToken(delegate: self)
        }
    }
    

    가장 일반적인 시나리오에서는 사용자가 로그인했음을 나타내는 onSignInCompleted(result)에 대한 호출을 받습니다. 결과는 access token을 검색하는 데 사용될 수 있습니다.

    getAccessToken(delegate)은 대리자 매개 변수를 허용하며 CredentialsDelegate 프로토콜에 필수 메서드를 구현해야 합니다.

    가장 일반적인 시나리오에서는 사용자가 access token을 가져왔음을 나타내는 onAccessTokenRetrieveCompleted(result)에 대한 호출을 가져옵니다.

    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)"
        }
    }
    
    
  4. 암호 흐름과 함께 Email을 사용할 때 프로토콜을 구현 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(delegate)은 대리자 매개 변수를 허용하며 CredentialsDelegate 프로토콜에 필수 메서드를 구현해야 합니다.

    가장 일반적인 시나리오에서는 사용자가 access token을 가져왔음을 나타내는 onAccessTokenRetrieveCompleted(result)에 대한 호출을 가져옵니다.

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

로그인 오류 처리

로그인하는 동안 모든 작업이 성공하는 것은 아닙니다. 예를 들어 사용자가 존재하지 않는 메일 주소로 로그인하거나 잘못된 코드를 제출하려고 할 수 있습니다.

  1. signIn(username) 또는 signIn(username, password) 메서드에 대한 오류를 처리하려면 다음 코드 조각을 사용합니다.

    func onSignInStartError(error: MSAL.SignInStartError) {
        if error.isUserNotFound || error.isInvalidUsername {
            resultTextView.text = "Invalid username"
        } else {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    }
    
  2. 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
}

클레임 값에 액세스하는 데 사용하는 키는 사용자 특성을 토큰 클레임으로 추가할 때 지정하는 이름입니다.

토큰 클레임에 사용자 특성 추가 문서에서 기본 제공 및 사용자 지정 특성을 토큰 클레임 으로 추가하는 방법을 알아봅니다.

사용자 로그 아웃

사용자를 로그아웃하려면 onSignInCompleted 콜백에서 받은 MSALNativeAuthUserAccountResult에 대한 참조를 사용하거나 getNativeAuthUserAccount()를 사용하여 캐시에서 로그인한 계정을 가져오고 accountResult 멤버 변수에 참조를 저장합니다.

  1. 여기에 설명된 대로 프로젝트에 대한 키 집합 그룹을 구성합니다.

  2. ViewController 클래스에 새 멤버 변수 var accountResult: MSALNativeAuthUserAccountResult?를 추가합니다.

  3. nativeAuth가 초기화되면 accountResult = nativeAuth.getNativeAuthUserAccount() 줄을 추가하여 캐시된 모든 계정을 검색하도록 viewDidLoad를 업데이트합니다.

  4. signInCompleted 처리기를 업데이트하여 계정 결과를 저장합니다.

    func onSignInCompleted(result: MSALNativeAuthUserAccountResult) {
        resultTextView.text = "Signed in successfully"
    
        accountResult = result
    }
    
  5. 로그아웃 단추를 추가하고 다음 코드를 사용하여 사용자를 로그아웃합니다.

    @IBAction func signOutPressed(_: Any) {
        guard let accountResult = accountResult else {
            print("Not currently signed in")
            return
        }
    
        accountResult.signOut()
    
        self.accountResult = nil
    
        resultTextView.text = "Signed out"
    }
    

앱에서 사용자를 로그아웃하는 데 필요한 모든 단계를 성공적으로 완료했습니다. 애플리케이션을 빌드하고 실행합니다. 모두 문제가 없는 경우 로그아웃 단추를 선택하여 성공적으로 로그아웃할 수 있습니다.

다음 단계

자습서: iOS 앱에서 셀프 서비스 암호 재설정