npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@boxyhq/remix-auth-sso

v1.1.1

Published

An SSO strategy for Remix Auth, based on the OAuth2Strategy

Downloads

16

Readme

BoxyHQSSOStrategy

Attention ⚠️: We have deprecated the earlier strategy BoxyHQSAMLStrategy (npm package: @boxyhq/remix-auth-saml). In case you are using that one please consider changing over to this strategy.

The BoxyHQSSOStrategy can be used to enable Single Sign-On (SSO) in your remix app. It extends the OAuth2Strategy.

Demo

Checkout the demo at https://github.com/boxyhq/jackson-remix-auth

Supported runtimes

| Runtime | Has Support | | ---------- | ----------- | | Node.js | ✅ | | Cloudflare | ✅ |

SAML Jackson Service

SAML Jackson implements SSO as an OAuth 2.0 flow, abstracting away all the complexities of the underlying SAML/OIDC protocol.

You can deploy SAML Jackson as a separate service. Check out the documentation for more details

Configuration

SSO login requires a connection for every tenant/product of yours. One common method is to use the domain for an email address to figure out which tenant they belong to. You can also use a unique tenant ID (string) from your backend for this, typically some kind of account or organization ID.

Check out the documentation for more details.

Usage

Install the strategy

npm install @boxyhq/remix-auth-sso

Create the strategy instance

// app/utils/auth.server.ts
import { Authenticator } from "remix-auth";
import {
  BoxyHQSSOStrategy,
  type BoxyHQSSOProfile,
} from "@boxyhq/remix-auth-sso";

// Create an instance of the authenticator, pass a generic with what your
// strategies will return and will be stored in the session
export const authenticator = new Authenticator<BoxyHQSSOProfile>(
  sessionStorage
);

auth.use(
  new BoxyHQSSOStrategy(
    {
      issuer: "http://localhost:5225", // point this to the hosted jackson service
      clientID: "dummy", // The dummy here is necessary if the tenant and product are set dynamically from the client side
      clientSecret: "dummy", // The dummy here is necessary if the tenant and product are set dynamically from the client side
      callbackURL: new URL(
        "/auth/sso/callback",
        process.env.BASE_URL
      ).toString(), // BASE_URL should point to the application URL
    },
    async ({ profile }) => {
      return profile;
    }
  )
);

Setup your routes

// app/routes/login.tsx
export default function Login() {
  return (
    <Form method="post" action="/auth/sso">
      {/* We will be using user email to identify the tenant*/}
      <label htmlFor="email">Email</label>
      <input
        id="email"
        type="email"
        name="email"
        placeholder="[email protected]"
        required
      />
      {/* Product can also be set dynamically, set to `demo` here */}
      <input type="text" name="product" hidden defaultValue="demo" />
      <button type="submit">Sign In with SSO</button>
    </Form>
  );
}
// app/routes/auth/sso.tsx
import { ActionFunction, json } from "remix";
import { auth } from "~/auth.server";
import invariant from "tiny-invariant";

type PostError = {
  email?: boolean;
  product?: boolean;
};
export const action: ActionFunction = async ({ request }) => {
  const formData = await request.formData();

  const email = formData.get("email");
  const product = await formData.get("product");

  const errors: PostError = {};
  if (!email) errors.email = true;
  if (!product) errors.product = true;

  if (Object.keys(errors).length) {
    return json(errors);
  }

  invariant(typeof email === "string");
  // Get the tenant from the domain
  const tenant = email.split("@")[1];
  return await auth.authenticate("boxyhq-sso", request, {
    successRedirect: "/private",
    failureRedirect: "/",
    context: {
      clientID: `tenant=${tenant}&product=${product}`,
      clientSecret: "dummy",
    },
  });
};
// app/routes/auth/sso/callback.tsx
import type { LoaderFunction } from "remix";
import { auth } from "~/auth.server";

export const loader: LoaderFunction = async ({ request, params }) => {
  return auth.authenticate("boxyhq-sso", request, {
    successRedirect: "/private",
    failureRedirect: "/",
  });
};