Search code examples
angularamazon-cognitoaws-amplify

Amplify v6 not returning token to angular from cognito hosted ui


I'm on Angular 15 and I updated from aws-amplify v5 to v6. I had to restructure some of the calls since it was a breaking change and I have everything connected I thought, but my app doesn't authenticate anymore. I think it has something to do with my auth service because that's the only change from when it was working. I'm using the Cognito Hosted UI currently.

Here's my auth service currently.

import { Injectable } from '@angular/core';
import { BehaviorSubject, Subject } from 'rxjs';
import { Amplify } from 'aws-amplify';
import { environment } from 'src/environments/environment';
import { fetchAuthSession, getCurrentUser, signOut } from 'aws-amplify/auth';

Amplify.configure({
  Auth: {
    Cognito: {
      userPoolId: environment.cognito.userPoolId,
      userPoolClientId: environment.cognito.appClientId,
      signUpVerificationMethod: 'code',
      loginWith: {
        oauth: {
          domain: 'my-app.auth.us-east-1.amazoncognito.com',
          scopes: [
            'email',
            'profile',
            'openid',
            'aws.cognito.signin.user.admin',
          ],
          redirectSignIn: [environment.redirectUrl],
          redirectSignOut: ['http://localhost:4200/'],
          responseType: 'code',
        },
      },
    },
  },
});
const currentConfig = Amplify.getConfig();
console.log('currentConfig', currentConfig);

@Injectable({ providedIn: 'root' })
export class AuthService {
  authIsLoading = new BehaviorSubject<boolean>(true);
  authDidFail = new BehaviorSubject<boolean>(false);
  authStatusChanged = new Subject<boolean>();
  public loggedIn = false;

  async getAuthenticatedUser() {
    try {
      const { username, userId, signInDetails } = await getCurrentUser();

      console.log(`The username: ${username}`);

      console.log(`The userId: ${userId}`);

      console.log(`The signInDetails: ${signInDetails}`);
      return signInDetails;
    } catch (err) {
      console.log(err);
      throw err;
    }
  }

  async getRefreshedAuthenticatedUser() {
    try {
      const { accessToken, idToken } = (await fetchAuthSession()).tokens ?? {};
      return { accessToken, idToken };
    } catch (err) {
      console.log(err);
      return null;
    }
  }

  async logout() {
    try {
      await signOut();
      this.authStatusChanged.next(false);
    } catch (error) {
      console.log(error);
    }
  }

  async isAuthenticated(): Promise<boolean> {
    const user = await this.getAuthenticatedUser();
    console.log('USERTIME', user);
    return !!user;
  }
}

In addition I set up a lambda preAuth and postAuth cognito trigger functions to make sure those steps happen and both got an event. So it's just amplify not giving me my token for some reason. Also on my app in amplify v5 the localStorage had these tokens there, but they aren't there in v6

enter image description here

Here's the 302 redirect from cognito hosted UI

HTTP/2 302 
date: Mon, 20 Nov 2023 23:51:41 GMT
content-length: 0
location: http://localhost:4200/redirect/?code=0274cb71-2add-4bff-8f8f-9d004ea14438
content-security-policy-report-only: script-src https://d3oia8etllorh5.cloudfront.net https://my-view-app.auth.us-east-1.amazoncognito.com; style-src https://d3oia8etllorh5.cloudfront.net https://my-app.auth.us-east-1.amazoncognito.com; img-src https://placeholder.cloudfront.net https://my-app.auth.us-east-1.amazoncognito.com; report-uri https://my-app.auth.us-east-1.amazoncognito.com/cspreport
x-amz-cognito-request-id: dsfssd-ed22-4d41-a4cf-45add22e55fa
set-cookie: XSRF-TOKEN=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/; Secure; HttpOnly; SameSite=Lax
XSRF-TOKEN=2bf2bb29-e8b7-40ff-9914-7b41a7ac3d18; Path=/; Secure; HttpOnly; SameSite=Lax
cognito="H4sIAAAAAAAAAAH9AAL/XiELDZtKtGVzEjYV00NzW5p9zaydExOStPySiR1SBPOyKnEgsl4e53j3MTLptV8bCJo8elZBNSGu/jvy3TtJB70Z3sqYlrbUYp0u5C2y0pj5GMoRgzWGVCHdq1LRqeA1EwuVNaIcoJk1wvTm6ZUl20fK16XtrGg1VZ7eL1r+s/YOEi/43vO+NlGtFw6AHArhlhwDGRtEMDWY7PFCqfsTwIUnefTSCXbikC6gDgOn5Q+iOx8Ds9ZD5u4KI3Jj3Q4TiwbNLYTCAsdOyPEL25cJyLVueuQLV/fmUQ+U1LL58TyE8b0W2+kSY0/6UISpH5WyrOfsQUHhoUbauvZ+vCbUQgj9AAAA.H4sIAAAAAAAAAMtjLvQ8wJZutipCkXOd1e2P33qfWLqEXvth1xv8J7vc4yQAfSRTdSAAAAA=.4"; Version=1; Domain=my-app.auth.us-east-1.amazoncognito.com; Max-Age=3600; Expires=Tue, 21-Nov-2023 00:51:41 GMT; Path=/; Secure; HttpOnly; SameSite=Lax
cache-control: no-cache, no-store, max-age=0, must-revalidate
pragma: no-cache
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
strict-transport-security: max-age=31536000 ; includeSubDomains
x-frame-options: DENY
server: Server
X-Firefox-Spdy: h2

Errors I see

ERROR Error: Uncaught (in promise): UserUnAuthenticatedException: User needs to be authenticated to call this API. That's from getCurrentUser().


Solution

  • As you can see, to fix the error ERROR Error: Uncaught (in promise): UserUnAuthenticatedException: User needs to be authenticated to call this API you first need to log in. However, if you are using Cognito Hosted UI along with Amplify v6, you need to call the signInWithRedirect() method.

    Something like this:

    import { signInWithRedirect } from 'aws-amplify/auth';
    
    constructor() {
        this.signIn;
    }
    
    public async signIn(): Promise<void> {
        try {
            await signInWithRedirect();
        } catch (err) {
            this.loggerService.error(err);
        }
    }
    
    

    After that, you can access and call getCurrentUser(); ... etc.