Setting cookies with custom plugin auth

Hi, I'm having a few issues with setting this up the way that I want it to but I may be approaching it from the wrong way. I am using another application that I want users to be able to single click sign on into but it is not an Idp or oauth provider. Instead it providers a token in the URL that I can decrypt. The current imagined workflow is as follows: 1. User clicks button 2. Gets sent to /api/auth/test/sso 3. Create a new plugin that creates a new auth endpoint to decrypt it, create a new user if doesnt exists. 4. Redirect the user to the authenticated /dashboard page. I have created a very simple poc which assumes that all the verification is complete.
import { BetterAuthPlugin, createAuthEndpoint } from "better-auth/plugins";

export const tutorcruncherPlugin = () => {
return {
id: "test",
endpoints: {
sso: createAuthEndpoint(
"/test/sso",
{
method: "GET",
},
async (ctx) => {
// Verify stuff - assume that it passes

// this is a sample user that I added for testing.
const user = await ctx.context.internalAdapter.findUserById(
"Bvptc4rkZplmGgzFmx4DylRqVgJbjjIv",
);

const session = await ctx.context.internalAdapter.createSession(
"Bvptc4rkZplmGgzFmx4DylRqVgJbjjIv",
ctx.request,
);

ctx.context.setNewSession({
session: session,
user: user!,
});

return ctx.redirect("/dashboard");
},
),
},
} satisfies BetterAuthPlugin;
};
import { BetterAuthPlugin, createAuthEndpoint } from "better-auth/plugins";

export const tutorcruncherPlugin = () => {
return {
id: "test",
endpoints: {
sso: createAuthEndpoint(
"/test/sso",
{
method: "GET",
},
async (ctx) => {
// Verify stuff - assume that it passes

// this is a sample user that I added for testing.
const user = await ctx.context.internalAdapter.findUserById(
"Bvptc4rkZplmGgzFmx4DylRqVgJbjjIv",
);

const session = await ctx.context.internalAdapter.createSession(
"Bvptc4rkZplmGgzFmx4DylRqVgJbjjIv",
ctx.request,
);

ctx.context.setNewSession({
session: session,
user: user!,
});

return ctx.redirect("/dashboard");
},
),
},
} satisfies BetterAuthPlugin;
};
The above code does not add the cookies into the browser and does not set them either. I have added the nextCookies plugin as well as the methods ctx.setCookie from https://www.better-auth.com/docs/concepts/hooks#cookies. Any help would be greatly appreciated - losing my mind over this.
Hooks | Better Auth
Better Auth Hooks let you customize BetterAuth's behavior
6 Replies
Andy
AndyOP4d ago
I can hit the endpoint and it correctly redirects me but doesn't include any Set-Cookie headers when i try to set it, neither does it include the Cookies when checking the browser storage
KiNFiSH
KiNFiSH4d ago
Have you tried to use ctx object to set the cookie ?
Andy
AndyOP4d ago
I have tried that but was missing a step. I got it work by mimicking how the better-auth library signs the tokens instead here :
const signedtoken = await createHMAC("SHA-256", "base64urlnopad").sign(
ctx.context.secret,
session.token,
);

ctx.setCookie("better-auth.session_token", signedtoken, {
expires: session.expiresAt,
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: "lax",
path: "/",
});

// Set the secure cookie in prod
if (process.env.NODE_ENV === "production") {
ctx.setCookie("__secure-better-auth.session_token", signedtoken, {
expires: session.expiresAt,
httpOnly: true,
secure: true,
sameSite: "lax",
path: "/",
});
}

return ctx.redirect("/");
},
const signedtoken = await createHMAC("SHA-256", "base64urlnopad").sign(
ctx.context.secret,
session.token,
);

ctx.setCookie("better-auth.session_token", signedtoken, {
expires: session.expiresAt,
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: "lax",
path: "/",
});

// Set the secure cookie in prod
if (process.env.NODE_ENV === "production") {
ctx.setCookie("__secure-better-auth.session_token", signedtoken, {
expires: session.expiresAt,
httpOnly: true,
secure: true,
sameSite: "lax",
path: "/",
});
}

return ctx.redirect("/");
},
Is there an easier way than this? I would have assumed that the ctx.context.setNewSession method would be doing this already
KiNFiSH
KiNFiSH4d ago
Yeah but all this stuff is encapsulated by better auth on the methods from the ctx
Andy
AndyOP3d ago
Sorry - but im super confused I have no idea what you mean, is there an easier way of doing this? I can see that there is a ctx.context.createAuthCookie() but its not very well documented here: https://www.better-auth.com/docs/concepts/plugins#endpoints and cuts off. This is the exact line:
createAuthCookie: This is a helper function that let's you get a cookie name and options for either to set or get cookies. It implements things like __secure prefix and __host prefix for cookies based on
createAuthCookie: This is a helper function that let's you get a cookie name and options for either to set or get cookies. It implements things like __secure prefix and __host prefix for cookies based on
Would it be possible for anyone to provide an example of using this function? I have looked at the source code for better-call and this seems to be creating the two-factor cookie:
const cookieName = ctx.context.createAuthCookie(TWO_FACTOR_COOKIE_NAME);
const twoFactorCookie = await ctx.getSignedCookie(
cookieName.name,
ctx.context.secret,
);
const cookieName = ctx.context.createAuthCookie(TWO_FACTOR_COOKIE_NAME);
const twoFactorCookie = await ctx.getSignedCookie(
cookieName.name,
ctx.context.secret,
);
But the createAuthCookie, doen't seem to actually create the cookie - just confused about how to do this, especially in prod, where i'm not sure if __secure-better-auth.session_token is the correct name for it
Plugins | Better Auth
Learn how to use plugins with Better Auth.
Andy
AndyOP2d ago
Hi, is there any help with this - it seems that I'm incorrectly signing the cookies so everytime i try to use the getSession it fails. I can't find anywhere where it states how to create your own cookies/session/users by using an alternative authentication logic route. Would anyone have an example of how this could be done and for it to be recognised correctly? I can see the cookies in the browser, they're just not being verified by better-auth / extracting the session data out of them All good, got it to work by following steps of another plugin

Did you find this page helpful?