Remix Auth SAML Strategy
remix-auth-saml provides a SAML 2.0 authentication strategy for Remix Auth, enabling single sign-on (SSO) integration in Remix applications. This library abstracts the complexities of SAML authentication flows, including service provider (SP) and identity provider (IdP) interactions, metadata exchange, and assertion processing. The current stable version is 1.2.0, with releases occurring periodically, primarily for dependency updates and minor fixes as seen in recent changelogs. Key differentiators include its direct integration with the Remix Auth ecosystem, providing a familiar API for developers already using `remix-auth`, and its explicit support for both Node.js and Cloudflare runtimes, making it versatile for various deployment targets.
Common errors
-
Error: Missing SAML validator. Please install a validator (e.g., @authenio/samlify-node-xmllint) and pass it into the strategy constructor.
cause The `validator` option was not provided or was null in the `SamlStrategy` constructor, which is a required dependency for SAML XML parsing and validation.fixInstall a SAML XML validator like `@authenio/samlify-node-xmllint` (`npm i @authenio/samlify-node-xmllint`) and pass it to the `SamlStrategy` options: `new SamlStrategy({ validator: require('@authenio/samlify-node-xmllint'), ... })`. -
TypeError: Cannot read properties of undefined (reading 'authenticate')
cause The `authenticator` instance from `remix-auth` was not correctly initialized or exported, or the SAML strategy was not registered with it using `authenticator.use(samlStrategy, 'saml')`.fixEnsure `authenticator` is correctly initialized with session storage and exported from `auth.server.ts`. Verify that `authenticator.use(samlStrategy, 'saml')` is called before attempting to use the 'saml' strategy.
Warnings
- gotcha SAML configuration requires precise matching between the Service Provider (your Remix app) and the Identity Provider (IdP). Small mismatches in `authURL`, `callbackURL`, certificate formats, or signing/encryption preferences can lead to authentication failures that are difficult to debug.
- gotcha A SAML XML validator is a mandatory dependency for `remix-auth-saml`, but it's not bundled. Forgetting to install one (e.g., `@authenio/samlify-node-xmllint`) will cause runtime errors when the strategy attempts to process SAML responses.
- gotcha When deploying to environments with different hostnames or port numbers, the `authURL`, `callbackURL`, and `idpMetadataURL` configured in `SamlStrategy` must reflect the actual public-facing URLs. Hardcoding `localhost` will lead to issues in production.
Install
-
npm install remix-auth-saml -
yarn add remix-auth-saml -
pnpm add remix-auth-saml
Imports
- SamlStrategy
const SamlStrategy = require('remix-auth-saml').SamlStrategy;import { SamlStrategy } from 'remix-auth-saml'; - metadata
import metadata from 'remix-auth-saml';
import { metadata } from 'remix-auth-saml'; - Authenticator
import { Authenticator } from 'remix-auth';
Quickstart
import { Authenticator } from "remix-auth";
import { sessionStorage } from "~/services/session.server"; // Assuming a session storage setup
import { SamlStrategy } from "remix-auth-saml";
import * as validator from "@authenio/samlify-node-xmllint"; // Or another SAML XML validator
// Create an Authenticator instance
export let authenticator = new Authenticator<any>(sessionStorage);
// Initialize the SAML strategy
let samlStrategy = new SamlStrategy(
{
validator,
authURL: "http://localhost:3000/auth/saml",
callbackURL: "http://localhost:3000/auth/saml/callback",
idpMetadataURL: "http://localhost:7000/metadata", // URL to your Identity Provider's metadata
spAuthnRequestSigned: false,
spWantAssertionSigned: false,
spWantMessageSigned: false,
spWantLogoutRequestSigned: false,
spWantLogoutResponseSigned: false,
spIsAssertionEncrypted: false,
// Optional: Specify private keys and certificates for signing/encryption
// privateKey: "./path/to/sp-private-key.pem",
// signingCert: "./path/to/sp-public-cert.pem"
},
async ({ extract, data }) => {
// This verify callback runs after successful SAML authentication
// 'extract' contains parsed user profile data from the SAML assertion
// 'data' is the raw IdP response, useful for backend verification or decryption
console.log("User profile extracted:", extract);
console.log("Raw IdP response data:", data);
// Here, you would typically find or create a user in your database
// based on 'extract' data and return the user object.
// Example: const user = await userService.findOrCreate(extract);
// return user;
// For this example, we'll just return a placeholder
return { id: extract.nameID, email: extract.attributes['urn:oid:0.9.2342.19200300.100.1.3'] };
}
);
// Register the strategy with the Authenticator
authenticator.use(samlStrategy, "saml");
// Export SP metadata for the IdP
export let spMetadata = samlStrategy.metadata();