Amplify-js: Hub TypeError: Cannot read property 'setItem' of undefined (AuthClass)

Created on 14 May 2019  路  16Comments  路  Source: aws-amplify/amplify-js

Describe the bug
It seems import {AuthClass} from '@aws-amplify/auth'; is defining an instance of AuthClass without any configuration (new AuthClass(null)) as the default instance via these lines https://github.com/aws-amplify/amplify-js/blob/master/packages/auth/src/index.ts#L24.

The AuthClass listens to Hub via these lines, https://github.com/aws-amplify/amplify-js/blob/master/packages/auth/src/Auth.ts#L111-L125 and the storage here would be null throwing a null pointer exception which can lead to console errors like:

[ERROR] 27:39.356 Hub TypeError: Cannot read property 'setItem' of undefined
    at Object.callback (Auth.js:95)
    at Hub.js:122
    at Array.forEach (<anonymous>)
    at HubClass.push../node_modules/@aws-amplify/core/lib/Hub.js.HubClass._toListeners (Hub.js:119)
    at HubClass.push../node_modules/@aws-amplify/core/lib/Hub.js.HubClass.dispatch (Hub.js:77)
    at dispatchAuthEvent (Auth.js:61)
    at AuthClass.<anonymous> (Auth.js:387)
    at step (Auth.js:44)
    at Object.next (Auth.js:25)
    at fulfilled (Auth.js:16)

In my case, I define my own instance of the AuthClass with the proper configuration options, so really this Hub listener is called twice for both instances. My instance that I defined with all the proper configuration seems to have storage correctly configured there and does not throw the error.

To Reproduce
Steps to reproduce the behavior:

  1. Use a second AuthClass instance for managing your user pool.

Expected behavior
It does not create a default instance? Or maybe it handles the null pointer without exception?

Screenshots

Desktop (please complete the following information):

  • OS: Mac OS
  • Browser Chrome
  • Version 74

Additional context

Sample code

You can turn on the debug mode to provide more info for us by setting window.LOG_LEVEL = 'DEBUG'; in your app.

Auth Hub feature-request

Most helpful comment

Soooo.......this is the problem i had, and i'll try to phrase it in a nicer way than i did to mean at the time.

i was using the api and the auth. from their modules

import API, { graphqlOperation } from '@aws-amplify/API';

API.configure(.....)

and
import Auth from '@aws-amplify/Auth';
API.configure(.....)

this would throw error in console because api internally uses auth as well and initiate a new instance of auth with null config....
problem, but not a huge problem ...... everything still works

But, when you have API using cognito userpool as authentication it wouldnt work because again API creates its own instance of Auth with null configuration.

the alternative is to use the whole of amplify, which is not tree shakable, it builds with everything.....everything, my build size increases by 5mb!

All 16 comments

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

This issue has been automatically closed because of inactivity. Please open a new issue if are still encountering problems.

this is an actual issue, can we reopen it

facing the same using AuthClass directly:

const { AuthClass } = require('@aws-amplify/auth');

const auth = new AuthClass({
    "identityPoolId": 'some-IdentityPoolId',
    "userPoolId": 'som-userPoolId',
    "userPoolWebClientId": 'some-userPoolWebClientId',
    region: 'some-region',
});

(async () => {
    try {
        const res = await auth.signIn('[email protected]', '123456')
        console.log('===res', res)
    } catch (e) {
        console.log('===e', e)
    }
})()

@sammartinez multiple users have requested this issue be re-opened.

Apologizes that this got closed, @mtraynham Can you explain your use case a little bit more? Im curious on why you are using AuthClass instead of just import { Auth } from '@aws-amplify/auth' for Hub events.

@sammartinez It's been a while, so I believe this is because to configure that particular global constant instance, the documentation suggests you pull in all of @aws-amplify, like so:

import Amplify, { Auth } from '@aws-amplify';
import awsconfig from './aws-exports';
Amplify.configure(awsconfig);

https://aws-amplify.github.io/docs/js/authentication#manual-setup

In reality, I only want a subset of the amplify functionality which is authentication.

Although I just realized, I guess you could likely pull in Auth as you suggested, via import Auth from '@aws-amplify/auth' and run configure on that instance. My only hesitation there is this method is not marked with a public visibility modifier and I may or may not have run into a TypeScript linter issue complaining about that, or I just didn't know about it...

