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

Guest Identity Inconsistency: Server Uses Cookies, Client Uses localStorage #14256

Open
3 tasks done
MarekBodingerBA opened this issue Feb 28, 2025 · 3 comments
Open
3 tasks done
Labels
bug Something isn't working Next.js SSR Issues related to Server Side Rendering

Comments

@MarekBodingerBA
Copy link

Before opening, please confirm:

JavaScript Framework

Next.js

Amplify APIs

Authentication

Amplify Version

v6

Amplify Categories

No response

Backend

None

Environment information

  System:
    OS: Windows 11 10.0.26100
    CPU: (22) x64 Intel(R) Core(TM) Ultra 9 185H
    Memory: 7.52 GB / 31.43 GB
  Binaries:
    Node: 22.11.0 - ~\AppData\Local\Volta\tools\image\node\22.11.0\node.EXE
    npm: 10.9.2 - ~\AppData\Local\Volta\tools\image\npm\10.9.2\bin\npm.CMD
  Browsers:
    Edge: Chromium (131.0.2903.70)
  npmPackages:
    @ampproject/toolbox-optimizer:  undefined ()
    @aws-amplify/adapter-nextjs: 1.5.1 => 1.5.1
    @aws-amplify/adapter-nextjs/api:  undefined ()
    @aws-amplify/adapter-nextjs/data:  undefined ()
    @aws-sdk/client-cognito-identity: ^3.750.0 => 3.758.0
    @aws-sdk/client-sts: ^3.750.0 => 3.758.0 (3.621.0)
    @babel/core:  undefined ()
    @babel/runtime:  7.22.5
    @edge-runtime/cookies:  6.0.0
    @edge-runtime/ponyfill:  4.0.0
    @edge-runtime/primitives:  6.0.0
    @hapi/accept:  undefined ()
    @mswjs/interceptors:  undefined ()
    @napi-rs/triples:  undefined ()
    @next/font:  undefined ()
    @opentelemetry/api:  undefined ()
    @types/node: ^20 => 20.17.19
    @types/react: ^19 => 19.0.10
    @types/react-dom: ^19 => 19.0.4
    @vercel/nft:  undefined ()
    @vercel/og:  0.6.4
    acorn:  undefined ()
    amphtml-validator:  undefined ()
    anser:  undefined ()
    assert:  undefined ()
    async-retry:  undefined ()
    async-sema:  undefined ()
    aws-amplify: 6.13.1 => 6.13.1
    aws-amplify/adapter-core:  undefined ()
    aws-amplify/adapter-core/internals:  undefined ()
    aws-amplify/analytics:  undefined ()
    aws-amplify/analytics/kinesis:  undefined ()
    aws-amplify/analytics/kinesis-firehose:  undefined ()
    aws-amplify/analytics/personalize:  undefined ()
    aws-amplify/analytics/pinpoint:  undefined ()
    aws-amplify/api:  undefined ()
    aws-amplify/api/internals:  undefined ()
    aws-amplify/api/server:  undefined ()
    aws-amplify/auth:  undefined ()
    aws-amplify/auth/cognito:  undefined ()
    aws-amplify/auth/cognito/server:  undefined ()
    aws-amplify/auth/enable-oauth-listener:  undefined ()
    aws-amplify/auth/server:  undefined ()
    aws-amplify/data:  undefined ()
    aws-amplify/data/server:  undefined ()
    aws-amplify/datastore:  undefined ()
    aws-amplify/in-app-messaging:  undefined ()
    aws-amplify/in-app-messaging/pinpoint:  undefined ()
    aws-amplify/push-notifications:  undefined ()
    aws-amplify/push-notifications/pinpoint:  undefined ()
    aws-amplify/storage:  undefined ()
    aws-amplify/storage/s3:  undefined ()
    aws-amplify/storage/s3/server:  undefined ()
    aws-amplify/storage/server:  undefined ()
    aws-amplify/utils:  undefined ()
    babel-packages:  undefined ()
    browserify-zlib:  undefined ()
    browserslist:  undefined ()
    buffer:  undefined ()
    bytes:  undefined ()
    ci-info:  undefined ()
    cli-select:  undefined ()
    client-only:  0.0.1
    commander:  undefined ()
    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 ()
    data-uri-to-buffer:  undefined ()
    debug:  undefined ()
    devalue:  undefined ()
    domain-browser:  undefined ()
    edge-runtime:  undefined ()
    events:  undefined ()
    find-up:  undefined ()
    fresh:  undefined ()
    glob:  undefined ()
    gzip-size:  undefined ()
    http-proxy:  undefined ()
    http-proxy-agent:  undefined ()
    https-browserify:  undefined ()
    https-proxy-agent:  undefined ()
    icss-utils:  undefined ()
    ignore-loader:  undefined ()
    image-size:  undefined ()
    is-animated:  undefined ()
    is-docker:  undefined ()
    is-wsl:  undefined ()
    jest-worker:  undefined ()
    json5:  undefined ()
    jsonwebtoken:  undefined ()
    loader-runner:  undefined ()
    loader-utils:  undefined ()
    lodash.curry:  undefined ()
    lru-cache:  undefined ()
    mini-css-extract-plugin:  undefined ()
    nanoid:  undefined ()
    native-url:  undefined ()
    neo-async:  undefined ()
    next: 15.1.7 => 15.1.7
    node-fetch:  undefined ()
    node-html-parser:  undefined ()
    ora:  undefined ()
    os-browserify:  undefined ()
    p-limit:  undefined ()
    p-queue:  undefined ()
    path-browserify:  undefined ()
    path-to-regexp:  undefined ()
    picomatch:  undefined ()
    platform:  undefined ()
    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 ()
    process:  undefined ()
    punycode:  undefined ()
    querystring-es3:  undefined ()
    raw-body:  undefined ()
    react: ^19.0.0 => 19.0.0
    react-builtin:  undefined ()
    react-dom: ^19.0.0 => 19.0.0
    react-dom-builtin:  undefined ()
    react-dom-experimental-builtin:  undefined ()
    react-experimental-builtin:  undefined ()
    react-is:  19.0.0-rc-65e06cb7-20241218
    react-refresh:  0.12.0
    react-server-dom-turbopack-builtin:  undefined ()
    react-server-dom-turbopack-experimental-builtin:  undefined ()
    react-server-dom-webpack-builtin:  undefined ()
    react-server-dom-webpack-experimental-builtin:  undefined ()
    regenerator-runtime:  0.13.4
    sass-loader:  undefined ()
    scheduler-builtin:  undefined ()
    scheduler-experimental-builtin:  undefined ()
    schema-utils:  undefined ()
    semver:  undefined ()
    send:  undefined ()
    server-only:  0.0.1
    setimmediate:  undefined ()
    shell-quote:  undefined ()
    source-map:  undefined ()
    source-map08:  undefined ()
    stacktrace-parser:  undefined ()
    stream-browserify:  undefined ()
    stream-http:  undefined ()
    string-hash:  undefined ()
    string_decoder:  undefined ()
    strip-ansi:  undefined ()
    superstruct:  undefined ()
    tar:  undefined ()
    terser:  undefined ()
    text-table:  undefined ()
    timers-browserify:  undefined ()
    tty-browserify:  undefined ()
    typescript: ^5 => 5.7.3
    ua-parser-js:  undefined ()
    unistore:  undefined ()
    util:  undefined ()
    vm-browserify:  undefined ()
    watchpack:  undefined ()
    web-vitals:  undefined ()
    webpack:  undefined ()
    webpack-sources:  undefined ()
    ws:  undefined ()
    zod:  undefined ()
    zod-validation-error:  undefined ()
  npmGlobalPackages:
    corepack: 0.29.4
    npm: 10.9.0

