Skip to main content

NPM Library

SAML Jackson is available as an npm package that can be integrated into any Node.js based web application framework.

Install the SDK using the command below.

npm install @boxyhq/saml-jackson

Configuration Options

Please note that the initialization of @boxyhq/saml-jackson is async, you cannot run it at the top level.

import jackson, {
type IConnectionAPIController,
type IOAuthController,
} from "@boxyhq/saml-jackson";


let oauth: IOAuthController;
let connection: IConnectionAPIController;

(async function init() {
const jackson = await require('@boxyhq/saml-jackson').controllers({
externalUrl: "https://your-app.com",
samlAudience: "https://saml.boxyhq.com",
oidcPath: "/api/oauth/oidc",
samlPath: "/api/oauth/saml"
db: {
engine: "sql",
type: "postgres",
url: "postgres://postgres:postgres@localhost:5432/postgres",
},
});

oauth = jackson.oauthController;
connection = jackson.connectionAPIController;
})();

Single Sign-On Connections

Create SAML Connection

Create a new SAML Single Sign-On connection.

await connection.createSAMLConnection({
tenant: 'boxyhq',
product: 'your-app',
rawMetadata: '<raw-saml-metadata>', // Visit https://mocksaml.com to download Metadata
redirectUrl: ['https://your-app.com/*'],
defaultRedirectUrl: 'https://your-app.com/sso/callback',
});

Update SAML Connection

Update a SAML Single Sign-On connection.

await connection.updateSAMLConnection({
tenant: 'boxyhq',
product: 'your-app',
rawMetadata: '<raw-saml-metadata>',
redirectUrl: ['https://your-app.com/*'],
defaultRedirectUrl: 'https://your-app.com/sso/callback-updated',
clientID: 'f7c909a5c72a5535847acf32558b2429a5172dd6',
clientSecret: 'cc6ba07bc42c2f449c9b0a3cc41c256dea08f705e1b44fdc',
});

Create OIDC Connection

Create a new OIDC Single Sign-On connection.

await connection.createOIDCConnection({
tenant: 'boxyhq',
product: 'your-app',
redirectUrl: ['https://your-app.com/*'],
defaultRedirectUrl: 'https://your-app.com/sso/callback',
oidcDiscoveryUrl:
'https://accounts.google.com/.well-known/openid-configuration',
oidcClientId: '<OpenID Client ID>',
oidcClientSecret: '<OpenID Client Secret>',
});

Update OIDC Connection

Update an OIDC Single Sign-On connection.

await connection.updateOIDCConnection({
tenant: 'boxyhq',
product: 'your-app',
redirectUrl: ['https://your-app.com/*'],
defaultRedirectUrl: 'https://your-app.com/sso/callback',
oidcDiscoveryUrl:
'https://accounts.google.com/.well-known/openid-configuration',
oidcClientId: '<OpenID Client ID>',
oidcClientSecret: '<OpenID Client Secret>',
clientID: '749f95c4bd02b4adb6c0633249e70d5ad45b75e2',
clientSecret: '2d730ac71c74e7d49dccf362c9a61005b6246cc65d6d0fa4',
});

Get SAML/OIDC Connections

Get the details of an existing SAML or OIDC Single Sign-On connection.

// Using tenant and product
await connection.getConnections({
tenant: 'boxyhq',
product: 'your-app',
});

// Using the client ID
await connection.getConnections({
clientID: 'f7c909a5c72a5535847acf32558b2429a5172dd6',
});

Delete SAML/OIDC Connection

Update a SAML or OIDC Single Sign-On connection.

// Using tenant and product
await connection.deleteConnections({
tenant: 'boxyhq',
product: 'your-ap',
});

// Using client ID and client secret
await connection.deleteConnections({
clientID: 'f7c909a5c72a5535847acf32558b2429a5172dd6',
clientSecret: 'cc6ba07bc42c2f449c9b0a3cc41c256dea08f705e1b44fdcp',
});

Single Sign-On Authentication

Handle OAuth 2.0 (or OIDC) Authorization request

To initiate the flow, the application must trigger an OAuth 2.0 (or OIDC) redirect to the authorization endpoint of your app. You'll use the authorize method within the authorization handler.

authorize will resolve the SSO URL (redirect_url) based on the connection configured for the tenant/product. The app needs to redirect the user to this URL. Keep in mind that the SSO URL structure is different based on the type of SSO Connection. For a SAML Connection, this will contain the SAMLRequest whereas for an OIDC Connection the SSO URL will be the Authorization endpoint with the OIDC request params (scope, response_type, etc.) attached.

await oauth.authorize({
tenant: "boxyhq",
product: "your-app",
redirect_uri: "https://your-app.com/sso/callback",
state: "c38ee339-6b82-43d3-838f-4036820acce9",
response_type: 'code';
code_challenge: string;
code_challenge_method: 'plain' | 'S256' | '';
scope?: string;
nonce?: string;
idp_hint?: string;
prompt?: string;
});

Handle IdP Response

The response is sent back to your app after authentication at IdP. After the handling of this response, the profile of the authenticated user is extracted and stored against a short-lived code that is then sent back to the app. To handle the response use the appropriate method as detailed below:

SAML Response

Handle the response from the SAML Identity Provider. After successful authentication, IdP sends back (via browser POST) the SAMLResponse and RelayState to the Assertion Consumer Service (ACS) URL (samlPath) of the app. You'll use the samlResponse method within your ACS endpoint. This will parse and validate the SAML Response after which the user profile is extracted.

await oauth.samlResponse({
SAMLResponse: '...',
RelayState: '...',
});

OIDC Response

Handle the response from the OIDC Identity Provider. After successful authentication, IdP sends back (via browser redirect) the code and state to the redirect URL (oidcPath) that handles the OIDC response. You'll use the oidcAuthzResponse method within your oidcPath handler. This will exchange the code for tokenSet (id_token and access_token) from the OIDC Provider. The "userinfo" endpoint of the OIDC Provider also gets invoked. Both the id_token claims and userinfo response are used to form the user profile.

await oauth.oidcAuthzResponse({
code: '...',
state: '...',
});

Request Access Token

Requests an access_token by passing the authorization code from the previous step along with other authentication details.

const tenant = 'boxyhq';
const product = 'your-app';

await oauth.token({
code: '5db7257fde94e062f6243572e31818d6e64c3097',
redirect_uri: 'https://your-app.com/sso/callback',
client_id: `tenant=${tenant}&product=${product}`,
client_secret: 'dummy',
grant_type: 'authorization_code',
});

Fetch User Profile

Once the access_token has been fetched, you can use it to retrieve the user profile from the Identity Provider.

const accessToken = '6b81f03b60c34e46e740d96c7e6242923736a2d1';

await oauth.userInfo(accessToken);