Redirect breaks auth.apis. APIs don't follow redirects #845

Closed
opened 2026-03-13 08:06:47 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @mishelen on GitHub (Mar 14, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Create plugin extending get-session via redirect to other option of session management

export const anonymousSessionPlugin = () => {
  return {
    id: "plugin-anonymous-session",
    endpoints: {
      getAnonymousSession: createAuthEndpoint(
        "/get-anonymous-session",
        { method: "GET" },
        async (ctx) => {
          return ctx.json({ session: null, user: null });
        }
      )
    },
    hooks: {
      before: [
        {
          matcher: (context) => context.path === "/get-session",
          handler: createAuthMiddleware(async (ctx) => {   
            if (!ctx.getCookie("better-auth")) {
              // `return` instead of `throw` will throw.
              throw ctx.redirect("/api/auth/get-anonymous-session");
            }
          })
        }
      ]
    }
  };
};

create RSC in the Next. something like:

export default async function ProfilePage() {
  const response = await auth.api.getSession({// <= returns Error [APIError]
    headers: await headers(),
  });
  return (<div/>);
}

Expect Error on Next.js level:

Error: An error occurred in the Server Components render but no message was provided

Current vs. Expected behavior

auth.api.[whatever] doesn't follow redirects and treats them as just errors...

What version of Better Auth are you using?

^1.1.18

Provide environment information

- OS ubunty
- browser firefox

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 @mishelen on GitHub (Mar 14, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce Create plugin extending `get-session` via redirect to other option of session management ```js export const anonymousSessionPlugin = () => { return { id: "plugin-anonymous-session", endpoints: { getAnonymousSession: createAuthEndpoint( "/get-anonymous-session", { method: "GET" }, async (ctx) => { return ctx.json({ session: null, user: null }); } ) }, hooks: { before: [ { matcher: (context) => context.path === "/get-session", handler: createAuthMiddleware(async (ctx) => { if (!ctx.getCookie("better-auth")) { // `return` instead of `throw` will throw. throw ctx.redirect("/api/auth/get-anonymous-session"); } }) } ] } }; }; ``` create RSC in the Next. something like: ```tsx export default async function ProfilePage() { const response = await auth.api.getSession({// <= returns Error [APIError] headers: await headers(), }); return (<div/>); } ``` Expect Error on Next.js level: ``` Error: An error occurred in the Server Components render but no message was provided ``` ### Current vs. Expected behavior `auth.api.[whatever]` doesn't follow redirects and treats them as just errors... ### What version of Better Auth are you using? ^1.1.18 ### Provide environment information ```bash - OS ubunty - browser firefox ``` ### 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 bug label 2026-03-13 08:06:47 -05:00
Author
Owner

@mishelen commented on GitHub (Mar 14, 2025):

A bit of an update, I did make it work, but is that how it should be? It doesn't look good:

export default async function ProfilePage() {
  let response: Session | null = null;
  try {
    response = await auth.api.getSession({
      headers: await headers(),
    });
  } catch (e) {
    if (e instanceof APIError && e.statusCode === 302) {
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-expect-error
      response = await auth.api.getAnonymousSession({
        headers: await headers(),
      });
    }
  }

  return (<div/>);
}

Just manual redirect. I note that infering types for the API doesn't work completely.

@mishelen commented on GitHub (Mar 14, 2025): A bit of an update, I did make it work, but is that how it should be? It doesn't look good: ```tsx export default async function ProfilePage() { let response: Session | null = null; try { response = await auth.api.getSession({ headers: await headers(), }); } catch (e) { if (e instanceof APIError && e.statusCode === 302) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error response = await auth.api.getAnonymousSession({ headers: await headers(), }); } } return (<div/>); } ``` Just manual redirect. I note that infering types for the API doesn't work completely.
Author
Owner

@Kinfe123 commented on GitHub (Mar 16, 2025):

this behaviour is expected to just throw an API error instead of redirection since it also couples with mostly with non-RSC api calls . it does not feel good to add it there but plugin that extends those functionality with redirections metadatas makes sense to add on this to apply for RSC as well.

@Kinfe123 commented on GitHub (Mar 16, 2025): this behaviour is expected to just throw an API error instead of redirection since it also couples with mostly with non-RSC api calls . it does not feel good to add it there but plugin that extends those functionality with redirections metadatas makes sense to add on this to apply for RSC as well.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#845