Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next.js SSR: true - Error: Invalid Refresh token calling currentAuthenticatedUser server side when user pool Device Tracking is set to opt-in #11664

Open
3 tasks done
mpinter opened this issue Jul 21, 2023 · 4 comments
Assignees
Labels
Auth Related to Auth components/category feature-request Request a new feature Next.js SSR Issues related to Server Side Rendering

Comments

@mpinter
Copy link

mpinter commented Jul 21, 2023

Before opening, please confirm:

JavaScript Framework

Next.js

Amplify APIs

Authentication

Amplify Categories

auth

Environment information

# Put output below this line

 System:
    OS: macOS 13.4.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 81.05 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 16.19.0 - ~/.volta/tools/image/node/16.19.0/bin/node
    Yarn: 1.22.19 - ~/.volta/tools/image/yarn/1.22.19/bin/yarn
    npm: 8.19.3 - ~/.volta/tools/image/node/16.19.0/bin/npm
    pnpm: 8.6.1 - ~/Library/pnpm/pnpm
  Browsers:
    Brave Browser: 114.1.52.117
    Safari: 16.5.1
  npmPackages:
    @ampproject/toolbox-optimizer:  undefined ()
    @babel/core:  undefined ()
    @babel/runtime:  7.15.4 
    @bratislava/json-schema-xsd-tools: ^0.2.1 => 0.2.1 
    @edge-runtime/cookies:  3.2.1 
    @edge-runtime/ponyfill:  2.3.0 
    @edge-runtime/primitives:  3.0.1 
    @grafana/faro-core: ^1.0.5 => 1.0.5 (1.0.2)
    @grafana/faro-web-sdk: ^1.0.2 => 1.0.2 
    @hapi/accept:  undefined ()
    @hookform/resolvers: ^2.9.10 => 2.9.10 
    @hookform/resolvers/ajv:  1.0.0 
    @hookform/resolvers/class-validator:  1.0.0 
    @hookform/resolvers/computed-types:  1.0.0 
    @hookform/resolvers/io-ts:  1.0.0 
    @hookform/resolvers/joi:  1.0.0 
    @hookform/resolvers/nope:  1.0.0 
    @hookform/resolvers/superstruct:  1.0.0 
    @hookform/resolvers/typanion:  1.0.0 
    @hookform/resolvers/vest:  1.0.0 
    @hookform/resolvers/yup:  1.0.0 
    @hookform/resolvers/zod:  1.0.0 
    @internationalized/date: 3.3.0 => 3.3.0 (3.2.0)
    @jest/globals: ^29.5.0 => 29.5.0 
    @js-joda/core: ^5.5.3 => 5.5.3 
    @legendapp/state: ^1.2.11 => 1.2.11 
    @napi-rs/triples:  undefined ()
    @next/font:  undefined ()
    @next/react-dev-overlay:  undefined ()
    @openapitools/openapi-generator-cli: ^2.6.0 => 2.6.0 
    @opentelemetry/api:  undefined ()
    @radix-ui/react-dropdown-menu: ^2.0.4 => 2.0.4 
    @react-aria/overlays: 3.14.1 => 3.14.1 (3.15.0)
    @rjsf/core: ^5.9.0 => 5.9.0 
    @rjsf/utils: ^5.9.0 => 5.9.0 
    @rjsf/validator-ajv8: ^5.9.0 => 5.9.0 
    @segment/ajv-human-errors:  undefined ()
    @svgr/webpack: 6.5.1 => 6.5.1 
    @tanstack/react-query: ^4.29.14 => 4.29.14 
    @testing-library/jest-dom: ^5.16.5 => 5.16.5 
    @testing-library/react: ^13.4.0 => 13.4.0 
    @types/formidable: ^2.0.5 => 2.0.5 
    @types/lodash: 4.14.192 => 4.14.192 
    @types/minio: ^7.0.14 => 7.0.15 
    @types/node: 18.11.18 => 18.11.18 (18.11.19)
    @types/react: 18.0.28 => 18.0.28 (18.0.27)
    @types/react-dom: 18.0.11 => 18.0.11 (18.0.10)
    @types/uuid: ^9.0.1 => 9.0.1 
    @types/xml2js: ^0.4.11 => 0.4.11 
    @typescript-eslint/eslint-plugin: ^5.56.0 => 5.56.0 
    @typescript-eslint/parser: ^5.54.0 => 5.54.1 
    @vercel/nft:  undefined ()
    @vercel/og:  undefined ()
    acorn:  undefined ()
    add-to-calendar-button-react: ^2.2.3 => 2.2.3 
    ajv: ^8.12.0 => 8.12.0 (6.12.6)
    ajv-formats: ^2.1.1 => 2.1.1 
    amphtml-validator:  undefined ()
    anser:  undefined ()
    arg:  undefined ()
    assert:  undefined ()
    async-retry:  undefined ()
    async-sema:  undefined ()
    autoprefixer: 10.4.14 => 10.4.14 
    aws-amplify: ^5.3.3 => 5.3.3 
    axios: ^1.4.0 => 1.4.0 (0.26.0, 0.27.2, 0.24.0)
    babel-packages:  undefined ()
    browserify-zlib:  undefined ()
    browserslist:  undefined ()
    buffer:  undefined ()
    bytes:  undefined ()
    chalk:  undefined ()
    cheerio: ^1.0.0-rc.12 => 1.0.0-rc.12 
    ci-info:  undefined ()
    classnames: 2.3.1 => 2.3.1 
    cli-select:  undefined ()
    client-only:  0.0.1 
    comment-json:  undefined ()
    compression:  undefined ()
    conf:  undefined ()
    constants-browserify:  undefined ()
    content-disposition:  undefined ()
    content-type:  undefined ()
    cookie:  undefined ()
    cross-spawn:  undefined ()
    crypto-browserify:  undefined ()
    css.escape:  undefined ()
    currency.js: ^2.0.4 => 2.0.4 
    data-uri-to-buffer:  undefined ()
    debug:  undefined ()
    depcheck: ^1.4.3 => 1.4.3 
    devalue:  undefined ()
    domain-browser:  undefined ()
    edge-runtime:  undefined ()
    eslint: 8.20.0 => 8.20.0 (8.33.0)
    eslint-config-adjunct: 4.11.1 => 4.11.1 (4.11.2)
    eslint-config-airbnb: 19.0.4 => 19.0.4 
    eslint-config-airbnb-typescript: 17.0.0 => 17.0.0 
    eslint-config-auto: 0.7.1 => 0.7.1 
    eslint-config-next: 13.4.6 => 13.4.6 
    eslint-config-prettier: 8.8.0 => 8.8.0 
    eslint-plugin-array-func: 3.1.8 => 3.1.8 
    eslint-plugin-eslint-comments: 3.2.0 => 3.2.0 
    eslint-plugin-html: 7.0.0 => 7.0.0 
    eslint-plugin-import: 2.27.5 => 2.27.5 
    eslint-plugin-jest: ^27.1.3 => 27.2.1 
    eslint-plugin-jest-async: ^1.0.3 => 1.0.3 
    eslint-plugin-jest-dom: ^4.0.2 => 4.0.3 
    eslint-plugin-json: 3.1.0 => 3.1.0 
    eslint-plugin-lodash: 7.4.0 => 7.4.0 
    eslint-plugin-lodash-fp: 2.2.0-a1 => 2.2.0a1 
    eslint-plugin-markdown: 3.0.0 => 3.0.0 
    eslint-plugin-no-constructor-bind: 2.0.4 => 2.0.4 
    eslint-plugin-no-secrets: 0.8.9 => 0.8.9 
    eslint-plugin-no-unsanitized: 4.0.2 => 4.0.2 
    eslint-plugin-no-use-extend-native: 0.5.0 => 0.5.0 
    eslint-plugin-optimize-regex: 1.2.1 => 1.2.1 
    eslint-plugin-promise: 6.0.0 => 6.0.0 
    eslint-plugin-react-hooks: 4.6.0 => 4.6.0 
    eslint-plugin-scanjs-rules: 0.2.1 => 0.2.1 
    eslint-plugin-security: 1.7.1 => 1.7.1 
    eslint-plugin-simple-import-sort: 10.0.0 => 10.0.0 
    eslint-plugin-sonarjs: 0.18.0 => 0.18.0 
    eslint-plugin-switch-case: 1.1.2 => 1.1.2 
    eslint-plugin-tailwindcss: 3.6.0 => 3.6.0 
    eslint-plugin-testing-library: ^5.9.1 => 5.10.0 
    eslint-plugin-unicorn: 43.0.2 => 43.0.2 
    events:  undefined ()
    find-cache-dir:  undefined ()
    find-up:  undefined ()
    fresh:  undefined ()
    get-orientation:  undefined ()
    glob:  undefined ()
    gzip-size:  undefined ()
    http-proxy:  undefined ()
    http-proxy-agent:  undefined ()
    https-browserify:  undefined ()
    https-proxy-agent:  undefined ()
    husky: ^8.0.1 => 8.0.3 
    icss-utils:  undefined ()
    ignore-loader:  undefined ()
    image-size:  undefined ()
    is-animated:  undefined ()
    is-docker:  undefined ()
    is-wsl:  undefined ()
    jest: ^29.5.0 => 29.5.0 
    jest-each: ^29.3.1 => 29.4.1 (29.5.0)
    jest-environment-jsdom: ^29.5.0 => 29.5.0 
    jest-worker:  undefined ()
    js-cookie: ^3.0.1 => 3.0.1 (2.2.1)
    json-schema: ^0.4.0 => 0.4.0 
    json5:  undefined ()
    jsonwebtoken:  undefined ()
    libphonenumber-js: ^1.10.21 => 1.10.21 
    libphonenumber-js/build:  undefined ()
    libphonenumber-js/core:  undefined ()
    libphonenumber-js/max:  undefined ()
    libphonenumber-js/max/metadata:  undefined ()
    libphonenumber-js/min:  undefined ()
    libphonenumber-js/min/metadata:  undefined ()
    libphonenumber-js/mobile:  undefined ()
    libphonenumber-js/mobile/examples:  undefined ()
    libphonenumber-js/mobile/metadata:  undefined ()
    libxmljs2: ^0.31.0 => 0.31.0 
    lint-staged: ^13.1.2 => 13.1.2 
    loader-runner:  undefined ()
    loader-utils:  undefined ()
    lodash: 4.17.21 => 4.17.21 
    lodash.curry:  undefined ()
    lru-cache:  undefined ()
    micromatch:  undefined ()
    mini-css-extract-plugin:  undefined ()
    nanoid:  undefined ()
    native-url:  undefined ()
    neo-async:  undefined ()
    next: 13.4.5 => 13.4.5 
    next-i18next: 12.1.0 => 12.1.0 
    next-i18next-create-client:  undefined ()
    next-query-params: ^4.1.0 => 4.1.0 
    node-fetch:  undefined ()
    node-html-parser:  undefined ()
    ora:  undefined ()
    os-browserify:  undefined ()
    p-limit:  undefined ()
    path-browserify:  undefined ()
    platform:  undefined ()
    postcss: 8.4.24 => 8.4.24 (8.4.23, 8.4.21, 8.4.14)
    postcss-flexbugs-fixes:  undefined ()
    postcss-modules-extract-imports:  undefined ()
    postcss-modules-local-by-default:  undefined ()
    postcss-modules-scope:  undefined ()
    postcss-modules-values:  undefined ()
    postcss-preset-env:  undefined ()
    postcss-safe-parser:  undefined ()
    postcss-scss:  undefined ()
    postcss-value-parser:  undefined ()
    pre-commit: ^1.2.2 => 1.2.2 
    prettier: ^2.8.8 => 2.8.8 
    process:  undefined ()
    punycode:  undefined ()
    querystring-es3:  undefined ()
    raw-body:  undefined ()
    react: 18.2.0 => 18.2.0 
    react-aria: 3.26.0 => 3.26.0 
    react-aria-components: 1.0.0-alpha.5 => 1.0.0-alpha.5 
    react-builtin:  undefined ()
    react-cookie-consent: 7.5.0 => 7.5.0 
    react-dom: 18.2.0 => 18.2.0 
    react-dom-builtin:  undefined ()
    react-dom-experimental-builtin:  undefined ()
    react-experimental-builtin:  undefined ()
    react-hook-form: ^7.42.1 => 7.43.0 
    react-is:  18.2.0 
    react-markdown: 8.0.3 => 8.0.3 
    react-refresh:  0.12.0 
    react-remove-scroll: ^2.5.5 => 2.5.5 
    react-resize-detector: ^8.0.3 => 8.0.3 
    react-select: ^5.4.0 => 5.7.0 
    react-server-dom-webpack-builtin:  undefined ()
    react-server-dom-webpack-experimental-builtin:  undefined ()
    react-simple-snackbar: ^1.1.11 => 1.1.11 
    react-stately: 3.24.0 => 3.24.0 
    react-turnstile: ^1.1.0 => 1.1.0 
    regenerator-runtime:  0.13.4 
    rehype-raw: 6.1.1 => 6.1.1 
    remark-directive: ^2.0.1 => 2.0.1 
    remark-directive-rehype: ^0.4.2 => 0.4.2 
    remark-gfm: 3.0.1 => 3.0.1 
    rooks: 5.11.8 => 5.11.8 
    sass-loader:  undefined ()
    saxon-js: ^2.5.0 => 2.5.0 
    scheduler-builtin:  undefined ()
    scheduler-experimental-builtin:  undefined ()
    schema-utils:  undefined ()
    semver:  undefined ()
    send:  undefined ()
    server-only:  0.0.1 
    setimmediate:  undefined ()
    sharp: ^0.32.1 => 0.32.1 
    shell-quote:  undefined ()
    slugify: ^1.6.6 => 1.6.6 
    source-map:  undefined ()
    stacktrace-parser:  undefined ()
    stream-browserify:  undefined ()
    stream-http:  undefined ()
    string-hash:  undefined ()
    string_decoder:  undefined ()
    strip-ansi:  undefined ()
    tailwind-scrollbar-hide: ^1.1.7 => 1.1.7 
    tailwindcss: 3.3.2 => 3.3.2 (3.2.4)
    tar:  undefined ()
    terser:  undefined ()
    text-table:  undefined ()
    timers-browserify:  undefined ()
    tslog: ^4.8.2 => 4.8.2 
    tty-browserify:  undefined ()
    typescript: 5.1.3 => 5.1.3 (4.9.5)
    ua-parser-js:  undefined ()
    undici:  undefined ()
    unistore:  undefined ()
    universal-cookie: ^4.0.4 => 4.0.4 
    use-query-params: ^2.2.0 => 2.2.0 
    use-query-params/adapters/reach:  undefined ()
    use-query-params/adapters/react-router-5:  undefined ()
    use-query-params/adapters/react-router-6:  undefined ()
    use-query-params/adapters/window:  undefined ()
    usehooks-ts: 2.9.1 => 2.9.1 
    util:  undefined ()
    uuid: ^9.0.0 => 9.0.0 (3.4.0, 8.3.2)
    vm-browserify:  undefined ()
    watchpack:  undefined ()
    web-vitals:  undefined ()
    webpack:  undefined ()
    webpack-sources:  undefined ()
    ws:  undefined ()
    xml-loader: ^1.2.1 => 1.2.1 
    xml2js: ^0.4.23 => 0.4.23 
    xslt3: ^2.5.0 => 2.5.0 
    zod:  undefined ()
  npmGlobalPackages:
    corepack: 0.15.1
    npm: 8.19.3


