Solved

Google Sign In in Front App


Badge +3

We Are trying to implement a Plugin using the Google Sign Button. The problem is however that the sign does not work because Google is trying to open a new window. That of course doesn't work in the plug-in within the Front app. 

 

Hence, my question is if anyone else has built such an integration and how did they manage to integrate Google sign in within the Front app plugin?

icon

Best answer by xdmnl 27 March 2024, 21:05

View original

22 replies

Userlevel 4
Badge +7

Hi @josula , Using the openUrlInPopup SDK method to open your new auth window should help resolve this issue. 

Let us know if you have questions!

Badge +3

Thanks this got the Login to work at least but how can I set cookies in the front app then for my auth? I am using next-auth with the google sign in… 

Right now I can signin in the popup but then in my plugin I am still not logged in. I guess its because it is not acually setting the auth cookies correctly

Userlevel 4
Badge +7

I put together a basic demo app using Next.js (though not next-auth) recently which sets cookies via Server Actions - https://github.com/dugjason/nextjs-front-plugin-with-cookie 

Importantly you should ensure you’re setting a partioned cookie to comply with upcoming browser privacy proposals (see this post for details), as well as setting samesite: ‘none’ and secure: true. 

It looks like next-auth allows for you to send custom instructions to be used when creating cookies (see next-auth docs). I believe sending something like the following in your next-auth config should work;

...

{
...
cookies: {
sameSite: 'none',
secure: true,
partitioned: true,
}
}

Looking forward to hearing how that goes 🤞

Badge +3

Thanks to me it is still not clear how it works with cookies across multiples domains.

I have this signin logic:

 

import { useFrontContext } from "@/providers/frontContext";
import { signIn, useSession } from "next-auth/react";
import { useRouter } from "next/router";

export default function Login() {
const { data, status } = useSession();

console.log("session", data, status);
const router = useRouter();
const context = useFrontContext();

const handleSignIn = () => {
if (context) {
context.openUrlInPopup(
"http://localhost:3000/api/auth/signin/google",
{}
);
} else {
signIn("google", { callbackUrl: "/offers" });
}
};
if (status === "authenticated") {
router.push("/youAreLoggedIn");
}

return (
<>
<button
onClick={() => handleSignIn()}
className="text-sm font-semibold leading-6"
>
Google
</button>
</>
);
}

Then when I click on the button it opens a new tab (when I am opening in the front app), and I get redirected to the API endpoint via this /api endpoint in nextjs:

 

import NextAuth, { AuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";
export const authOptions: AuthOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_ID as string,
clientSecret: process.env.GOOGLE_SECRET as string,
}),
],
session: {
strategy: "jwt",
},
};

export default NextAuth(authOptions);

However then I can see that the next-auth tokens are set correctly in the localhost:3000 Cookie tab under the Applications in  Dev Tools but I cannot see them in my frontapp.com cookie tab and I do not know how this cross website auth could possbily work

 

 

Can anyone support here what I might be missing?

Badge +3

 Thanks to me it is still not clear how it works with cookies across multiples domains.

I have this signin logic:

import { useFrontContext } from "@/providers/frontContext";
import { signIn, useSession } from "next-auth/react";
import { useRouter } from "next/router";

export default function Login() {
const { data, status } = useSession();

console.log("session", data, status);
const router = useRouter();
const context = useFrontContext();

const handleSignIn = () => {
if (context) {
context.openUrlInPopup(
"http://localhost:3000/api/auth/signin/google",
{}
);
} else {
signIn("google", { callbackUrl: "/offers" });
}
};
if (status === "authenticated") {
router.push("/youAreLoggedIn");
}

return (
<>
<button
onClick={() => handleSignIn()}
className="text-sm font-semibold leading-6"
>
Google
</button>
</>
);
}

Then when I click on the button it opens a new tab (when I am opening in the front app), and I get redirected to the API endpoint via this /api endpoint in nextjs:

 

import NextAuth, { AuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";
export const authOptions: AuthOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_ID as string,
clientSecret: process.env.GOOGLE_SECRET as string,
}),
],
session: {
strategy: "jwt",
},
};

export default NextAuth(authOptions);

However then I can see that the next-auth tokens are set correctly in the localhost:3000 Cookie tab under the Applications in  Dev Tools but I cannot see them in my frontapp.com cookie tab and I do not know how this cross website auth could possbily work

Can anyone support here what I might be missing?

Badge +3

I mean I cannot possibly be the first one to ever implement google auth in a front plugin?

Badge +3

Sorry my previous answer has not been accepted by the admins of this forum yet. My last post seems a bit out of context now

Userlevel 5
Badge +8

Sorry @josula the spam filters mistakenly flagged your replies. FYI @jason 

Badge +3

Does anyone have a clue? Basically I am looking for a working example of embedding an iframe including Google Auth ideally via next-auth in react.

I manage to open the auth in a new tab but then the cookies are not written correctly back to front so that my auth session claims I am not logged in...

Badge +3

So what works:

  1. I have a google sign in button in my iframe / plugin
  2. It opens a new tab in my front application where I signin
  3. I can see in my cookies that I do have my Cookies under `localhost:3000` - where my plugin is currently running - the cookies are set correctly.
  4. I can also see in the other Cookie tab of Front that my front_id etc are set coorectly.

  5. The problem is: When I come back to my plugin in front it shows me the “Sign in with google” button again, because it does not find the session because it is stored in the localhost cookie tab. 

I am not sure what to do here.

Userlevel 4
Badge +7

