Auto Sign In with Cognito / Amplify Authenticator Components?

扶醉桌前 提交于 2019-12-24 19:25:51

问题


I'm using the Amplify authenticator component (described here) with Cognito User Pools.

Right now, adding the basic authenticator to html takes the user through the following process automatically:

1) Sign up
2) Enter verification code sent to email
3) Sign-in: Re-enter user name and password

This is based on just adding to html:

<amplify-authenticator></amplify-authenticator>

So new users sign up, and then right away need to sign in. It would be better if they were automatically signed-in, so that upon entering their verification code they went right into the app. This would be a common authentication flow.

Is there a way to have automatic sign-in like this while still using the authenticator components?

I see a github discussion about this topic here, but it is not resolved.


回答1:


I have figured it out for my purposes. The key is that the Amplify components (authenticator, as well as the individual components) give out information about the state after the user takes action. You can listen for this info, and then programmatically sign in the user once you get the "signIn" state.

These are the states, as described here (I am using Angular):

'signUp' //when you want to show signUp page
'confirmSignUp' //the user has probably just submitted info for signing up, and now you want to show the "confirm" page--like the page where they can enter a verification code

'signIn' //this is the key for these purposes. This is when you want to show the sign in page. In the basic authenticator structure, this happens just after the user has been signed up. So this is where you can automatically sign in the user with Auth.signIn, like below.

'confirmSignIn' //I assume this is after user has submitted the sign in form and you want a confirm page to show
'signedIn' //presumably after user has been fully signed in (not confirmed)
'forgotPassword' //presumably when the forgotPassword form loads (not confirmed)
'requireNewPassword' //presumably when user clicks 'reset password' (not confirmed)

So, using Authenticator, you can listen for the 'signIn' event and automatically sign in the user then. Note however that, while this will sign in the user automatically, Authenticator may still show the sign in page while this action is being processed. You can hide this page, or just use the individual Amplify components, like I show in #2 below.

Even better would be if Amplify/Cognito could just have an option for the developer to select automatic sign in after sign up when they set up Cognito. Automatic sign in on sign up would be in line with modern authentication practice, and would be better for user flow. I do not find this option anywhere. If anyone at Amplify/Cognito is listening, please consider adding this feature.