Describe the bug

When rendering server-side with next, when the access token in no longer valid but refresh token is, amplify fails on calling SSR.Auth.currentAuthenticatedUser() with error Error: Invalid Refresh Token. Before the access token expires everything works both client and server side, and even with expired access token everything is refreshed as it should on client side, but doesn't work server side.

This seems to happen only when Device Tracking is not set to 'don't remember' (only tried with that and with opt-in option, don't know the behaviour for 'always remember'). This happens for users who have not 'opted in' to device tracking, in fact the only reason why we had it set that way was that it was the Cognito default when creating the pool through AWS console.

The reason we tried toggling the device tracking was this comment - without it, we were just looking into why the refresh token works client side and not server side.

Expected behavior

Would expect SSR Auth to work even with opt-in device tracking, mainly when the users have not opted in. Or for it to work the same way client and server side. I understand from this issue that the access token can't be updated from server (yet), but would expect the token to be refreshed on the server and the separately on the client.

If this is expected behaviour with such option, then it may simply need extra documentation, or a better error message.

Reproduction steps

You can see the amplify config of our project here, the call to currentAuthenticatedUser is here which is used in almost every getServerSideProps to forward user data to page props (like here)

But I suspect the same behaviour should show on a empty project, calling currentAuthenticatedUser with cognito user pool . We have configured the cognito pool and client 'by hand' (from aws console) before we started using the aws-amplify lib, in case this may make a difference.

