AWS 시작하기

Flutter 애플리케이션 구축

AWS Amplify를 사용하여 간단한 Flutter 애플리케이션 생성

모듈 3: 인증 추가

이 모듈에서는 Amplify CLI와 라이브러리를 사용하여 인증을 구성하고 앱에 추가합니다.

소개

앱에 추가할 첫 번째 Amplify 범주는 인증입니다. Amplify는 내부적으로 Amazon Cognito를 사용하여 사용자 풀과 자격 증명 풀을 관리합니다.

이 모듈에서는 사용자를 등록, 확인, 로그인/로그아웃하는 방법을 알아봅니다. 여기서는 코드 단 몇 줄로 각 화면의 기능을 구현해볼 것입니다.

배우게 될 내용

  • 인증 범주 구성
  • 사용자 등록
  • 사용자 이메일 확인
  • 인증된 사용자 로그인
  • 인증된 사용자 로그아웃

주요 개념

인증 – 인증은 사용자를 확인하고 관리하여 앱의 리소스와 상호 작용할 수 있도록 하는 프로세스입니다.

 완료 시간

10분

 사용되는 서비스

구현

  • 인증 서비스 생성

    Arempify 프로젝트에 인증 서비스를 추가하려면 터미널을 통해 프로젝트의 루트 디렉터리에서 다음 명령을 실행해야 합니다.

    amplify add auth

    인증 서비스 구성에 대한 몇 가지 질문이 표시됩니다. Enter 키를 눌러 각 질문에 대해 기본값을 선택합니다. 결과로 표시되는 출력은 다음과 같습니다.

    ➜  photo_gallery git:(master) ✗ amplify add auth
    Using service: Cognito, provided by: awscloudformation
    
     The current configured provider is Amazon Cognito.
    
     Do you want to use the default authentication and security configuration? Default configuration
     Warning: you will not be able to edit these selections.
     How do you want users to be able to sign in? Username
     Do you want to configure advanced settings? No, I am done.

    인증 리소스가 완전히 구성되면 다음과 같은 출력이 표시됩니다.

    Successfully added resource photogallery42b5391b locally

    위의 출력에서 보듯이 리소스가 로컬로만 추가되었습니다. 로컬에서 변경한 내용으로 백엔드를 구성하려면 다음 명령을 실행해야 합니다.

    amplify push

    로컬 변경 내용을 백엔드로 보내기 전에, Amplify CLI는 상태 보고서를 표시하여 다음 변경 사항을 적용할지 여부를 확인합니다.

    Current Environment: dev
    
    | Category | Resource name        | Operation | Provider plugin   |
    | -------- | -------------------- | --------- | ----------------- |
    | Auth     | photogallery42b5391b | Create    | awscloudformation |
    ? Are you sure you want to continue? Yes

    로컬 변경 내용을 백엔드로 보내기 전에, Amplify CLI는 상태 보고서를 표시하여 다음 변경 사항을 적용할지 여부를 확인합니다.

    ✔ All resources are updated in the cloud

    또한 /lib/amplifyconfiguration.dart 파일을 보면서 인증 값을 검사하여 인증 리소스가 제대로 구성되었는지 확인할 수도 있습니다.

  • 종속 구성 요소 설치

    Visual Studio 코드로 돌아가 pubspec.yaml을 열고 다음 종속성을 추가합니다.

    ... # amplify_core: '<1.0.0'
    
    amplify_auth_cognito: '<1.0.0'
    
    ... # dev_dependencies:

    이제 파일을 저장하여 Visual Studio 코드가 Amplify Auth Cognito 플러그인을 설치하도록 합니다. 저장 시에 종속 구성 요소가 설치되어 있지 않은 경우 터미널에서 $ flutter pub get을 실행할 수도 있습니다.

    다음과 같은 출력이 표시됩니다.

    exit code 0
  • 플러그인 구성

    Auth 종속 구성 요소가 설치되었으므로 이제 Auth 플러그인을 _main.dart 파일의 _MyAppState._configureAmplify()에 있는 Amplify 인스턴스에 추가할 수 있습니다.

    ... // void _configureAmplify() async {
    
    _amplify.addPlugin(authPlugins: [AmplifyAuthCognito()]);
    
    ... // try {

    이제 앱을 실행하고 로그에 성공 메시지가 여전히 표시되는지 확인합니다.

    성공 메시지가 계속 표시되면 이제 인증 흐름의 기능 구현을 시작할 수 있습니다. 그렇지 않은 경우 위의 단계를 반복하거나 Amplify 초기화 모듈에서 모든 단계를 수행했는지 확인합니다.

  • 기능 구현

    Flutter 앱 만들기 모듈에서는 호출된 함수를 기반으로 AuthState의 업데이트를 처리하도록 AuthService를 구현했습니다. 이제 사용자가 각 프로세스를 성공적으로 완료했을 때만 상태를 업데이트하도록 각각의 기능을 업데이트해야 합니다.

    auth_service.dart에서 AuthService에 AuthCredentials 속성을 추가합니다.

    ... // final authStateController = StreamController<AuthState>();
    
    AuthCredentials _credentials;
    
    ... // void showSignUp() {

    이 속성은 사용자가 이메일 주소를 확인한 후 즉시 로그인할 수 있도록 등록 프로세스를 진행하는 동안 SignUpCredentials를 메모리에 저장하는 데 사용됩니다. 이렇게 하지 않으면 사용자가 로그인 화면으로 이동하여 수동으로 로그인해야 합니다.

    signUpWithCredentials를 다음으로 업데이트합니다.

    // 1
    void signUpWithCredentials(SignUpCredentials credentials) async {
      try {
        // 2
        final userAttributes = {'email': credentials.email};
    
        // 3
        final result = await Amplify.Auth.signUp(
            username: credentials.username,
            password: credentials.password,
            options: CognitoSignUpOptions(userAttributes: userAttributes));
    
        // 4
        if (result.isSignUpComplete) {
          loginWithCredentials(credentials);
        } else {
          // 5
          this._credentials = credentials;
    
          // 6
          final state = AuthState(authFlowStatus: AuthFlowStatus.verification);
          authStateController.add(state);
        }
      
      // 7
      } on AuthError catch (authError) {
        print('Failed to sign up - ${authError.cause}');
      }
    }
    1. 등록 프로세스 중에 await를 사용하므로 이 함수는 비동기식으로 업데이트되어야 합니다.
    2. 등록 프로세스의 일부로서 사용자의 이메일을 전달할 userAttributes를 생성해야 합니다.
    3. Cognito에 등록하기 위해 이메일이 포함된 사용자 속성과 함께 자격 증명으로 제공된 사용자 이름 및 암호를 전달합니다. 이는 비동기 프로세스이므로 await 키워드를 사용해야 합니다.
    4. 결과가 성공적으로 반환되면 다음 단계로 이메일을 확인합니다. 어떤 이유로든 등록 프로세스가 완료되면 사용자를 앱에 로그인시키기만 하면 됩니다.
    5. 사용자가 이메일을 확인할 때 사용하도록 _credentials에 SignUpCredentials를 저장합니다.
    6. 앞서 했던 것과 마찬가지로 AuthState를 verification으로 업데이트하지만, 여기서는 성공적으로 로그인하고 등록 프로세스가 완료되지 않은 것을 확인한 후에만 업데이트합니다.
    7. 어떤 이유로든 등록이 실패하면 로그에 오류를 출력하기만 하면 됩니다.

    verifyCode를 다음으로 업데이트합니다.

    // 1
    void verifyCode(String verificationCode) async {
     try {
       // 2
       final result = await Amplify.Auth.confirmSignUp(
           username: _credentials.username, confirmationCode: verificationCode);
    
       // 3
       if (result.isSignUpComplete) {
         loginWithCredentials(_credentials);
       } else {
         // 4
         // Follow more steps
       }
     } on AuthError catch (authError) {
       print('Could not verify code - ${authError.cause}');
     }
    }
    1. signUpWithCredentials의 경우와 마찬가지로 verifyCode도 비동기 하무로 표시해야 합니다.
    2. _credentials를 사용하여 사용자 이름을 제공하고 입력한 코드를 VerificationPage에서 confirmSignUp으로 전달합니다.
    3. confirmSignUp의 결과가 등록이 완료되었음을 나타내면 등록 중에 생성된 _credentials로 사용자 로그인을 시도합니다. 사용자가 Amplify에 로그인해야 하므로 성공한 경우에는 AppState를 더 이상 업데이트하지 않습니다.
    4. 등록이 완료되지 않은 경우 결과를 사용하여 등록을 완료하기 위해 수행해야 할 추가 단계를 알아봅니다. 앱에서 이런 상황이 발생해서는 안 됩니다.

    인증 흐름의 등록 부분을 구현했고, 이제 로그인 부분을 업데이트해야 합니다. loginWithCredentials를 다음으로 업데이트합니다.

    // 1
    void loginWithCredentials(AuthCredentials credentials) async {
     try {
       // 2
       final result = await Amplify.Auth.signIn(
           username: credentials.username, password: credentials.password);
    
       // 3
       if (result.isSignedIn) {
         final state = AuthState(authFlowStatus: AuthFlowStatus.session);
         authStateController.add(state);
       } else {
         // 4
         print('User could not be signed in');
       }
     } on AuthError catch (authError) {
       print('Could not login - ${authError.cause}');
     }
    }
    1. loginWithCredentials는 AuthCredentials를 파라미터로 사용하므로 LoginCredentials 또는 SignUpCredentials 중 어떤 것이 전달되더라도 작동합니다.
    2. AuthCredentials 사용자 이름과 암호를 Amplify 로그인 메서드에 전달하고 결과를 기다립니다.
    3. 로그인에 성공하고 결과의 isSignedIn 속성에서 사용자가 이제 로그인되었음이 확인될 경우 상태를 session으로 업데이트합니다.
    4. 이 앱에서는 이 상태에 도달해서는 안 됩니다. 사용자가 잘못된 자격 증명을 입력하거나 다른 오류를 수신하면 캐치 블록이 발생합니다.

    이제 logOut 메서드를 업데이트합니다.

    void logOut() async {
     try {
       // 1
       await Amplify.Auth.signOut();
    
       // 2
       showLogin();
     } on AuthError catch (authError) {
       print('Could not log out - ${authError.cause}');
     }
    }
    1. 옵션을 전달하지 않고 Auth.signOut()을 호출하면 모든 디바이스에서 사용자를 로그아웃하는 대신 이 디바이스의 사용자만 로그아웃합니다.
    2. showLogin() 메서드를 재사용하여, 로그아웃이 성공하면 상태를 업데이트하고 사용자를 로그인 화면으로 되돌릴 수 있습니다.

    마지막으로, 사용자가 앱을 닫았지만 이전 세션에서 이미 로그인된 경우 자동으로 사용자를 로그인할 수 있어야 합니다. 이 최종 함수를 AuthService에 추가합니다.

    void checkAuthStatus() async {
     try {
       await Amplify.Auth.fetchAuthSession();
    
       final state = AuthState(authFlowStatus: AuthFlowStatus.session);
       authStateController.add(state);
     } catch (_) {
       final state = AuthState(authFlowStatus: AuthFlowStatus.login);
       authStateController.add(state);
     }
    }

    checkAuthStatus가 현재 AuthSession을 가져오려고 시도합니다. 성공하면 사용자가 로그인됩니다. 가져오기가 실패하면 사용자가 로그인되지 않았으므로 LoginPage를 표시해야 합니다.

    이때 _MyAppState의 initState 메서드 내에서 showLogin을 호출합니다. 이를 checkAuthStatus로 변경합니다.

    ... // _configureAmplify();
    
    _authService.checkAuthStatus();
    
    ... // initState closing }

    이는 기존 인증 흐름을 보완하는 데 필요한 유일한 수정 사항입니다. 이 앱을 빌드하고 실행하면 등록하고, 이메일을 확인하고, 로그아웃한 후 다시 로그인할 수 있습니다.

    EndofModule3-gif

결론

사진 갤러리 앱에 사용자 인증을 추가했습니다. 다음 모듈에서는 앱에 스토리지를 추가합니다.

이 모듈이 유용했습니까?

감사합니다.
좋아하는 사항을 알려주세요.
닫기
실망을 드려 죄송합니다.
오래되었거나 혼란스럽거나 부정확한 사항이 있습니까? 피드백을 제공하여 이 자습서를 개선할 수 있도록 도와주십시오.
닫기

스토리지 추가