Skip to content

Server-side OAuth utilities for implementing multiple OAuth providers.

License

Notifications You must be signed in to change notification settings

omermecitoglu/oauth-kit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

oauth-kit

npm version npm downloads codecov License: MIT GitHub last commit GitHub issues GitHub stars

Table of Contents

Overview

Server-side OAuth utilities for implementing multiple OAuth providers.

Installation

To install this package

npm install @omer-x/oauth-kit

How to use

Provide a url to redirect users to the OAuth provider's authentication page

import { 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);

How to use get user information (Apple) with a Next.js API route

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
}

How to use get user information (Google) with a Next.js API route

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
}

License

This project is licensed under the MIT License. See the LICENSE file for details.

About

Server-side OAuth utilities for implementing multiple OAuth providers.

Topics

Resources

License

Stars

Watchers

Forks