amplify-js: withSSRContext not updating auth information on server-side
Before opening, please confirm:
- I have searched for duplicate or closed issues.
- I have read the guide for submitting bug reports.
- I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
React
Amplify APIs
Authentication
Amplify Categories
auth
Environment information
System:
OS: macOS 10.15.7
CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
Memory: 496.23 MB / 16.00 GB
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 12.20.0 - ~/.volta/tools/image/node/12.20.0/bin/node
Yarn: 1.22.5 - ~/.volta/tools/image/yarn/1.22.5/bin/yarn
npm: 6.14.8 - ~/.volta/tools/image/npm/6.14.8/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
Browsers:
Brave Browser: 89.1.22.70
Chrome: 89.0.4389.114
Edge: 89.0.774.63
Firefox Developer Edition: 88.0
Safari: 14.0.3
npmPackages:
@apollo/client: ^3.3.13 => 3.3.13
@apollo/react-hooks: ^4.0.0 => 4.0.0
@apollo/react-ssr: ^4.0.0 => 4.0.0
@aws-amplify/ui-react: ^1.0.6 => 1.0.6
@material-ui/core: ^4.11.3 => 4.11.3
@material-ui/icons: ^4.11.2 => 4.11.2
@types/draft-js: ^0.11.1 => 0.11.1
@types/isomorphic-fetch: ^0.0.35 => 0.0.35
@types/jest: ^26.0.12 => 26.0.22
@types/next-auth: ^3.13.0 => 3.13.0
@types/node: ^14.0.11 => 14.14.37
@types/react: ^17.0.3 => 17.0.3
@types/react-i18next: ^8.1.0 => 8.1.0
@types/slate: ^0.47.7 => 0.47.8
@types/slate-react: ^0.22.9 => 0.22.9
@types/styled-components: ^5.1.0 => 5.1.9
@typescript-eslint/eslint-plugin: ^4.20.0 => 4.20.0
@typescript-eslint/parser: ^4.20.0 => 4.20.0
apollo-client: ^2.6.10 => 2.6.10
apollo-link: ^1.2.14 => 1.2.14
apollo-link-http: ^1.5.17 => 1.5.17
aws-amplify: ^3.3.26 => 3.3.26
aws-amplify-react: ^4.2.30 => 4.2.30
babel-eslint: ^10.1.0 => 10.1.0
babel-jest: ^26.3.0 => 26.6.3
babel-plugin-styled-components: ^1.12.0 => 1.12.0
date-fns: ^2.14.0 => 2.19.0
deepmerge: ^4.2.2 => 4.2.2
draft-js: ^0.11.6 => 0.11.7
eslint: ^7.23.0 => 7.23.0
eslint-config-prettier: ^8.1.0 => 8.1.0
eslint-config-react-app: ^6.0.0 => 6.0.0
eslint-plugin-flowtype: ^5.4.0 => 5.4.0
eslint-plugin-import: ^2.21.2 => 2.22.1
eslint-plugin-jsx-a11y: ^6.3.1 => 6.4.1
eslint-plugin-prettier: ^3.1.4 => 3.3.1
eslint-plugin-react: ^7.20.0 => 7.23.1
eslint-plugin-react-hooks: ^4.2.0 => 4.2.0
fast-check: ^2.2.1 => 2.14.0
graphql: ^15.1.0 => 15.5.0
i18next: ^20.1.0 => 20.1.0
jest: ^26.4.2 => 26.6.3
lodash: ^4.17.21 => 4.17.21
next: ^10.1.2 => 10.1.2
prettier: ^2.2.1 => 2.2.1
react: ^17.0.2 => 17.0.2
react-dom: ^17.0.2 => 17.0.2
react-hook-form: ^6.15.5 => 6.15.5
react-i18next: ^11.5.0 => 11.8.12
react-is: ^17.0.2 => 17.0.2
slate: ^0.61.3 => 0.61.3
slate-hyperscript: ^0.61.3 => 0.61.3
slate-react: ^0.61.3 => 0.61.3
styled-components: 5.2.1 => 5.2.1
styled-normalize: ^8.0.7 => 8.0.7
stylelint: ^13.6.1 => 13.12.0
stylelint-config-recommended: ^4.0.0 => 4.0.0
stylelint-config-styled-components: ^0.1.1 => 0.1.1
stylelint-processor-styled-components: ^1.10.0 => 1.10.0
typescript: ^4.2.3 => 4.2.3
npmGlobalPackages:
npm: 6.14.8
Describe the bug
I’m using Cognito Authentication with Amplify in a next.js environment. I’ve configured amplify for SSR, but it seems like the withSSRContext is not updating properly. Despite a successful login, I’m not authorized on the serverside.
My flow: index.tsx
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: '/sign-in' });
context.res.end();
return null;
}
};
export async function getServerSideProps(context) {
const auth = await withAuth(context);
return {
props: {
authenticated: auth != null,
},
};
}
Because you are not logged in, you will get redirected to /sign-in.
On the /sign-in page you can log in via Auth.federatedSignIn({ provider: 'Google' })
The sign-in redirect URL is configured to http://localhost:3000.
After you log in successfully you will land on the index.tsx again, but the Auth within getServerSideProps is not updated. It constantly returns an error from await SSR.Auth.currentAuthenticatedUser(); so you will land at the /sign-in page again.
Expected behavior
I expect that the Auth information is available on the server-side after a successful login. For me, it seems like the amplify-js is updating the auth on the client-side and this is too late for handling stuff in a server-environment.
Reproduction steps
create-next-app amplify-auth-ssr-testamplify initamplify add auth- Add an auth with a social provider and a redirect sign-in URL to
http://localhost:3000 - Try to do some auth stuff mentioned within the bug details
Code Snippet
// Put your code below this line.
Log output
// Put your logs below this line
aws-exports.js
/* eslint-disable */
// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.
const awsmobile = {
"aws_project_region": "eu-central-1",
"aws_cognito_identity_pool_id": "XXX",
"aws_cognito_region": "eu-central-1",
"aws_user_pools_id": "XXX",
"aws_user_pools_web_client_id": "XXX",
"oauth": {
"domain": "XXX",
"scope": [
"phone",
"email",
"openid",
"profile",
"aws.cognito.signin.user.admin"
],
"redirectSignIn": "http://localhost:3000/",
"redirectSignOut": "http://localhost:3000/",
"responseType": "code"
},
"federationTarget": "COGNITO_USER_POOLS",
"aws_appsync_graphqlEndpoint": "XXX",
"aws_appsync_region": "XXX",
"aws_appsync_authenticationType": "AMAZON_COGNITO_USER_POOLS"
};
export default awsmobile;
Manual configuration
No response
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
I will try to create an example repo today
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 9
- Comments: 25 (5 by maintainers)
For those who are using Next.js with SSR to authenticate if the user has access to a speciffic page. The solution is similar as @lifedup but without setting the credentials in each method.
In your _app.ts (if you are using typescript) configure the following aws credentials:
In your index.ts or any other page that you would like to verify authentication:
I was able to reproduce this today. As of now redirecting client side should be the best work around for this. This is caused by the way Amplify loads cookies inside the browser, and how it can detect if a user is logged in or not.
Amplify must load at least once client side after being redirected from a federated login before
getServerSidePropscan detect if the user is logged in or not.To make this faster, make sure the route is completely empty, and all it does is redirect.
@chrisbonifacio
The bug occurs because the username contains @ but in cookies the @ becomes %40, on the following line the username contains @ instead of %40 https://github.com/aws-amplify/amplify-js/blob/main/packages/amazon-cognito-identity-js/src/CognitoUser.js#L1388
I guess the encodeURIComponent solve the problem
@tobiastimm Are you or anyone else still blocked on this issue? The cause of the issue can be different for each person but there have been some comments noting proper usage of
withSSRContext, some gotchas like when it comes to oauth that require Amplify to be able to finish the oauth flow which can be interrupted by server side redirects (workaround being client side redirect after signin is confirmed).Yup exactly, @bmkennedy-hcg you hit the nail on the head. This is the common scenario we are also encountering. For us, on initial sing-in redirect there is no authenticated user. So what we do is we fallback/redirect to a
callbackpage route, which loads amplify client side, which then performs another client side redirect, and then and only then is the user authenticated.It’s a lame workaround but it works. Since the initial sign-in redirect from cognito contains the code and state, I figured I could use the
oAuthClientexported by theserver, however the client theserveruses, actually rely’s on window object. So go figure…Thanks, @voigtito. Like you mentioned, I was able to get
withSSRContextto work once I configuredAuthinside ofgetServerSideProps. My code now looks like this:None of the docs mentioned that it is necessary to configure the
Authobject returned bywithSSRContext. Here is an example: https://aws.amazon.com/blogs/mobile/ssr-support-for-aws-amplify-javascript-libraries/Hi 👋 Closing this as we have not heard back from you. If you are still experiencing this issue and in need of assistance, please feel free to open a new issue and fill out as much info in the bug report form as you can provide.
Thank you!
@bezreyhan if you configure the Amplify or Auth just once in your _app.tsx it should work! If you configure it only in your index.tsx it wont work properly.
In a next.js application if you create the _app.tsx file inside /pages folder your next.js will always look at first. So this is the file where you need to configure your Amplify.
Here is an example of the _app.tsx file:
After setting this you can use Auth inside your getServerSideProps properly.