Code Snippet

// Put your code below this line.

export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
  const SSR = withSSRContext({ req: ctx.req })
  let userData = null
  try {
    const currentUser = await SSR.Auth.currentAuthenticatedUser() // <-- here we'll get "Invalid Refresh Token" error
    userData = currentUser.attributes || null
  } catch (error) {
    // TODO Auth throws this exact string, not an error object - refactor once amplify solves this
    if (error !== 'The user is not authenticated') {
      logger.error('getServersideAuth error: ', error)
    }
  }

  return {
    props: {
      ssrCurrentAuthProps: userData,
    },
  }
}

Log output

// Put your logs below this line


aws-exports.js

No response

Manual configuration

{
  Auth: {
    identityPoolId: environment.cognitoIdentityPoolId,
    region: environment.awsRegion,
    userPoolId: environment.cognitoUserPoolId,
    userPoolWebClientId: environment.cognitoClientId,
    mandatorySignIn: false,
    signUpVerificationMethod: 'code',
  },
  ssr: true,
}

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

@mpinter mpinter added the pending-triage Issue is pending triage label Jul 21, 2023
@cwomack cwomack added Auth Related to Auth components/category SSR Issues related to Server Side Rendering Next.js labels Jul 21, 2023
@achyuth4t
Copy link

I've also same issue.

