Session is not showing IP and user agent in nextjs #1978

Closed
opened 2026-03-13 09:18:40 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @Stealthwriter on GitHub (Sep 20, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Hi, I'm getting the user session in the server in nextjs, when I console log the session it doesn't show the Ip or useragent, why?

session {
session: {
expiresAt: 2025-09-27T10:05:13.419Z,
token: 'Qux6t6fuMlFXUeYuiRDqpVpbk1W24RMu',
createdAt: 2025-09-20T10:05:13.419Z,
updatedAt: 2025-09-20T10:05:13.419Z,
ipAddress: '',
userAgent: '',
userId: 'f6e1a4c3-c06e-4cca-8b4a-5f8ac00a8e4b',
impersonatedBy: null,
id: 'o0xiOOXcEqjxvrIvoUt4aCNmJjBhrPWe'
},
user: {
name: 'asd',

Current vs. Expected behavior

shows ip and user agent

What version of Better Auth are you using?

1.3

System info

nextjs

Which area(s) are affected? (Select all that apply)

Backend

Auth config (if applicable)

import { betterAuth } from "better-auth"
export const auth = betterAuth({
  emailAndPassword: {  
    enabled: true
  },
});

Additional context

No response

Originally created by @Stealthwriter on GitHub (Sep 20, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce Hi, I'm getting the user session in the server in nextjs, when I console log the session it doesn't show the Ip or useragent, why? session { session: { expiresAt: 2025-09-27T10:05:13.419Z, token: 'Qux6t6fuMlFXUeYuiRDqpVpbk1W24RMu', createdAt: 2025-09-20T10:05:13.419Z, updatedAt: 2025-09-20T10:05:13.419Z, ipAddress: '', userAgent: '', userId: 'f6e1a4c3-c06e-4cca-8b4a-5f8ac00a8e4b', impersonatedBy: null, id: 'o0xiOOXcEqjxvrIvoUt4aCNmJjBhrPWe' }, user: { name: 'asd', ### Current vs. Expected behavior shows ip and user agent ### What version of Better Auth are you using? 1.3 ### System info ```bash nextjs ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript import { betterAuth } from "better-auth" export const auth = betterAuth({ emailAndPassword: { enabled: true }, }); ``` ### Additional context _No response_
GiteaMirror added the nextjs label 2026-03-13 09:18:40 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Sep 20, 2025):

Better Auth does not automatically populate the ipAddress and userAgent fields in sessions for emailAndPassword authentication in Next.js. These fields are only set if the relevant headers (like x-forwarded-for and user-agent) are present and correctly forwarded to the authentication logic during sign-in or session creation. In many Next.js setups, especially with server components or API routes, these headers may not be forwarded by default, which leaves the fields empty example.

To ensure these fields are set, you need to explicitly forward the headers when calling sign-in or sign-up methods. For local development, if your IP is ::1 (IPv6 localhost), Better Auth may ignore it—replace it with 127.0.0.1 in your headers. Here’s a pattern that works:

const ip = header_res.get('x-forwarded-for');
await auth.api.signInEmail({
  body: { email, password },
  headers: {
    'x-forwarded-for': ip === '::1' ? '127.0.0.1' : ip,
    'user-agent': header_res.get('user-agent'),
  },
});

Make sure your Better Auth config includes the nextCookies plugin as the last plugin, and if you’re using proxies or server actions, always forward the necessary headers and cookies. If you’re running in a cross-origin setup or using server components, you may need to proxy requests through an API route to ensure all headers and cookies are present details.

If you follow these steps and still see empty fields, double-check your network/proxy setup and ensure your headers are actually reaching the Better Auth backend.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

@dosubot[bot] commented on GitHub (Sep 20, 2025): <!-- Answer --> Better Auth does not automatically populate the ipAddress and userAgent fields in sessions for emailAndPassword authentication in Next.js. These fields are only set if the relevant headers (like x-forwarded-for and user-agent) are present and correctly forwarded to the authentication logic during sign-in or session creation. In many Next.js setups, especially with server components or API routes, these headers may not be forwarded by default, which leaves the fields empty [example](https://github.com/better-auth/better-auth/issues/2117). To ensure these fields are set, you need to explicitly forward the headers when calling sign-in or sign-up methods. For local development, if your IP is ::1 (IPv6 localhost), Better Auth may ignore it—replace it with 127.0.0.1 in your headers. Here’s a pattern that works: ```js const ip = header_res.get('x-forwarded-for'); await auth.api.signInEmail({ body: { email, password }, headers: { 'x-forwarded-for': ip === '::1' ? '127.0.0.1' : ip, 'user-agent': header_res.get('user-agent'), }, }); ``` Make sure your Better Auth config includes the nextCookies plugin as the last plugin, and if you’re using proxies or server actions, always forward the necessary headers and cookies. If you’re running in a cross-origin setup or using server components, you may need to proxy requests through an API route to ensure all headers and cookies are present [details](https://github.com/better-auth/better-auth/issues/2055). If you follow these steps and still see empty fields, double-check your network/proxy setup and ensure your headers are actually reaching the Better Auth backend. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/167f9937-a82a-4f21-a3ee-bd42d6a23bd3?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/167f9937-a82a-4f21-a3ee-bd42d6a23bd3?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/167f9937-a82a-4f21-a3ee-bd42d6a23bd3?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/167f9937-a82a-4f21-a3ee-bd42d6a23bd3?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/167f9937-a82a-4f21-a3ee-bd42d6a23bd3?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/167f9937-a82a-4f21-a3ee-bd42d6a23bd3?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/167f9937-a82a-4f21-a3ee-bd42d6a23bd3?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4782)
Author
Owner

@Kinfe123 commented on GitHub (Sep 20, 2025):

if you are not behind any proxy or load balancer or sth, it should be working by default for local it should should be unknown and if you are behind proxy or sth make sure to mention on the ipAddress config - https://www.better-auth.com/docs/reference/options#advanced or make sure you are passing the correct headers request

@Kinfe123 commented on GitHub (Sep 20, 2025): if you are not behind any proxy or load balancer or sth, it should be working by default for local it should should be unknown and if you are behind proxy or sth make sure to mention on the ipAddress config - https://www.better-auth.com/docs/reference/options#advanced or make sure you are passing the correct headers request
Author
Owner

@state303 commented on GitHub (Dec 17, 2025):

For anyone who stumbled on this, albeit the header does have valid x-forwarded-for or x-real-ip and such...

export const auth = betterAuth({

  ...

  databaseHooks: {
    session: {
      create: {
        before: async (session, ctx) => {
          const xff = ctx?.request?.headers?.get('x-forwarded-for');
          const realIp = ctx?.request?.headers?.get('x-real-ip');
          const ip = xff?.split(',')[0].trim() || realIp || session.ipAddress;
          return {
            data: {
              ...session,
              ipAddress: ip,
            },
          };
        },
      },
    },
  },

  ...

});

This assumes that you have a valid headers, AND if it still does not working.

@state303 commented on GitHub (Dec 17, 2025): For anyone who stumbled on this, albeit the header does have valid x-forwarded-for or x-real-ip and such... ```ts export const auth = betterAuth({ ... databaseHooks: { session: { create: { before: async (session, ctx) => { const xff = ctx?.request?.headers?.get('x-forwarded-for'); const realIp = ctx?.request?.headers?.get('x-real-ip'); const ip = xff?.split(',')[0].trim() || realIp || session.ipAddress; return { data: { ...session, ipAddress: ip, }, }; }, }, }, }, ... }); ``` This assumes that you have a valid headers, AND if it still does not working.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1978