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

Popup login with Google provider instead or redirect #8030

Open
mayank1513 opened this issue Jul 13, 2023 · 2 comments
Open

Popup login with Google provider instead or redirect #8030

mayank1513 opened this issue Jul 13, 2023 · 2 comments
Labels
enhancement New feature or request triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.

Comments

@mayank1513
Copy link

Description 📓

Currently, there is no clean way to use popup login with Google provider. User should be able to simply provide an option and next-auth should take care of opening up a popup window to complete the authentication instead of redirecting to the provider's page.

How to reproduce ☕️

Create a simple auth page with Google provider.

Contributing 🙌🏽

Yes, I am willing to help implement this feature in a PR

@mayank1513 mayank1513 added enhancement New feature or request triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. labels Jul 13, 2023
@mayur-padshala
Copy link

Any solutions for NextAuth.js v5? Were you able to implement this in a clean way?

@gengue
Copy link

gengue commented Feb 26, 2025

It's not that clean but it works:

// (auth)/login/page.tsx
'use client';

import Form from 'next/form';
import { useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { Logo } from '@/components/logo';

export default function Page() {

  const handleLogin = async () => {
    const url = '/login/google';
    const title = 'Sign in with Google';
    const width = 600;
    const height = 600;
    const left = (window.screen.width - width) / 2;
    const top = (window.screen.height - height) / 2;

    const newWindow = window.open(
      url,
      title,
      `width=${width},height=${height},top=${top},left=${left}`,
    );
    newWindow?.focus();
  };

  useEffect(() => {
    const messageHandler = (event: MessageEvent) => {
      // Ensure the message is from the same origin
      if (event.origin !== window.location.origin) return;
      if (event.data?.status === 'authenticated') {
        window.location.reload();
      }
    };

    window.addEventListener('message', messageHandler);
    return () => window.removeEventListener('message', messageHandler);
  }, []);

  return (
    <div className="flex h-dvh w-screen items-start pt-12 md:pt-0 md:items-center justify-center bg-background">
      <div className="w-full max-w-md overflow-hidden rounded-2xl flex flex-col gap-6 align-center">
        <Logo width={120} height={120} className="self-center" />
        <Form action={handleLogin} className="flex justify-center">
          <Button type="submit">
            <svg
              role="img"
              viewBox="0 0 24 24"
              xmlns="http://www.w3.org/2000/svg"
            >
              <title>Google</title>
              <path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" />
            </svg>
            Signin with Google 
          </Button>
        </Form>
      </div>
    </div>
  );
}

// (auth)/login/google/page.tsx
'use client';
import { signIn } from 'next-auth/react';
import { useEffect } from 'react';

const SignInPage = () => {
  useEffect(() => {
    signIn('google', { redirectTo: '/login/google/popup-callback' });
  }, []);

  return (
    <div
      style={{ width: '100vw', height: '100vh',
        position: 'absolute', left: 0,
        top: 0, background: 'white',
      }}
    ></div>
  );
};

export default SignInPage;

// (auth)/login/google/popup-callback/page.tsx
'use client';
import { useEffect } from 'react';

export default function PopupCallback() {
  useEffect(() => {
    if (window.opener) {
      window.opener.postMessage(
        { status: 'authenticated' },
        window.location.origin,
      );
      window.close();
    }
  }, []);

  return <div>Logging you in...</div>;
}

I'm sure it can be improved, one of the pages can be fully removed it if the popup open the oauth url from the start

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.
Projects
None yet
Development

No branches or pull requests

3 participants