amplify-js: Using Auth method to check if the user is logged in with SSR and then trying to signOut does not work

Describe the bug I’m using the Auth method to know if a user is logged in and then execute the signOut method to logout but does not work. Also, the Auth.currentAuthenticatedUser() throws an error that the user is not authenticated even when it is on SSR. I have just implemented this on Dev, I haven’t tried on Prod.

To Reproduce

First, I have added the Amplify.configure({ ...config, ssr: true }); in the _app.js file. Then, I created a function to detect if the a user is logged in when the getServerSideProps is executed. This is withAuth:

import { withSSRContext } from 'aws-amplify';

export const withAuth = async context => {
  try {
    const SSR = withSSRContext(context);
    const user = await SSR.Auth.currentAuthenticatedUser();

    return user;
  } catch (error) {
    context.res.writeHead(301, { Location: '/signin' });
    context.res.end();
  }
};

I call this function on every private page the project has, like this:

import React from 'react';

import { withAuth } from '../lib/withAuth';
import { MySecretComponent } from '../components/views';

const MySecretPage = props => {
  const { user } = props;

  return <MySecretComponent user={user} />;
};

export async function getServerSideProps(context) {
  const auth = await withAuth(context);
  const user = JSON.parse(JSON.stringify(auth)); // Next.js throws a validation error with the object response if I dont do this.

  return {
    props: {
      user: user || null,
    },
  };
}

export default MySecretPage;

It works fine, but when the user wants to signOut, like this:

import React from 'react';
import { useRouter } from 'next/router';
import { Auth } from 'aws-amplify';

const MyComponent => () => {
  const router = useRouter();

  const signOut = () => {
    Auth.signOut().then(() => {
      router.reload();
    });
  };

  return <button onClick={signOut}>logout</button>
}

Amplify still detects I’m logged in… Even when the user already executed the signOut function… And here’s when the project starts to act weird, the method withAuth throws the user to /signin even when is “logged in” but I can still navigate to any private page with the <Link /> component. I already tried removing the cache from the browser and tried with an incognito page, but nothing…

One thing to mention is that I have a header component, to show the user photo and other info, I get this info using Auth in client-side using an useEffect. I don’t know if using Auth in the header component and also in SSR affects something…

Expected behavior Work fine, when the user wants to signout

  • Device: Windows, Linux, and Android phone
  • Browser Google Chrome latest version
  • Version of aws-amplify: 3.3.7
  • Next.js version: 10.0.1

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 8
  • Comments: 20 (8 by maintainers)

Most upvoted comments

Closing, as https://github.com/aws-amplify/amplify-js/pull/7718 (via v1.0.1) should resolve this duplication issue.

To install the latest version of @aws-amplify/ui-react, for example:

npm install aws-amplify @aws-amplify/ui-react
# or
yarn add aws-amplify @aws-amplify/ui-react

Be sure to install aws-amplify, rather than @aws-amplify/core directly. (aws-amplify will install @aws-amplify/core and other dependencies itself)

Let us know if you experience any issues! 🙏

Ahhh! The SSO redirect part to /signinreturn is what’s interesting: https://github.com/dbhagen/next.js-authentication-aws/commit/3ec7225c614b580c85b30cdf8be0a0024b1bb020

The way SSR Auth works at the moment is the Auth client handles the credentials negotiation, then sets credentials in cookies for the server to read.

If you were to redirect back to / or whichever page uses Auth or AmplifyAuthenticator, the client-side finish the SSO flow & show the signed-in version of the app.

Alternatively, you can convert signinpage to call Auth.currentAuthenticatedUser() and redirect on the client to your protected page (e.g. /profile), or error. Like:

https://github.com/dbhagen/next.js-authentication-aws/blob/main/pages/profile.js

I know it’s not the flow you were expecting (client negotiation vs. server), but let me know if that works. Or let me know if I’m misunderstood entirely. I haven’t had a chance to run the repository yet, but I do have a SSO version working: the difference is that it redirects back to the client to finish the login flow.

@dbhagen You’re having this same issue with https://github.com/dbhagen/next.js-authentication-aws, correct? If I were to drop-in aws-exports.js with Auth configured, I should see this bug, correct? Yes. In fact, this is the sanitized aws-exports.js from mine so you can make sure it matches up.

/* eslint-disable */
// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.

const awsmobile = {
    "aws_project_region": "us-east-1",
    "aws_cognito_identity_pool_id": "us-east-1:",
    "aws_cognito_region": "us-east-1",
    "aws_user_pools_id": "us-east-1_",
    "aws_user_pools_web_client_id": "",
    "oauth": {
        "domain": "-dev.auth.us-east-1.amazoncognito.com",
        "scope": [
            "phone",
            "email",
            "openid",
            "profile",
            "aws.cognito.signin.user.admin"
        ],
        "redirectSignIn": "http://localhost:3000/signinreturn/",
        "redirectSignOut": "http://localhost:3000/signoutreturn/",
        "responseType": "code"
    },
    "federationTarget": "COGNITO_USER_POOLS"
};


export default awsmobile;

@dbhagen I want to better understand this comment:

I’ll admit, the example worked fine until AWS Auth/WebUI/SSO was added

Do you mean the auth from the tutorial (https://dev.to/dabit3/the-complete-guide-to-next-js-authentication-2aco), or something else?

Yes, that tutorial worked perfectly with Auth.signOut() until I added SSO via an amplify update auth from the initial tutorial fork deployment.