Session Strategies
Auth Socials Strategy

Remix Auth Socials Strategy

A collection of Remix Auth strategies for Oauth2 Social logins.

It's rare to see only one social login button, and no one likes a big package.json so here we are 👀

Remix auth socials collates community Oauth packages in a way that allows you to set up multiple social logins with ease.

Supported runtimes

RuntimeHas Support
Node.js
Cloudflare

The Collection:

Please visit the repo's of each package to understand the specifics on their usage, and raise issues.

remix-auth-discord (opens in a new tab) - By Jonny (opens in a new tab)

remix-auth-facebook (opens in a new tab) - By Manos (opens in a new tab)

remix-auth-github (opens in a new tab) - By Sergio (opens in a new tab)

remix-auth-google (opens in a new tab) - By Bhanu (opens in a new tab)

remix-auth-microsoft (opens in a new tab) - By Juhana (opens in a new tab)

remix-auth-twitter (opens in a new tab) - By na2hiro (opens in a new tab)

Install the package

npm install remix-auth-socials

Create the strategy instance

app/utils/auth.server.ts
import { Authenticator } from "remix-auth";
import {
  GoogleStrategy,
  FacebookStrategy,
  SocialsProvider,
} from "remix-auth-socials";
import { sessionStorage } from "~/services/session.server";
 
// Create an instance of the authenticator
export let authenticator = new Authenticator(sessionStorage, {
  sessionKey: "_session",
});
// You may specify a <User> type which the strategies will return (this will be stored in the session)
// export let authenticator = new Authenticator<User>(sessionStorage, { sessionKey: '_session' });
 
const getCallback = (provider: SocialsProvider) => {
  return `http://localhost:3333/auth/${provider}/callback`;
};
 
authenticator.use(
  new GoogleStrategy(
    {
      clientID: "YOUR_CLIENT_ID",
      clientSecret: "YOUR_CLIENT_SECRET",
      callbackURL: getCallback(SocialsProvider.GOOGLE),
    },
    async ({ profile }) => {
      // here you would find or create a user in your database
      return profile;
    }
  )
);
 
authenticator.use(
  new FacebookStrategy(
    {
      clientID: "YOUR_CLIENT_ID",
      clientSecret: "YOUR_CLIENT_SECRET",
      callbackURL: getCallback(SocialsProvider.FACEBOOK),
    },
    async ({ profile }) => {}
  )
);

Setup your routes

app/routes/auth/$provider.tsx
import { ActionArgs, redirect } from "@remix-run/node";
import { authenticator } from "~/server/auth.server";
 
export let loader = () => redirect("/login");
 
export let action = ({ request, params }: ActionArgs) => {
  return authenticator.authenticate(params.provider, request);
};
app/routes/auth/$provider.callback.tsx
import { LoaderArgs } from "@remix-run/node";
import { authenticator } from "~/server/auth.server";
 
export let loader = ({ request, params }: LoaderArgs) => {
  return authenticator.authenticate(params.provider, request, {
    successRedirect: "/dashboard",
    failureRedirect: "/login",
  });
};
app/routes/login.tsx
import { Form } from "@remix-run/react";
import { SocialsProvider } from "remix-auth-socials";
 
interface SocialButtonProps {
  provider: SocialsProvider;
  label: string;
}
 
const SocialButton: React.FC<SocialButtonProps> = ({ provider, label }) => (
  <Form action={`/auth/${provider}`} method="post">
    <button>{label}</button>
  </Form>
);
 
export default function Login() {
  return (
    <>
      <SocialButton
        provider={SocialsProvider.DISCORD}
        label="Login with Discord"
      />
      <SocialButton
        provider={SocialsProvider.GITHUB}
        label="Login with Github"
      />
      <SocialButton
        provider={SocialsProvider.GOOGLE}
        label="Login with Google"
      />
      <SocialButton
        provider={SocialsProvider.FACEBOOK}
        label="Login with Facebook"
      />
      <SocialButton
        provider={SocialsProvider.MICROSOFT}
        label="Login with Microsoft"
      />
    </>
  );
}
app/routes/logout.tsx
import { ActionArgs } from "@remix-run/node";
import { authenticator } from "~/server/auth.server";
 
export let action = async ({ request, params }: ActionArgs) => {
  await authenticator.logout(request, { redirectTo: "/" });
};

Add a protected route and an automatic success redirect

Here's an example of a protected route

app/routes/dashboard.tsx
import { useLoaderData, Form } from "@remix-run/react";
import { LoaderArgs } from "@remix-run/node";
import { authenticator } from "~/server/auth.server";
 
export let loader = async ({ request, params }: LoaderArgs) => {
  const user = await authenticator.isAuthenticated(request, {
    failureRedirect: "/",
  });
 
  return { user };
};
 
export default function Dashboard() {
  const { user } = useLoaderData<typeof loader>();
 
  return (
    <div>
      <h1>Welcome {user.displayName}!</h1>
      <p>This is a protected page</p>
      <Form action="/logout" method="post">
        <button>Logout</button>
      </Form>
    </div>
  );
}

You might also want your index route to redirect to the dashboard for logged in users.

app/routes/index.tsx
import { useLoaderData } from "@remix-run/react";
import { LoaderArgs } from "@remix-run/node";
import { authenticator } from "~/server/auth.server";
 
export let loader = async ({ request, params }: LoaderArgs) => {
  const user = await authenticator.isAuthenticated(request, {
    successRedirect: "/dashboard",
  });
  return user;
};
 
export default function Index() {
  return (
    <div>
      <h1>Welcome!</h1>
      <p>
        <a href="/login">Please log in</a>
      </p>
    </div>
  );
}