AWS 시작하기
iOS 애플리케이션 구축
AWS Amplify를 사용하여 단순한 iOS 애플리케이션 생성
모듈 3: 인증 추가
이 모듈에서는 Amplify CLI와 라이브러리를 사용하여 인증을 구성하고 앱에 추가합니다.
소개
다음으로 추가할 기능은 사용자 인증입니다. 이 모듈에서는 관리형 사용자 자격 증명 공급자인 Amazon Cognito를 사용하여 Amplify CLI와 라이브러리에서 사용자를 인증하는 방법을 알아봅니다.
또한 Cognito를 통해 호스팅되는 사용자 인터페이스를 사용하여 단 몇 줄의 코드로 사용자 가입, 로그인, 암호 재설정을 허용하는 전체 사용자 인증 흐름을 제공하는 방법도 배웁니다.
“호스팅되는 사용자 인터페이스”를 사용한다는 것은 애플리케이션의 사용자 로그인 및 가입 인터페이스 흐름에 Cognito 웹 페이지를 활용한다는 것을 의미합니다. 앱의 사용자는 Cognito를 통해 호스팅되는 웹 페이지로 리디렉션되며 로그인 후 다시 앱으로 리디렉션됩니다. 물론, Cognito와 Amplify는 기본 UI도 지원합니다. 이 워크숍 지침에서 사용자 지정 인증 UI에 대해 자세히 알아볼 수 있습니다.
배우게 될 내용
- 인증 서비스 생성 및 배포
- Cognito 호스팅 UI 인증을 포함하도록 iOS 앱 구성
주요 개념
Amplify 라이브러리 – Amplify 라이브러리는 웹 또는 모바일 애플리케이션에서 AWS 서비스와 상호 작용할 수 있도록 해줍니다.
인증 – 소프트웨어에서 인증이란 인증 서비스 또는 API를 사용하여 사용자의 자격 증명을 확인하고 관리하는 프로세스를 의미합니다.
완료 시간
10분
사용되는 서비스
구현
-
인증 서비스 생성
인증 서비스를 생성하려면 터미널을 열고 다음 명령을 실행합니다.
amplify add auth ? Do you want to use the default authentication and security configuration? Select Default configuration with Social Provider and press enter ? How do you want users to be able to sign in? Select the default Username and press enter ? Do you want to configure advanced settings? Select the default No, I am done and press enter ? What domain name prefix do you want to use? Select the default and press enter Enter your redirect signin URI: type gettingstarted:// and press enter ? Do you want to add another redirect signin URI? Select the default N and press enter Enter your redirect signout URI: type gettingstarted:// and press enter ? Do you want to add another redirect signout URI? Select the default N and press enter ? Select the social providers you want to configure for your user pool: do not select any provider and press enter
다음 메시지가 표시되면 성공적으로 구성된 것입니다(정확한 리소스 이름은 다름).
Successfully added resource iosgettingstartedfc5a4717 locally
-
인증 서비스 배포
인증 서비스가 로컬로 구성되었으므로, 이제 클라우드에 배포할 수 있습니다. 터미널에서 프로젝트 디렉터리로 이동하여 다음 명령을 실행합니다.
amplify push # press Y when asked to continue
잠시 후에 다음 메시지가 표시됩니다.
✔ All resources are updated in the cloud Hosted UI Endpoint: https://iosgettingstarted-dev.auth.eu-central-1.amazoncognito.com/ Test Your Hosted UI Endpoint: https://iosgettingstarted-dev.auth.eu-central-1.amazoncognito.com/login?response_type=code&client_id=1234567890&redirect_uri=gettingstarted://
-
프로젝트에 Amplify 인증 라이브러리 추가
코드 작업을 시작하기 전에 Amplify 인증 라이브러리를 프로젝트의 종속성에 추가합니다. Podfile 파일을 열고 AmplifyPlugins/AWSCognitoAuthPlugin을 사용하여 해당 줄을 추가하거나 아래의 전체 파일을 복사해 붙여 넣습니다.
# you need at least version 13.0 for this tutorial, more recent versions are valid too platform :ios, '13.0' target 'getting started' do # Comment the next line if you don't want to use dynamic frameworks use_frameworks! # Pods for getting started pod 'Amplify', '~> 1.0' # required amplify dependency pod 'Amplify/Tools', '~> 1.0' # allows to call amplify CLI from within Xcode pod 'AmplifyPlugins/AWSCognitoAuthPlugin', '~> 1.0' # support for Cognito user authentication end
터미널에서 다음 명령을 실행합니다.
pod install
이 명령은 몇 초 안에 완료됩니다. 다음 명령이 표시됩니다. 실제 버전 번호는 다를 수 있습니다.
Analyzing dependencies Downloading dependencies Installing AWSAuthCore (2.14.1) Installing AWSCognitoIdentityProvider (2.14.1) Installing AWSCognitoIdentityProviderASF (1.0.1) Installing AWSCore (2.14.1) Installing AWSMobileClient (2.14.1) Installing AWSPluginsCore (1.0.4) Installing AmplifyPlugins (1.0.4) Generating Pods project Integrating client project Pod installation complete! There are 3 dependencies from the Podfile and 8 total pods installed.
-
런타임 시 Amplify 인증 라이브러리 구성
Xcode로 돌아와서 Backend.swift 파일을 엽니다. Backend 클래스에서
- AmplifyPlugins에 대한 import 문을 추가합니다.
- 이전 섹션에서 추가한 amplify 초기화 코드에 한 줄을 추가합니다.
완성된 코드 블록은 다음과 같습니다.
// at the top of the file import AmplifyPlugins private init () { // initialize amplify do { try Amplify.add(plugin: AWSCognitoAuthPlugin()) try Amplify.configure() print("Initialized Amplify") } catch { print("Could not initialize Amplify: \(error)") } }
정상적으로 작동하는지 확인하기 위해 프로젝트를 빌드합니다. [제품(Product)] 메뉴에서 [빌드(Build)]를 선택하거나 ⌘B를 입력합니다. 오류가 발생하지 않아야 합니다.
-
런타임 시 인증 트리거
나머지 코드 변경은 사용자의 상태(로그인 여부)를 추적하고, 사용자가 로그인하지 않은 경우 SignIn/SignUp 사용자 인터페이스를 트리거합니다.
a. SignIn 및 SignOut 코드를 추가합니다. backend 클래스의 아무 위치에나 다음 3개의 메서드를 추가합니다.
// MARK: - User Authentication // signin with Cognito web user interface public func signIn() { _ = Amplify.Auth.signInWithWebUI(presentationAnchor: UIApplication.shared.windows.first!) { result in switch result { case .success(_): print("Sign in succeeded") case .failure(let error): print("Sign in failed \(error)") } } } // signout public func signOut() { _ = Amplify.Auth.signOut() { (result) in switch result { case .success: print("Successfully signed out") case .failure(let error): print("Sign out failed with error \(error)") } } } // change our internal state, this triggers an UI update on the main thread func updateUserData(withSignInStatus status : Bool) { DispatchQueue.main.async() { let userData : UserData = .shared userData.isSignedIn = status } }
b. 인증 허브 리스너 추가
인증 상태의 변경 사항을 추적하기 위해 Amplify가 전송한 인증 이벤트를 구독하는 코드를 추가합니다. Backend.init() 메서드의 허브를 초기화합니다.
인증 이벤트가 수신되면 updateUserData() 메서드를 호출합니다. 이 메서드는 UserData 객체를 동기화합니다. UserData.isSignedIn 속성은 @Published입니다. 즉, 값이 변경되면 사용자 인터페이스가 자동으로 새로 고쳐집니다.
애플리케이션 시작 시간에 이전 인증 상태를 확인하는 코드도 추가합니다. 이 코드는 애플리케이션이 시작될 때 Cognito 세션이 있는지 확인하고 UI를 적절히 업데이트합니다.
Backend.init()에서 Amplify의 초기화 뒤에 다음 코드를 추가합니다.
// in private init() function // listen to auth events. // see https://github.com/aws-amplify/amplify-ios/blob/master/Amplify/Categories/Auth/Models/AuthEventName.swift _ = Amplify.Hub.listen(to: .auth) { (payload) in switch payload.eventName { case HubPayload.EventName.Auth.signedIn: print("==HUB== User signed In, update UI") self.updateUserData(withSignInStatus: true) case HubPayload.EventName.Auth.signedOut: print("==HUB== User signed Out, update UI") self.updateUserData(withSignInStatus: false) case HubPayload.EventName.Auth.sessionExpired: print("==HUB== Session expired, show sign in UI") self.updateUserData(withSignInStatus: false) default: //print("==HUB== \(payload)") break } } // let's check if user is signedIn or not _ = Amplify.Auth.fetchAuthSession { (result) in do { let session = try result.get() // let's update UserData and the UI self.updateUserData(withSignInStatus: session.isSignedIn) } catch { print("Fetch auth session failed with error - \(error)") } }
c. 사용자 인터페이스 코드 업데이트
마지막 코드 변경은 사용자 인터페이스와 관련된 것입니다. ContentView에 ZStack을 추가합니다. UserData.isSignedIn의 값에 따라 UI에 SigninButton 또는 기본 목록 보기가 표시됩니다.
ContentView.swift를 열고 ContentView 구조체의 본문을 바꿉니다.
var body: some View { ZStack { if (userData.isSignedIn) { NavigationView { List { ForEach(userData.notes) { note in ListRow(note: note) } } .navigationBarTitle(Text("Notes")) .navigationBarItems(leading: SignOutButton()) } } else { SignInButton() } } }
같은 파일에서 SignInButton 및 SignOutButton 보기를 추가합니다.
struct SignInButton: View { var body: some View { Button(action: { Backend.shared.signIn() }){ HStack { Image(systemName: "person.fill") .scaleEffect(1.5) .padding() Text("Sign In") .font(.largeTitle) } .padding() .foregroundColor(.white) .background(Color.green) .cornerRadius(30) } } } struct SignOutButton : View { var body: some View { Button(action: { Backend.shared.signOut() }) { Text("Sign Out") } } }
정상적으로 작동하는지 확인하기 위해 프로젝트를 빌드합니다. [제품(Product)] 메뉴에서 [빌드(Build)]를 선택하거나 ⌘B를 입력합니다. 오류가 발생하지 않아야 합니다.
d. Info.plist 업데이트
마지막으로, Cognito 호스팅 사용자 인터페이스로 제공되는 웹 인증 시퀀스의 끝에 앱이 시작되는지 확인해야 합니다. gettingstarted URI 체계를 앱의 Info.plist 파일에 추가합니다.
Xcode에서 Info.plist 파일을 선택하고 마우스 오른쪽 버튼으로 클릭한 다음 [다음으로 열기, 소스 코드(Open As, Source Code)]를 선택합니다.
아래의 <key> 및 <array> 요소를 맨 위의 <dict> 요소 안에 추가합니다.
<plist version="1.0"> <dict> <!-- YOUR OTHER PLIST ENTRIES HERE --> <!-- ADD AN ENTRY TO CFBundleURLTypes for Cognito Auth --> <!-- IF YOU DO NOT HAVE CFBundleURLTypes, YOU CAN COPY THE WHOLE BLOCK BELOW --> <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>gettingstarted</string> </array> </dict> </array> <!-- ... --> </dict>
e. 구축 및 테스트
정상적으로 작동하는지 확인하기 위해 프로젝트를 빌드합니다. 제품(Product) 메뉴에서 실행(Run)을 선택하거나 ⌘R을 입력합니다. 오류가 발생하지 않아야 합니다. [로그인(Sign In)] 버튼에서 앱이 시작됩니다.
전체 가입 흐름은 다음과 같습니다.