33

I've been using the aws-amplify library with ionic and was wondering how I would check if a user is logged in? I'm coming from a firebase background so this is quite different. This is so that I can grant access to certain pages based on the user's log in status. In my auth provider I import Amplify {Auth}. I can see that it's possible to get several pieces of data but I'm not sure what to use. There's currentUserPoolUser, getCurrentUser(), getSyncedUser(), currentAuthenticatedUser, currentSession, getCurrentUser(), userSession, currentUserCredentials, currentCredentials and currentUserInfo. I can't seem to find any documentation on any of this either. Everything I've read and watched covers up until the user signs in... Is this all supposed to be done on the client? Thanks.

NeXtMaN_786
  • 661
  • 2
  • 12
  • 23

8 Answers8

23

I'm using the ionViewCanEnter() function in every page to allow/deny access. The return value of this function determines if the page can be loaded or not (and it is executed before running the costructor). Inside this function you have to implement you logic.

In my case, using Amplify, I'm doing this:

async function ionViewCanEnter() {
    try {
        await Auth.currentAuthenticatedUser();
        return true;
    } catch {
        return false;
    }
}

Since amplify currentAuthenticatedUser() return a promise I use async await to wait for the response to know if the user is logged in or not.

McMath
  • 6,862
  • 2
  • 28
  • 33
AleCat83
  • 1,443
  • 3
  • 22
  • 41
  • 10
    WHY are you mixing old and new syntax? what about ```async ionViewCanEnter(){ try { await Auth.currentAuthenticatedUser() return true } catch(e) { return false } }``` – Esben von Buchwald Aug 01 '18 at 20:51
  • 1
    The flow-control purist in me worries that the error thrown is not necessarily related to the user's logged-in status, since the error is discarded. – Tim Heilman Jul 20 '22 at 15:42
  • this makes a request to the server that usually takes 300 milliseconds, I would like some instant check – Tomasz Mularczyk Aug 30 '23 at 10:12
14

Hey I think for now you can only use Auth.currentUserInfo(); to detect whether logged in or not. It will return undefined if you are not logged in or an object if you are.

powerful23
  • 257
  • 1
  • 7
  • 7
    or this one `Auth.currentAuthenticatedUser()` – iurii Feb 14 '18 at 21:23
  • Awesome thanks. Also, is it okay to do this all on the client side? Similar to how you can build full client side applications and use firebase as a BaaS? – NeXtMaN_786 Feb 15 '18 at 18:08
3

This can be achieved using the fetchAuthSession() method of Auth.

final CognitoAuthSession res = await Amplify.Auth.fetchAuthSession();
if (res.isSignedIn) {
  // do your thang
}
Greco
  • 39
  • 3
2

if you are using angular with ionic then you can do somthing like this in your authenticator service

import {AmplifyService} from 'aws-amplify-angular';
  ...
  constructor(private amplifyService:AmplifyService)
  {
    this.amplifyService.authStateChange$.subscribe(auth => {
      switch (auth.state) {
        case 'signedIn':
          this.signedIn = true;
        case 'signedOut':
          this.signedIn = false;
          break;
        default:
          this.signedIn = false;
      }
    }
}

then you can use this.signedIn in your router with canActivate guard.

Angular router guard: https://angular.io/guide/router#preventing-unauthorized-access

ssuperczynski
  • 3,190
  • 3
  • 44
  • 61
Mohamed Raafat
  • 116
  • 1
  • 4
2

You can make it a custom hook by listening to the hub (ionViewCanEnter from the above answers is for bootup of the app):
Hook tsx:

import {useState, useEffect} from 'react';
import {Hub, Auth} from 'aws-amplify';

export default function AuthenticatedStatus(): Boolean {
  const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);

  async function ionViewCanEnter() {
    console.log('hey');
    try {
      const authenticatedUser = await Auth.currentAuthenticatedUser();
      if (authenticatedUser !== undefined) {
        setIsAuthenticated(true);
      } else {
        setIsAuthenticated(false);
      }
    } catch {
      setIsAuthenticated(false);
    }
  }

  useEffect(() => {
    ionViewCanEnter();
  });

  useEffect(() => {
    const listener = data => {
      switch (data.payload.event) {
        case 'signIn' || 'autoSignIn' || 'tokenRefresh':
          console.log('is authenticated');
          setIsAuthenticated(true);
          break;
        case 'signOut' || 'signIn_failure' || 'tokenRefresh_failure' || 'autoSignIn_failure':
          console.log('is not authenticated');
          setIsAuthenticated(false);
          break;
      }
    };

    Hub.listen('auth', listener);
  });

  return isAuthenticated;
}

how to use:

const isAuthenticated = AuthenticatedStatus();
bieboebap
  • 320
  • 3
  • 18
1

An example that's worked with me, careful for flow control, both event-loop style and async/await style:

import { Auth } from "aws-amplify";

...

    exampleIsLoggedIn() {
      const notLoggedInStringThrown = "The user is not authenticated";
      Auth.currentAuthenticatedUser().then(
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
        (_currentAuthenticatedUser) => {
          this.$log.debug("Yes, user is logged in.");
        },
        (error) => {
          if (error === notLoggedInStringThrown) {
            this.$log.debug("No, user is not yet logged in.");
          } else {
            this.$log.error(error);
          }
        }
      );
    },
    async exampleIsLoggedInAsync() {
      const notLoggedInStringThrown = "The user is not authenticated";
      try {
        /* currentAuthenticatedUser = */ await Auth.currentAuthenticatedUser();
        this.$log.debug("Yes, user is logged in.");
      } catch (error) {
        if (error === notLoggedInStringThrown) {
          this.$log.debug("No, user is not yet logged in.");
        } else {
          this.$log.error(error);
        }
      }
    },
Tim Heilman
  • 340
  • 2
  • 11
0
import { Auth } from 'aws-amplify';

Auth.currentAuthenticatedUser({
  // Optional, By default is false. If set to true, 
  // this call will send a request to Cognito to get the latest user data
  bypassCache: false
})
  .then((user) => console.log(user))
  .catch((err) => console.log(err));

This method can be used to check if a user is logged in when the page is loaded. It will throw an error if there is no user logged in. This method should be called after the Auth module is configured or the user is logged in. To ensure that you can listen on the auth events configured or signIn.

Source: https://docs.amplify.aws/lib/auth/manageusers/q/platform/js/#retrieve-current-authenticated-user

jellonek
  • 2,094
  • 1
  • 13
  • 4
0

I wrote a hook that serves my purposes well:

import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { Auth, Hub } from "aws-amplify";


export interface UserDetailsT {
    username: string,
    email: string,
    emailVerified: boolean,
};


const useAuth = (): [UserDetailsT | null, Dispatch<SetStateAction<UserDetailsT | null>>] => {
    const [userDetails, setUserDetails] = useState<UserDetailsT | null>(null);
    
    useEffect(() => {
        const getUserDetails = async () => {
            try {
                if (userDetails === null) {
                    const { username, attributes } = await Auth.currentAuthenticatedUser() || null;
                    setUserDetails({
                        username,
                        email: attributes?.email,
                        emailVerified: attributes?.email_verified
                    });
                }
            } catch {
                setUserDetails(null);
            }
        }

        getUserDetails();
        Hub.listen('auth', () => getUserDetails());

    }, [Auth, userDetails, setUserDetails]);

    return [userDetails, setUserDetails];
};


export default useAuth;
Bud Linville
  • 193
  • 1
  • 10