@cwomack cwomack self-assigned this Jul 25, 2023
@cwomack cwomack added investigating This issue is being investigated and removed pending-triage Issue is pending triage labels Jul 25, 2023
@cwomack cwomack added the feature-request Request a new feature label Aug 8, 2023
@cwomack
Copy link
Member

cwomack commented Aug 8, 2023

Related to #11598

@cwomack
Copy link
Member

cwomack commented Aug 8, 2023

Hello @mpinter, and thank you for opening this issue. I've labeled this as a feature request at this point due to there being no ability to write the deviceKey to cookies where it could be accessed on the server side. While this is similar to the feature request in issue #11598, I think we'll keep them separate at this point since you're specifically calling out the issue tied to the invalid refresh token.

I'm curious to see if disabling device tracking stops the errors from happening. Is that something you can test and verify? @achyuth4t, not sure if you can try this as well and let me know what you experience. Thanks!

@cwomack cwomack removed the investigating This issue is being investigated label Aug 8, 2023
@mpinter
Copy link
Author

mpinter commented Aug 10, 2023

@cwomack hi - yes, apologies if that wasn't clear, disabling device tracking for user pool indeed stops the error from happening. It's the way we run this presently (and in production) and it seems to have solved these issues for us. We never really wanted to use device tracking, had it set that way only because it was the default option and we didn't notice.

Still, what I'd assume is a bug in all of this (unless I'm misunderstanding the way the opt-in device tracking should behave) is the fact that with the opt-in option selected, users that have not opted-in behave the same way as when the device tracking is disabled everywhere else - which is fine & expected - except for this SSR refresh token handling - which is therefore unexpected in this context. What I'd expect is that if the user have not opted in, the deviceKey is not checked at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Auth Related to Auth components/category feature-request Request a new feature Next.js SSR Issues related to Server Side Rendering
Projects
None yet
Development

No branches or pull requests

3 participants