Server-side OAuth utilities for implementing multiple OAuth providers.
To install this package
npm install @omer-x/oauth-kitimport { generateOAuthURL as loginWithAppleURL } from "@omer-x/oauth-kit/apple/client";
import { generateOAuthURL as loginWithGoogleURL } from "@omer-x/oauth-kit/google/client";
// process.env.GOOGLE_OAUTH_CLIENT_ID = your Google OAuth Client ID from Google Cloud Console
// publicOrigin = public origin of your app e.g. "https://myapp.com"
// callbackEndpoint = endpoint to handle the OAuth callback e.g. "/auth/google"
// locale = locale code e.g. "en", "fr", "de"
loginWithGoogleURL(process.env.GOOGLE_OAUTH_CLIENT_ID, publicOrigin, "/auth/google", locale);
loginWithAppleURL(process.env.APPLE_OAUTH_CLIENT_ID, publicOrigin, "/auth/apple", locale);import { createAccessToken } from "@omer-x/oauth-kit/apple/access-token";
import { decodeIdToken, signClientSecret } from "@omer-x/oauth-kit/apple/jwt";
import { parseOneTimeUserInfo } from "@omer-x/oauth-kit/apple/utils";
import { decodeState } from "@omer-x/oauth-kit/utils";
import { hasLocale } from "next-intl";
import { routing } from "~/i18n/routing";
export async function POST(request: Request) {
const [
formData,
publicOrigin, // public origin of your app e.g. "https://myapp.com"
] = await Promise.all([
request.formData(),
getPublicOrigin(request.headers), // implement this function to get the public origin from request headers
]);
const { pathname } = new URL(request.url);
const originURL = new URL(pathname, publicOrigin).toString();
const state = formData.get("state");
const code = formData.get("code");
const rawUserData = formData.get("user");
if (typeof code !== "string") throw new Error("Invalid code");
if (typeof state !== "string") throw new Error("Invalid state");
if (!process.env.APPLE_OAUTH_TEAM_ID) throw new Error("APPLE_OAUTH_TEAM_ID env is missing!");
if (!process.env.APPLE_OAUTH_CLIENT_ID) throw new Error("APPLE_OAUTH_CLIENT_ID env is missing!");
if (!process.env.APPLE_OAUTH_KEY_ID) throw new Error("APPLE_OAUTH_KEY_ID env is missing!");
if (!process.env.APPLE_OAUTH_PRIVATE_KEY) throw new Error("APPLE_OAUTH_PRIVATE_KEY env is missing!");
const { locale } = decodeState(state);
if (!hasLocale(routing.locales, locale)) throw new Error(`Unknown Locale (${locale})`);
const clientSecret = signClientSecret(
process.env.APPLE_OAUTH_TEAM_ID,
process.env.APPLE_OAUTH_CLIENT_ID,
process.env.APPLE_OAUTH_KEY_ID,
process.env.APPLE_OAUTH_PRIVATE_KEY,
);
const oauth = await createAccessToken(process.env.APPLE_OAUTH_CLIENT_ID, clientSecret, code, originURL);
const appleUser = decodeIdToken(oauth.id_token);
const appleUserInfo = parseOneTimeUserInfo(rawUserData); // Beware! they send this information only once, so use it wisely!
// apply your authentincation logic here, e.g. create or update user in your database
// then redirect the user to the app
}import { createAccessToken } from "@omer-x/oauth-kit/google/access-token";
import { getGoogleUser } from "@omer-x/oauth-kit/google/api";
import { fetchUserPicture } from "@omer-x/oauth-kit/google/utils";
import { decodeState } from "@omer-x/oauth-kit/utils";
import { hasLocale } from "next-intl";
import { routing } from "~/i18n/routing";
export async function GET(request: Request) {
const [
publicOrigin, // public origin of your app e.g. "https://myapp.com"
] = await Promise.all([
getPublicOrigin(request.headers), // implement this function to get the public origin from request headers
]);
const { searchParams, pathname } = new URL(request.url);
const originURL = new URL(pathname, publicOrigin).toString();
const code = searchParams.get("code");
const state = searchParams.get("state");
if (typeof code !== "string") throw new Error("Invalid code");
if (typeof state !== "string") throw new Error("Invalid state");
if (!process.env.GOOGLE_OAUTH_CLIENT_ID) throw new Error("GOOGLE_OAUTH_CLIENT_ID env is missing!");
if (!process.env.GOOGLE_OAUTH_CLIENT_SECRET) throw new Error("GOOGLE_OAUTH_CLIENT_SECRET env is missing!");
const { locale } = decodeState(state);
if (!hasLocale(routing.locales, locale)) throw new Error(`Unknown Locale (${locale})`);
const oauth = await createAccessToken(
process.env.GOOGLE_OAUTH_CLIENT_ID,
process.env.GOOGLE_OAUTH_CLIENT_SECRET,
code,
originURL,
);
const googleUser = await getGoogleUser(oauth.access_token);
// apply your authentincation logic here, e.g. create or update user in your database
// optional step: fetch user picture
const picture = await fetchUserPicture(googleUser.picture); // this is a File object, you can upload it to your storage service if you wish
// then redirect the user to the app
}This project is licensed under the MIT License. See the LICENSE file for details.