Describe the bug

In a Next.js application using Amplify JS with guest identities enabled, there's an inconsistency in identity source between server and client components. The server-side correctly uses cookies for guest identity, but the client-side incorrectly uses localStorage instead of cookies, resulting in different identity IDs being used for the same guest user.

The bug only manifests for guest/unauthenticated users in Next.js applications, while authenticated sessions work correctly. This creates potential issues for applications relying on consistent identity management across server and client components.

Expected behavior

Both server-side and client-side sessions should use cookies as the source for guest identities, maintaining consistency across Next.js server and client components, just as they do for authenticated users.

Reproduction steps

  1. Clone the reproduction repository: https://github.com/MarekBodingerBA/amplify-js-guest-identity-bug
  2. Install dependencies
  3. Run the Next.js application
  4. Visit the homepage as an unauthenticated user
  5. Observe that:
    • Server-side session shows an identityId from cookies
    • Client-side session shows a different identityId from localStorage
    • The cookies and localStorage sections clearly show this discrepancy

Note: The authentication flow cannot be tested with this reproduction as it doesn't contain sign in flow. To verify the authenticated behavior, you would need to use your own environment variables and provide respective cookies.

Code Snippet

No response

Log output

No response

aws-exports.js

No response

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

Additional information and screenshots

Guest Identity Output:

