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
Runtime | Has 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
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
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);
};
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",
});
};
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"
/>
</>
);
}
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
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.
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>
);
}