Hi @josula , I’ll admin I’m not 100% sure why this works, and it’s not pretty, but I’ve put together a sample repo that does work; https://github.com/dugjason/nextauth4-front-plugin 

@jason’s code sample works because of this specific line that sets partitioned cookies as recommended by our article on Replacing third-party cookies in Front plugins.
This is the recommended solution because it is completely transparent for the end-user.

Alternatively, your plugin can use the Storage Access API to ask the user permission to use third-party cookies.

Badge +3

I have been trying for weeks now: I manage to implement the tool so I can use it in front via iFrame and google Auth but now I cannot use it in a regular browser anymore because the cookies are not set securely via the popup window to the parent. I have spent countless hours trying to fix this. It is incredibly frustrating and delaying our deployment since weeks now….

 

In Chrome my App only runs if the next-auth.session-key is set with a “__Secure-….” in front of it. If I do this however, then my Front App wont pass my auth anymore because it expects it differently.

 

So either one works (Front Integration) or my Browser….

Below my authOptions:

import { NextAuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";

const cookieOptions = {
httpOnly: true,
partitioned: true,
sameSite: "none" as "none",
secure: true,
path: "/",
};

export const authOptions: NextAuthOptions = {
secret: process.env.NEXTAUTH_SECRET,

// Configure one or more authentication providers
providers: [
GoogleProvider({
clientId: process.env.AUTH_GOOGLE_ID as string,
clientSecret: process.env.AUTH_GOOGLE_SECRET as string,
}),
],

// Update cookie options to be secure and sameSite: 'none' and partioned
cookies: {
sessionToken: {
name: `next-auth.session-token`,
options: cookieOptions,
},
callbackUrl: {
name: `next-auth-callback-url`,
options: cookieOptions,
},
csrfToken: {
name: `next-auth.csrf-token`,
options: cookieOptions,
},
pkceCodeVerifier: {
name: `next-auth.pkce.code_verifier`,
options: cookieOptions,
},
},
};

 

Then my middleware:

import { authOptions } from "@/lib/auth/auth-options";
import withAuth from "next-auth/middleware";

export default withAuth({
jwt: { decode: authOptions.jwt?.decode },
callbacks: {
authorized: ({ token }) => !!token,
},
pages: {
signIn: "/signin",
error: "/error",
},
});

export const config = { matcher: ["/", "/offers", "/offer/:path"] };

And my API route in Next JS:

import NextAuth from "next-auth";

import { authOptions } from "@/lib/auth/auth-options";

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };

 

 

 

This issue is incredibly time consuming on our end. I do not really understand how Front does not have this (Provider OAuth) out of the box? Our internal stakeholders are waiting since weeks for this feature and we simply cannot release it because of this auth topic

Userlevel 4
Badge +7

Hi @josula , can you help me understand what you’re experiencing when you keep the __Secure prefix on the cookie names in Front? I’m having trouble replicating what you’re reporting. 

I’ll re-share that repo and a hosted example where it works both in-browser and in Front:

I’m seeing it logs in successfully, and will allow you to access a /secure page only when logged in. 

 

Something to note about Front plugins is that they are best built as a single-page app, and use states (rather than pages/paths) to alter that’s being shown to the user. Given that Front plugins are typically designed with a “mobile-first” layout given the small max-width, we often find developers will add a separate page to their app for the Front plugin, and render components as needed in the smaller viewport. 

Badge +3

Thanks for sharing this. I seriously copied everything 1:1. When I click on “Sign In” in my app it redirects me immediately to /api/auth/signin?csrf=true and just shows me the sign in with google button - on click on the button nothing happens at all… 

 

I seriously checked each file 100 times and just copied them from your repo… 😅

 

But I do agree: Your example works fine. Could it be that my Google Auth is wrongly configured?! But I cant really believe this, it worked fine before

 

 

Userlevel 4
Badge +7

So when initiating a sign-in in my version, we use an onclick handler (see code) to open a new window containing this page where the user clicks to start the auth process (but the plugin page remains unchanged). 

I think what might be happening for you is that the user is being redirected to the login auth page inside the iframe. They then click sign in, the OAuth popup window opens and they start the auth flow, but it can’t update the page rendered in the iframe, so you get stuck at this point. 

I hope that helps unblock you! 🤞

Badge +3

Thanks I copied all of that over, I replaced all successive components with your code: I end up at the weird Google Sign In button that does nothing… I will have to take yet another look tomorrow morning, I think it might also be some .env or Google Config stuff. But I doubt it since this already worked before

Badge +3

I just cloned and replicated your repo and it works fine on my machine. there is some difference somewhere I will try to find tomorrow. Thanks again for all the support

Userlevel 4
Badge +7

Just sharing a screenshot from my Google OAuth console to show how I configured the origin/redirect URL for the hosted app;

Screenshot from Google OAuth console 

 

Badge +3

Thanks for sharing! Funny enough, if I clone the current repo, add my .env file and Click on SIgn In in Chrome I get the same issue as I do currently. I even removed and cloned your repo again. This is incredibly weird. It is in Chrome and Brave though

 

Badge +3

Ok this was wild but I got it now: The problem was with security of local vs prod and the including __Secure- prefix. I am setting an env in prod now like so:

 

const productionPrefix process.env.AUTH_REQUIREMENT === "PRODUCTION" ? "__Secure-" : "";

And then my cookies like so:

 

cookies: {

sessionToken: {

name: `${productionPrefix}next-auth.session-token`,

options: cookieOptions,

},

}

 

This finally got it to work in both prod as well as local. 

 

It should be alright security wise I guess since it is all server side.

Userlevel 4
Badge +7

Great to hear you got it working! 🚀

Reply