Recent updates to the aws-amplify hub make it easier to listen to (AWS Cognito) auth state changes without using the aws-amplify-angular package. I...
For further actions, you may consider blocking this person and/or reporting abuse
Great post! I've implemented this for my Angular app, but I'm using a third party identity provider and the hosted UI and I'm having an issue getting the authenticated state set correctly on the first load.
The issue is with the Authenticated Code Grant. When the app loads initially, it passes the code to Amplify which then makes calls out to Cognito to obtain the tokens and user information. The time delay causes all the
isLoggedIn
states to be marked as false. A page refresh then shows the user as logged in correctly as the tokens are all in local storage now.Any advice?
Thanks,
it's hard to see the error without code, but I would suggest trying these steps:
it sounds to me like it might be an Angular changeDetection problem.
Apologies! Below is my basic AuthGuard.
You can just do
Do not subscribe here! In your case it will resolve to false immediately and never actually care about the subscribe callback. Also it will create a leak, if you do not unsubscribe. When returning an Observable, Angular will do it for you!
What I actually do is talk to the Amplify Auth class directly:
I have to check for the Browser platform, because Amplify is not SSR compatible. But this will directly look at the saved value in localStorage.
Thanks for the suggestions!!
I've tried both, and still get 'not authenticated' on the first load/login of the app. The only thing I've been able to get to work is adding a timeout in the auth service to give it time to populate the localstorage. Here is a related github issue: github.com/aws-amplify/amplify-js/...
When the ADFS system redirects the user to the site with a auth code (instead of token) Amplify has to make multiple calls out to Cognito, and the canActivate is not waiting for the calls Amplify is making to return.
I'm going to try adding a loop in the auth service that checks for the localstorage before performing any .next actions. I'll let you know how it turns out and post my solution!
Edit: This seems to do the trick:
Would love to hear any other ideas on waiting on the tokens to populate.
One note about my previous comment. If you return an observable in a guard, you need to make sure it is completed. To do that, you can just add take(1):
What you can think about as well is to wait for rendering the app until the Auth.currentAuthenticatedUser() resolves.
Wrap the AppComponent's HTML with a
BehaviourSubjects are so powerful for state management. I find that in most cases I never need Redux or NgRx when utilizing behaviorSubjects to implement dataStorage services. Cool article. I found it searching for tips on using Amplify with Angular. Cheers!
Thanks for sharing this awesome solution!
2 things I needed to change:
Auth.currentAuthenticatedUser()
to retrieve it.This post was amazing! It really helped me get my feet underneath me with the AWS library. I do have a simple question. Are you getting errors with executing code in the Hub.Listen() callback using THIS? I nested Auth.CurrentAuthenticatedUser into that callback block and that code never gets executed if I use THIS in the Auth.CurrentAuthenticatedUser. Thanks!
Figured it out for anyone whoever discovers this comment later ..... at the time of this post, executing a behavior subject inside the Hub.Listen callback, you must use NgZone so angular can detect there is a change.
this is so good! its everything the way i wanted to implement laid out in a platter.
going through amplify docs wasnt fun.
thanks