Server-side Session:
{
  "credentials": {
    // ... credentials redacted ...
  },
  "identityId": "eu-central-1:id-1"
}

Client-side Session:
{
  "credentials": {
    // ... credentials redacted ...
  },
  "identityId": "eu-central-1:id-2"
}

Client-side Cookies:
com.amplify.Cognito.[poolId].identityId=eu-central-1:id-1

LocalStorage:
{
  "com.amplify.Cognito.[poolId].identityId": "eu-central-1:id-2"
}

Authenticated Identity Output:

Server-side Session:
{
  "credentials": {
    // ... credentials redacted ...
  },
  "identityId": "eu-central-1:id-3",
  "userSub": "user-1"
}

Client-side Session:
{
  "credentials": {
    // ... credentials redacted ...
  },
  "identityId": "eu-central-1:id-3",
  "userSub": "user-1"
}

Client-side Cookies:
CognitoIdentityServiceProvider.[clientId].LastAuthUser=[redacted];
CognitoIdentityServiceProvider.[clientId].[userId].accessToken=[redacted];
CognitoIdentityServiceProvider.[clientId].[userId].idToken=[redacted];
CognitoIdentityServiceProvider.[clientId].[userId].refreshToken=[redacted];
CognitoIdentityServiceProvider.[clientId].[userId].signInDetails=[redacted];
CognitoIdentityServiceProvider.[clientId].[userId].clockDrift=[redacted];

LocalStorage:
{}
@github-actions github-actions bot added pending-triage Issue is pending triage pending-maintainer-response Issue is pending a response from the Amplify team. labels Feb 28, 2025
@MarekBodingerBA
Copy link
Author

I want to ask an extra question - I noticed something with the App Router (I've only used Pages Router in production before). Without middleware, on each page refresh a new guest identity gets created. But when I add this no-op middleware, the identity cookie gets set properly and stays consistent. As I understand, it is not possible to modify headers (therefore set the cookies) directly in pages. Is this the recommended way to handle identity cookies in Next.js App Router with Amplify?

@HuiSF HuiSF added SSR Issues related to Server Side Rendering Next.js labels Feb 28, 2025
@cwomack cwomack added bug Something isn't working and removed pending-triage Issue is pending triage labels Feb 28, 2025
@cwomack
Copy link
Member

cwomack commented Feb 28, 2025

Hello, @MarekBodingerBA 👋 and thank you for opening this issue. We're marking this as a bug, as it indeed appears that the identityId differs on the client side and server side for unauth role users. If we have any further questions or updates on progress for this, we'll follow up with a new comment.

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending a response from the Amplify team. label Feb 28, 2025
@HuiSF
Copy link
Member

HuiSF commented Feb 28, 2025

Hi @MarekBodingerBA Could you also provide some more details about your use cases so we can do some analysis on this issue. Much appreciated.

  1. Could provide sample code of how you are using the unauthenticated role from your server side?
  2. Regarding the extra issue - "without the middleware, on each page refresh a new guest identity gets created", could you provide sample code for triggering this behavior?

Also regarding your extra question, Next.js App router doesn't allow SetCookie headers to be set from a React Server Component backed page route, but only from the middleware, an API route or a Server Action. So yes, in general, if you want to set consistent cookie, the middleware is the best spot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Next.js SSR Issues related to Server Side Rendering
Projects
None yet
Development

No branches or pull requests

3 participants