import Auth from '@aws-amplify/auth';
Auth.configure({...});

It's honestly been a while since I've touched the code (Sept 2018), so I can't exactly remember what I did while getting this all setup.

Pertaining to the bug, I could see multiple instances of AuthClass being used in a single app (even though I'm not doing it), but the scope of that question may be beyond this bug. Feel free to advise us (or me) if we should take a different route here, such as configuring the global constant instead of a second instance.


Edit I tried out your suggestion. Everything seems to work the same, and the console error is gone. Seems like the vendor file is roughly the same size as well, so I'm guessing it didn't pull anything extra in.

@harmohan-a @sepo-one issue re-opened fyi.

My use case is that i don't want any global configuration.
Just need to create a singleton instance out of AuthClass and configure it via constructor.
(We might have want to work with different user pools).
(See example above).

Similar to @mtraynham, we only use Amplify's auth module and hit this bug with the following:

import { AuthClass } from '@aws-amplify/auth';

const auth = new AuthClass({
    region: 'eu-west-2',
    userPoolId: 'my-pool-id',
    userPoolWebClientId: 'my-client-id',
});

Problem actually lies in here: https://github.com/aws-amplify/amplify-js/blob/master/packages/auth/src/index.ts.

An instance is created with null config.
Then configure() does not create storage if config is null.
And then Hub.listen fails because no storage is created.

(might come up with pull request if have some time).

Soooo.......this is the problem i had, and i'll try to phrase it in a nicer way than i did to mean at the time.

i was using the api and the auth. from their modules

import API, { graphqlOperation } from '@aws-amplify/API';

API.configure(.....)

and
import Auth from '@aws-amplify/Auth';
API.configure(.....)

this would throw error in console because api internally uses auth as well and initiate a new instance of auth with null config....
problem, but not a huge problem ...... everything still works

But, when you have API using cognito userpool as authentication it wouldnt work because again API creates its own instance of Auth with null configuration.

the alternative is to use the whole of amplify, which is not tree shakable, it builds with everything.....everything, my build size increases by 5mb!

Im going to move this under a feature request, from what I am reading it seems that people are looking to utilizing Auth as a standalone piece instead of bringing in the entire Amplify Library. I will let you guys know that we are working on modularizing our library. While we don't have a confirmed date at the moment, there is work in flight to make Amplify modularized.

I'm using AuthClass at the moment with Next.JS to have two Storage mechanisms. One for cookies in the browser and the other for cookies on the server. I'm running into this issue which prevents auth on the server from working (the session is not hydrated it appears?), it does work occasionally.

Yeah, if you start to modularise the API and the other parts of Amplify, why not AUTH.
We only use AUTH and API. I don't want the rest polluting my bundle. It is already over 5 mb because of aws-amplify.
When can we expect @amplify/auth to be released? It is still sitting at version 1.6.3?

This issue has been around for a while & may be addressed in a few different ways:

  1. [email protected] introduce modularization changes, so import { API, Auth } from "aws-amplify" should yield the same bundle-size as import { Auth } from "aws-amplify".

    If that's not your experience, then please open a new issue because that's impacting _all_ use-cases.

  2. Creating new instances of Auth should be better supported in part thanks to #6146. Internally, that's using new Auth.constructor(), rather than directly accessing an AuthClass.

    I'm using AuthClass at the moment with Next.JS to have two Storage mechanisms. One for cookies in the browser and the other for cookies on the server. I'm running into this issue which prevents auth on the server from working (the session is not hydrated it appears?), it does work occasionally.

    This use-case has been addressed as part of #6146!

    Please see my synopsis on changes here: https://github.com/aws-amplify/amplify-js/issues/5435#issuecomment-692990722

    Amplify.configure({ ...awsExports, ssr: true }) is all it takes to get credentials passed to the server for Next.js

With these changes & more in the past year-and-a-half, this issue should be resolved.

If not, please open a new issue with specifics so we can address it based on our new SSR & modularization support 馃檹

Was this page helpful?
0 / 5 - 0 ratings

Related issues

josoroma picture josoroma  路  3Comments

ldgarcia picture ldgarcia  路  3Comments

callmekatootie picture callmekatootie  路  3Comments

benevolentprof picture benevolentprof  路  3Comments

ddemoll picture ddemoll  路  3Comments