Note: There seem to be some issues that can arise when using these components. For example--with the authenticator, if the user submits info to sign up, but then leaves the page before entering their verification code: the next time they try to access the app they may have trouble, because they can't go through the sign up process again (a user has already been created), but they also can't sign in (because they've never verified). Some more discussion on that is here.

Additionally, I have found error messages to be an issue. These Amplify components automatically show error messages, and some of them from Cognito are technical messages I would never want a user to see (stuff that talks about "user id" and lambda functions, depending on the random error). There may be a way to customize these, like described here, but be sure you test a lot of different scenarios to see what might happen in terms of the error messages.

If these issues prove problematic for you (like they have for me), you may want to use your own forms instead, and then use Auth.signIn() and related Amplify methods, instead of these components.

But, for auto-signing-in with Amplify components, here is code that worked for me:

1. Using Amplify's Authenticator component:

html

<amplify-authenticator></amplify-authenticator> 

ts:

    import { AmplifyService } from 'aws-amplify-angular';
    import Auth from '@aws-amplify/auth';

    Export class AuthComponent implements OnInit {

      state: any;
      newUser: any;
      username: any;
      password: any;

      constructor(public amplifyService: AmplifyService){
          this.amplifyService.setAuthState(this.authState) //may be not required     
          this.amplifyService.authStateChange$ //listening for state changes
                .subscribe(authState => {
                    this.state = authState.state

                    if (this.state === 'confirmSignUp'){
                      console.log('user just signed up, now on verify code form')
                      this.newUser = authState.user 
                      this.password = this.newUser.username
                      let checkPassword = this.newUser.username.password
                      if (checkPassword != 'undefined') { 
                         this.password = checkPassword
                      /*Note here: I have coded it this way because it looks like the authenticator runs two events when the user hits "sign up". In the first event, you can get the user's password, to be used in the Auth.signIn() function below. In the second event, you can only get the user's username (and password would show up as undefined if you grabbed it there). So we need a way to get the password from the first event.*/
                      } 
                   }

                   if ((this.newUser) && (this.state === 'signIn')){//this.newUser included because otherwise this event will fire anytime the sign in page loads--even for returning users trying to sign in (who you would not want to sign in automatically)  
                   console.log('user has just finished signing up)
                   Auth.signIn(this.username, this.password).then(()=>{//there might be more parameters, like email, first name and last name, phone number, etc. here--depends on your Cognito settings
                     console.log('should be signed in now! You can navigate away from this page')
                     }).catch((error)=>{
                       console.log('error here = ' + error.message + ', error code = ' + error.code)
                   })
                  }
             })
        }
 }

Like I mentioned above, this will show the "sign in" page while the Auth.signIn() function is processing. To avoid that, you could have an *ngIf, saying hide the page when this.state = "signIn".

2. Using Individual Amplify Auth Components:

In the below, the page will load with the sign up form.

Once the user enters their details and clicks sign up, the page will show the "confirm sign up" form, which is where the user enters a verification code that Cognito has sent to him/her (depending on your Cognito settings).

Then, once the user is signed up, you can get the "signIn" state like above, and automatically sign the user in:

html:

    <amplify-auth-sign-up [authState]="authState" *ngIf="showSignUp"></amplify-auth-sign-up>
    <amplify-auth-confirm-sign-up [authState]="authState" *ngIf="showVerify"></amplify-auth-confirm-sign-up> 

ts:

   import { AmplifyService } from 'aws-amplify-angular';
   import { AuthState } from 'aws-amplify-angular/dist/src/providers';
   import Auth from '@aws-amplify/auth';  

   Export class AuthComponent implements OnInit {

    public authState: AuthState
    public newUser: any
    public username: any
    public password: any
    public state: any
    public showSignUp = true
    public showVerify = false

    constructor(public amplifyService: AmplifyService) {
         this.authState ={//the individual Amplify components require a state be set
           user: null,
           state: 'signUp' 
         }

         this.amplifyService.setAuthState(this.authState)  //this might not be required

         this.amplifyService.authStateChange$ //listening for state changes. 
                .subscribe(authState => {   
                    this.state = authState.state 
                    if (this.state === 'confirmSignUp'){//get change in state
                       this.newUser = authState.user  
                       this.username = this.newUser.username  
                     let checkPassword = this.newUser.username.password
                      if (checkPassword != 'undefined') { 
                       this.password = checkPassword
                        /*Note here: I have coded it this way because it looks like the authenticator runs two events when the user hits "sign up". In the first event, you can get the user's password, to be used in the Auth.signIn() function below. In the second event, you can only get the user's username (and password would show up as undefined if you grabbed it there). So we need a way to get the password from the first event.*/ 
                     }                     
                     this.authState ={
                          user: authState.user,
                         state: 'confirmSignUp'
                      }

                      this.showSignUp = false
                       this.showVerify = true
                   }

                  if ((this.newUser) && (this.state === 'signIn')){//this.newUser included because otherwise this event will fire anytime the sign in page loads--even for returning users trying to sign in (who you would not want to sign in automatically)  
                   console.log('user has just finished signing up)
                   Auth.signIn(this.username, this.password).then(()=>{//there might be more parameters, like email, first name and last name, phone number, etc. here--depends on your Cognito settings
                     console.log('should be signed in now! You can navigate away from this page')
                     }).catch((error)=>{
                       console.log('error here = ' + error.message + ', error code = ' + error.code)
                   })
                 }
             })
        }
  }


来源:https://stackoverflow.com/questions/59254358/auto-sign-in-with-cognito-amplify-authenticator-components

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!