Skip to main content

· 8 min read
Aswin V

We have already covered SAML at a high level from both user and application provider points of view.

In this post, we'll dive into the technicalities of SAML, OAuth 2.0 and OpenID Connect and how these come together to serve as building blocks for Jackson SSO.


SAML was designed for traditional web applications in the early 2000s. The goal was to provide a seamless user experience for applications by federating authentication to an IdP. As a result, applications no longer had to maintain identities for users. All they had to do was to redirect the browser to the IdP which would then authenticate the user and return an assertion about the logged-in user. This assertion in effect was a token, asserting to the app that the user authenticated at the IdP and the assertion is valid for the set period contained within it.

While SAML gave us a solution to the problem of SSO or federated identity, it does not address the issue of authorization.

The need for authorization arose with the dawn of Single Page Apps (SPA) and native platforms such as mobile. More and more logic started moving from backend to frontend and an ecosystem of apps that could talk to one another (via HTTP(S)) sprung up. For eg:- You could reserve movie tickets and send invitations to your Facebook friends. This meant that applications started acting on behalf of the end-user, requesting data (friend list) from other services (Facebook). One way we could solve it was by sharing our credentials (for services) with the app. Nothing could be more dangerous than this, because now the application can virtually do anything the user could do. This paved the path for standards like OAuth that provides us with a mechanism to grant controlled and limited access to resources on behalf of the user.

OAuth 2.0

The OAuth 2.0 Authorization framework enables a third-party application/client to obtain limited access to an HTTP service on behalf of the resource owner (or user). In the final step of this process, the client receives a short-lived access token that can be used to access the protected resources.

The flow starts with the app redirecting the user agent to an intermediary Authorization server (AS). The AS authenticates the user and obtains permission from the user to access resources. Once that's done, AS redirects back to the client with an Authorization code. The Authorization code is a grant or a credential representing the user's authorization to be used by the client. In the final step, the client uses this code to obtain an access token. This flow otherwise called Authorization Code grant is one of 4 grant types that are supported. For sake of simplicity, we can omit the others for now.

The above-mentioned flow offers a few benefits:

  • The user only authenticates with the authorization server and the credentials are never shared with the app.
  • The access token is not transmitted* via the user agent but directly to the client via an HTTP request.
  • The Client can be authenticated by the authorization server by using a client secret.

* It's worth mentioning the fact that another grant type 'implicit grant' does return an access token via the user agent in the redirect URL fragment

Using OAuth 2.0 for authentication

Since authentication usually occurs before issuing the access token, it is usually assumed that possession of an access token is proof that authentication happened. The access token is then used to query the Identity API to obtain user details.

However, this does not fully serve as proof of authentication and has several pitfalls:

  • The access token is opaque to the client and its intended audience is the protected resource server.
  • There is no way to know if the user is still around because information about the authentication event is not exposed.
  • In situations where clients get an access token directly in the return URL (implicit grant), there is a high chance that an attacker can inject their malicious token. This can be mitigated by using the Authorization code flow as the token is retrieved from the token endpoint directly.
  • OAuth does not define a standard set of fields for the Identity API. For eg:- While one IdP could use user_id for the user identifier, the same could be subject in another one. This requires different handling on the client side from one IdP to another.

A new standard called 'OpenID Connect' which builds on top of OAuth 2.0 brings new artifacts like ID tokens that can serve as reliable proof of authentication and also standardizes things like scope and claims.

OpenID Connect (OIDC)

OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It supports 3 flows of which Authorization code and implicit flow are similar to the ones defined in OAuth 2.0. The notable difference here is the return of an ID Token in JWT format (JSON Web Token). The claims in the ID Token help the client reliably confirm the identity of the user. The audience(aud) claim will be set to the client id which means the ID token is intended to be consumed by the client alone. Conforming to the OAuth 2.0 spec, an access token is still returned which can be used to obtain information about the user from the "userinfo" endpoint. OIDC also standardizes the claims in the ID Token as well as the "userinfo" response.

Assembling the SSO puzzle

Now that we have all the pieces of the SSO puzzle, bringing it together in Jackson would look something like the one below.

img alt

Allow me to explain.

We need to support two kinds of SSO Identity Providers - SAML and OIDC. For the sake of discussion, consider the scenario of two apps where one (CRM) needs to log in with Azure AD via SAML and another (HRM) needs to log in with Google Workspace via OIDC.

Setup SSO Connection

The preliminary step (marked by the green arrow above) is to add the SSO Connection to Jackson. For SAML IdP, this would mean saving the XML metadata from the IdP. The metadata would contain the SSO URL to send the SAML request to plus the public key to verify the SAML assertion signature. In the case of OIDC IdP, we need the discovery URL and client credentials (clientID and clientSecret of the registered app). The discovery URL can be used to query metadata about IdP such as authorization and token endpoints while the client credentials will be used to authenticate the Jackson client orchestrating the OIDC flow.

Login flow

Jackson supports both OAuth 2.0 as well OpenID flows. The OAuth 2.0 flow is made secure by supporting Authorization Code flow with PKCE. By including the scope openid in the client request Jackson will switch to OpenID flow.

The login process follows the below steps:

  1. The Client (Browser app) initiates the login by redirecting to Jackson's authorize endpoint. Jackson will parse the tenant/product in the request and use it to redirect the user to the configured IdP.
  2. Step 2 varies based on the Identity Provider type. For SAML IdP, Jackson would construct the SAML request, sign it and send it to IdP. The IdP validates the request and authenticates the user. For OIDC IdP, Jackson constructs an OpenID Connect request and redirects the user to the OIDC Provider authorization endpoint.
  3. Once the user is logged in successfully, the IdP redirects back to Jackson. For SAML, the response contains the user profile. In the case of OIDC, the response contains the authorization code that is used by Jackson to obtain the token and user profile from the OIDC IdP. Jackson generates a short-lived authorization code and stores the user profile against it.
  4. The authorization code generated in the previous step is sent to the client app.
  5. The client exchanges the code for the token and uses it to query the userInfo endpoint of Jackson to get the complete user profile. In the case of OpenID flow, ID Token is returned by Jackson and contains the basic user profile.

Final thoughts

So in a nutshell, Jackson acts as a proxy between the client app and the IdP doing the heavy lifting of orchestrating SAML/OIDC flows with the configured IdPs. This way you can quickly scale your app auth to any number of providers allowing you to focus on your core product.

· 3 min read
Kiran K

Enterprise-ready SaaS Starter Kit is a Next.js based SaaS Starter Kit that can save hundreds of development hours while building enterprise-ready SaaS apps.

Kickstart your enterprise app development with Next.js SaaS Starter Kit

Let's look at some of the enterprise-ready features the SaaS kit offers.


SAML stands for Security Assertion Markup Language. It is an XML-based open standard for transferring identity data between an identity provider (IdP) and a service provider (SP).

Single Sign On (SSO) allows your customers to manage their team's users outside your built-in user table.

SAML SSO is integrated with the help of SAML Jackson

Directory Sync (SCIM)

Directory sync helps organizations automate the provisioning and de-provisioning of their users.

As a result, it streamlines the user lifecycle management process by saving valuable organizational hours, creating a single truth source of the user identity data, and facilitating them to keep the data secure.

Directory Sync is integrated with the help of SAML Jackson

Webhooks & Events

Webhooks are a way for systems to notify external applications that a specific event has occurred in your SaaS app without receiving a request.

Webhooks are a great solution if the client does not know when an event will occur and wants to be notified in real-time.

Webhook is integrated with the help of Svix

Team Management

Teams describe the functionality that enables modern software to be coordinated and managed.

Through Teams, SaaS app users invite others to collaboratively use the application with them by creating an account.

Other Features

Let's also look at other standard features the SaaS kit offers.

  • Create account
  • Sign in with Email and Password
  • Sign in with Magic Link
  • Update account
  • Manage team
  • Manage team members
  • Invite users to the team
  • Accept invitation

Getting Started

Please follow these simple steps to get a local copy up and running.

1. Setup

Clone or fork this GitHub repository

git clone

2. Go to the project folder

cd saas-starter-kit

3. Install dependencies

npm install

4. Set up your .env file

Duplicate .env.example to .env.

cp .env.example .env

5. Set up database schema

npx prisma db push

6. Start the server

In a development environment:

npm run dev

7. Start the Prisma Studio

Prisma Studio is a visual editor for the data in your database.

npx prisma studio

Contributing guide

Contributions make the open-source community a fantastic place to learn, inspire, and create. Any contributions you make are greatly appreciated.

We also invite new supporters to contribute to the repository if you are interested.

· 4 min read
Kiran K

This article will walk you through everything you should know about SCIM and Directory Sync.

What is SCIM?

System for Cross-domain Identity Management (SCIM) is an open standard that allows for the automation of user provisioning (Directory Sync).

SCIM facilitates user identity data communication between Identity Providers (Okta, OneLogin, etc.) and Service Providers (Enterprise SaaS apps).

Why should you care about SCIM?

Many companies manually onboard and offboard users, which consumes many IT resources and time.

User lifecycle management (ULM) begins when employees start their job and continue until they leave the company. ULM is all about provisioning and de-provisioning users when they join an organization.

For IT departments, this means creating an account for the new employees in the cloud apps they need to use after starting their job. Also, IT departments must ensure that when those employees leave, they revoke access to those accounts.

Smaller organizations might address these procedures manually, but the process can become error-prone and time-consuming when done at scale. This is where the SCIM and Directory Sync come to the organization's rescue.

What is Directory Sync?

Directory sync helps organizations automate the provisioning and de-provisioning of their users.

As a result, it streamlines the user lifecycle management process by saving valuable organizational hours, creating a single truth source of the user identity data, and facilitating them to keep the data secure.

How does the Directory Sync work?

Directory sync allows programmatic access to the user identity data via a standard protocol (SCIM).

Directory sync implementation typically involves a client and a server. A client is an identity provider (IDP) with a directory of user identities. A service provider (SP) is an enterprise SaaS app that needs a subset of data from those identities.

When you make changes to the user identities, the changes are automatically synced to the SP according to the SCIM protocol. SP can now process these data according to the way they want.

Some common user identity changes include adding new users to the organization, updating existing users, removing users from the organization, adding users to groups, etc.

Technically, SCIM is a set of APIs that allows you to manipulate the users and group objects and expose these data as JSON through the REST endpoints.

How to add Directory Sync to your SaaS app?

Building Directory sync implementation yourself can be tedious and time-consuming for any engineering team.

Below are some questions the engineering team should answer before starting building Directory sync.

  • How do we support multiple identity providers?
  • How much effort should the team put into support & maintenance?
  • Do we have developers with good knowledge of SCIM and its security?
  • Is it worth building the Directory sync ourselves?

In short, building Directory sync yourself is not a good idea. It requires a lot of tedious engineering work and ongoing maintenance.

The best alternative is an open-source dedicated Directory Sync implementation provider like SAML Jackson from BoxyHQ.

Directory Sync from BoxyHQ

BoxyHQ can help enterprises to add Directory Sync to any SaaS app with just a few lines of code.

Enterprise SaaS apps can provide a Webhook endpoint to SAML Jackson, and Jackson will notify the Webhook every time a change occurs in the user identity data within the IDP.


In short, Jackson hides all the complexities involved with Directory Sync implementation and makes your integration easier.

BoxyHQ's Directory Sync implementation supports identity providers such as Okta, OneLogin, Azure AD, and JumpCloud. We're looking forward to adding more identity providers in future releases.

Here are a few critical aspects that make BoxyHQ's Directory Sync implementation stand out.

  • An open-source solution.
  • Allows you to keep control of your data.
  • Support multiple identity providers.
  • Allows you to listen to six critical SCIM events.

Final Thoughts

Directory Sync is a valuable investment for every organization seeking efficiency and security in their user lifecycle management system.

If you are interested in becoming enterprise-ready without the hassle, then let's chat! You can book a free consultation call and talk with our CEO about how we can help. So let's start the journey together.

· 3 min read
Sama - Carlos Samame

Let’s start with some facts to understand why it sucks!

On one hand:

  • Cybercrime went up 600% due to the COVID-19 Pandemic
  • Data breaches and cyber attacks in 2021 were 5.1 billion breached records, this is 11% more than in 2020
  • 79% of companies have experienced at least one cloud data breach in the past 18 months
  • Software supply chain attacks jumped over 300% in 2021
  • It is estimated that worldwide, cyber crimes will cost $10.5 trillion annually by 2025.

(Data from Purplesec, IT Governance, VentureBeat)

On the other hand:

  • 70% of development teams always or frequently skip security steps due to time pressures when completing projects
  • Almost 60% of devs are releasing code 2x faster, thanks to DevOps.
  • In 2021, only 20% of organizations have fully integrated security into the development
  • Security has low priority. 67% of developers surveyed by Secure Code Warrior admitted that they routinely left known vulnerabilities and exploits in their code
  • Github expects the number of software developers using its platform (56 million in 2020), to grow to 100 million developers in 2025

(Invicti Security, Gitlab, Github, VentureBeat)

Security vs Developers

Security teams focus on planning secure IT environments, but developers are asked to focus on productivity while they are also tasked with implementing these security plans. The main issue is that developers are often left out of security planning processes, creating a strained relationship between these two teams.

It is important to build a healthy relationship where trust, communication, and collaboration are key to moving toward the organization’s north star. But traditional security teams sometimes see themselves as inspectors of the developer's work. And that attitude needs to change - “when you’re a hammer, everything is a nail”.

Did you know that in “Gartner's Top Strategic Technology Trends for 2022: Cybersecurity Mesh”, the word "developer" is not included not even once? We were shocked about it; developers need to have a leading role in cybersecurity!

It’s “Shift Left Security” time!

With shift left security we mean moving security sooner in the development process. Teams should provide developers with the right tools to do their job securely; this is why it is essential to automate product security.

But most of the new security solutions are focused on selling to the CISOs and their security teams, maybe because they are the ones with the budget for “security”; but what about developers? Most of their new solutions are oriented toward productivity, which makes sense since we live in an agile world, but what if there were new developer-first security solutions? Well, it is about time; a recent survey from Forrester shows that last year 27% of organizations had their development teams holding the budget for application security tools and that number has increased to 37% this year.

Developer-first security Tools

While some security tools for developers have started to appear, it is still early days. The ecosystem needs solutions to automate security for developers and most importantly, that is reliable. Our hypothesis is that the most important products will come from the open-source community; they have a genuine interest in supporting and empowering developers.

We are consolidating a list of reliable open source developer-first security tools for security, if you know of a project we should consider, or if you would like to have access to this list, please send me an email: or/and help us spread the word! 🙌

Security risks everywhere

· 4 min read
Sama - Carlos Samame

If you are thinking about building features to be enterprise-ready, there are typically two paths that brought you here:

  1. Your team has initially focused on smaller customers and is now looking to expand, or
  2. Your team is building a new product and targeting enterprise customers from day 1

Either way, you need to be aware that selling to enterprises is super exciting, especially if you like to play golf and you are ok with a long sales cycle - it could easily take you up to three years to close a deal.

Enterprises can be scared to give startups a chance and startups often lose out to more established businesses. However, there are two great ways to make sure your business doesn't miss out:

  • List of other enterprise customers (“show me more logos, we are not a guinea pig”)
  • Compliance requirements (“a checklist to show my boss you are safe”)

Security risks everywhere

But what is enterprise readiness? From a product perspective, identified common features that set enterprise software apart. You can do a free self-assessment here. The basics mean that your business meets the standards that enterprises look for in solution providers.

Now, the good news is that to be enterprise-ready you don’t need to build these common undifferentiated features which can drain your resources and bank account. Here is why:

  1. Customer Obsession – You need to forget about product development and narrow your attention to customer development. You need to talk to potential enterprise customers and understand their current needs, pains, motivations, processes, etc. Remember that they’ve got plenty of software they already depend on that will need to work smoothly with yours. On top of learning how to navigate the enterprise, you need to identify Infosec barriers and consider how to mitigate them; if your solution needs to process internal data, things will be more complex.

  2. Time to market – Instead of spending months building in-house enterprise-grade features, there are off-the-shelf enterprise readiness solutions that you can integrate into your SaaS app with just a few lines of code. There is no need to wait months to build Single Sign-On (SSO), Directory Sync, Audit Logs, Privacy Vault, and other boring stuff that enterprises ask for anymore, now you could plug them within hours. And your team can spend more time building your core product instead of non-core features that won’t add value to your customers’ main needs.

  3. Cut engineering costs – Out-of-the-box solutions will help your company save developers time. If you consider the learning curve, coding, fixing bugs, and all the hassle that your tech team needs to go through, you will realize that people’s time is more expensive than developer tools. And the good news is that there are reliable open source solutions that you could use at no cost. Free and trustworthy? That’s the beauty of open source communities. Self-hosting these solutions will allow your company to maintain a level of control that will simplify things if you need to be certified (SOC2, ISO 27001, HIPAA, etc).

Here are 3 open-source solutions that could be interesting for you - BoxyHQ (disclaimer, I'm a Co-Founder here), Supertokens, and Oso. There are plenty of other solutions that are relevant, we are building a list and would love to learn about other projects you use, please share them with me.

Let’s be sincere, will your engineers focus on building the best SAML SSO feature or will they just focus on checking the box? Compliance security could be expensive in the long term when working with large enterprises. Especially if things go wrong because being compliant doesn’t mean your SaaS app is unhackable.

Remember that not all enterprises are the same. But working with a few design partners will help your team to define an efficient product roadmap, build a robust go-to-market strategy, and you will close more enterprise deals.

Deals, deals, deals!

If you know anyone that needs to build enterprise features we would love to hear from them and see how could we help, please feel free to share my email: - Thank you!

· 3 min read
Jay Singh

This article follows my first article in which I explain the basics of SAML from the users' side. If you haven't read that one already I would recommend reading that one first here. In this article, we are going to take a look at what SAML authentication and setup look like from the solution providers' perspective.

If you are a B2B solutions provider and you plan to have enterprise customers they will likely ask that your product supports SAML SSO. This is because the customer will already be using an IDP to manage user access and security to their services. Anything outside this will be a risk and not fit into their user's workflows.

Most larger solution providers have already invested a lot of time and money into building SAML integrations with IDP providers but this leaves smaller competitors with less time and resources at a disadvantage as they often haven't been able to prioritize enterprise security features over the core product build.

The main reason why smaller companies don’t implement SAML as part of the standard build is that it traditionally takes a long time as they have to build a custom integration with each IDP provider their customers use. Well, this is now an old issue because we have created BoxyHQ which allows you to connect to our free product with one single integration that then connects to all the IDPs for you! Let's take a look at what the integrations with and without BoxyHQ look like first.

Without BoxyHQ

In the diagram above we can see what it looks like when you build a custom SAML integration with each IDP. As you can see for each IDP you have to connect all the instances of your product and build a unique integration. This can take months and take the focus away from your team building your core product. We believe that enterprise readiness should be accessible and easy for businesses of all sizes so we built BoxyHQ. Let's see what that looks like.

With BoxyHQ

As you can see from the image above with BoxyHQ you only have to connect your product with a straightforward integration to BoxyHQ and then we manage and connect you to all the IDPs! It is that simple and you can deploy SAML SSO for your clients in as little as 8 days. We are also open source and free so you don't need to worry about big maintenance bills, we will even offer you custom support during the integration.

If you are interested in becoming enterprise-ready without the hassle then let's chat! You can book a free consultation call and chat with our CEO about how we can help. Let's start the journey together.

· 5 min read
Jay Singh

I have always worked in tech, so have always needed to understand the technical nature of the products we are building. This process has always been over-complicated for me so I now always try to write a guide for non-technical people like me. It turns out that once you understand it you can explain it to other non-technical people much easier! So here we go as I try to explain SAML (Security Assertion Markup Language) SSO (single sign-on) and why BoxyHQ makes it so easy to implement. Firstly you have probably heard of not only SAML but OAuth 2.0 and OIDC, these are all protocols that achieve the same result of providing SSO. There are a few nuances but those are out of scope for this article to keep things simple.

Let's start with what SAML SSO is and what it does. An example of SAML SSO in action would be a user in your company signs into a single dashboard and inside that dashboard, they have all the icons for the external services they use such as their CRM (Hubspot) and accounting software (Xero). The user can now just log in to any of their services by clicking on them rather than logging into each one individually.

But how does this work? Well, the idea behind SAML SSO is that by centralizing your access to an external system you can better manage access and permission as well as improve security. So in our example, the dashboard that allowed the user to just click an icon and log in was SAML in action. Because the company has connected to its external servicing using SAML it can now let its users access all the services from a single point. This single point of access is known as the IdP (Identity Provider) which authenticates the access to all the other services via SAML.

The diagrams below show how this access flow would work with and without SAML: Without SAML SSO

In the diagram above we can see that the company is not using SAML so the user has to log into each of the services with an individual username and password. The username and password are managed by the service provider and access is also managed via an admin user on the service provider's side. The user must be given access to each of the services from each of the services and remember the login details for each one.


In the image above we can see that the company is using an IdP such as Okta so the user simply has to log in once and then can access all the external services from a single dashboard. This also means that the company admins can manage access to the different services as they control the access directly from their IdP.

Now, remember that this is just a high-level overview of SAML and the technical aspects behind the scenes can get a lot more complicated.

We have been looking at SAML from a company user's perspective but it's also important to remember that these service providers also have to build a SAML integration to enable them to connect to their clients’ IdPs. This can be a very long and time-consuming process for service providers and this is where BoxyHQ comes in. Instead of service providers building a custom integration for each IdP their customers use which can take months, the service providers can use BoxyHQ and have all the connections to IdPs they need with a single integration! You can be SAML-ready in as little as 8 days! To understand how this looks check out my other blog here.

So what are the main benefits of SAML? Here are three of the most important ones I have identified.

Increased Security

SAML is at its heart a security standard and as it provides a single point of authentication that takes place in a secure environment it adds an extra layer of security to your service that most enterprise customers will ask for.

Improved user experience

As a user using SAML is very simple and pleasant to use as you only have to log in once and then you can access all your external services on a dashboard with a single click. This saves the user time and makes their overall experience of your product better.

Reduces cost

Without SAML you have to maintain account information across multiple services but when you use SAML this is all managed by the IdP.

BoxyHQ is open source and our SAML SSO product, SAML Jackson is just the first product we have built to help companies become enterprise-ready. If you are interested in discussing your authentication strategy or deploying SAML SSO you can book a call with our CEO here to discuss how we can support you.

I hope you have found this high-level explanation of SAML and its use cases helpful. If you have any questions please don't hesitate to reach out to us on our live chat on our website

· 9 min read
Kiran K

In this article, you'll learn how add SAML SSO login to an Express.js app. You'll use SAML Jackson with Auth0 to authenticate users and protect routes.

You can also access the full code at the GitHub repository.

Let’s get started!


To follow along with this article, you’ll need the following:

  • Node.js installed on your computer
  • Basic knowledge about Node.js and Express.js

Setting up the database

For our article, we’ll create a free Postgres database on Heroku instead of setting up a local Postgres server.

  • Go to Heroku signup page, then create an account.
  • Go to Apps and click Create new app.
  • Give your app a name, and click the Create app button.
  • Go to the Resources tab.
  • Choose the Heroku Postgres from the Add-ons search box, and click Submit Order Form.
  • Click the Heroku Postgres and select Settings tab.
  • Click the View Credentials button and copy URI.

Now you have created a free PostgreSQL database and copied the database connection URI. We'll need the connection URI later.

Configure the Identity Provider

We'll use the Auth0 as our identity provider. An Identity Provider (IdP) is a service that manage user accounts for your app.

  • First, go to the Auth0 signup page, then create an account.
  • Go to Dashboard > Applications > Applications.
  • Click the Create Application button.
  • Give your new application a name.
  • Choose Regular Web Applications as an application type and the click Create.
  • Go to the app you created, then click the Addons tab.
  • In the SAML2 Web App box, click the slider to enable the Addon.
  • Go to the Usage tab and download the Identity Provider Metadata.
  • Go to the Settings tab and make below changes.
  • Add http://localhost:3000/sso/acs as your Application Callback URL that receives the SAML response.
  • Paste the following JSON for Settings, then click Enable button.
"audience": "",
"mappings": {
"id": "",
"email": "",
"firstName": "",
"lastName": ""

audience is just an identifier to validate the SAML audience. More info.

Auth0 provides database connections to authenticate users with an email/username and password. These credentials are securely stored in the Auth0 user store.

Let's create one so that our users can register or login.

Now we've everything ready, let's move to the next step.

Getting started

Launch a terminal and clone the GitHub repo:

git clone
cd express-saml

Now, install the dependencies:

npm install

Add the environment variables:

cp .env.example .env

Update the DATABASE_URL variable with your Heroku Postgres database connection URI.

Append ?sslmode=no-verify to your database connection URI otherwise Heroku won't allow you to link to the database. This is a Heroku specific configuration.

For example postgres://

About the Express app

This is a simple express.js app created using express-generator. You can use any express.js app if you want.

Our express.js app has only 2 routes.

  • GET / render a home page
  • GET /dashboard render a dashboard

So, what's the plan? We'll add SAML SSO login (via Auth0) to our express.js app so that only authenticated users can access the /dashboard.

Install SAML Jackson

Run the following command to install the latest version of the SAML Jackson.

npm i --save @boxyhq/saml-jackson

Once you installed Jackson, let's initialize it.

Add the following code to the routes/index.js.

// routes/index.js


let apiController;
let oauthController;

const jacksonOptions = {
externalUrl: process.env.APP_URL,
samlAudience: process.env.SAML_AUDIENCE,
samlPath: '/sso/acs',
db: {
engine: 'sql',
type: 'postgres',
url: process.env.DATABASE_URL,

(async function init() {
const jackson = await require('@boxyhq/saml-jackson').controllers(jacksonOptions);

apiController = jackson.apiController;
oauthController = jackson.oauthController;

Setting up Express.js routes

Add SAML Metadata

The first route you'll create is the GET /config one. This route will display a form with following fields:

  • Metadata: Enter the XML Metadata content you've downloaded from IdP.
  • Tenant: Jackson supports a multi-tenant architecture, this is a unique identifier you set from your side that relates back to your customer's tenant. This is normally an email, domain, an account id, or user-id.
  • Product: Jackson support multiple products, this is a unique identifier you set from your side that relates back to the product your customer is using.
// routes/index.js

router.get('/config', async (req, res) => {

Add a view to display the form.

<!-- views/config.ejs -->

<!DOCTYPE html>
<title>SAML Config</title>
<link rel="stylesheet" href="/stylesheets/style.css" />
<h1>SAML Config</h1>
<p>Add SAML Metadata.</p>
<form action="/config" method="POST">
<div class="form-group">
<label for="tenant">Tenant</label>
class="form-control col-md-6"
<div class="form-group">
<label for="product">Product</label>
class="form-control col-md-6"
<div class="form-group">
<label for="rawMetadata">Metadata (Raw XML)</label>
class="form-control col-md-6"
<button type="submit" class="btn btn-primary">Submit</button>

Now let's add another route POST /config that will store the form data by calling the SAML Jackson config API.

This step is the equivalent of setting an OAuth 2.0 app and generating a client ID and client secret that will be used in the login flow.

// routes/index.js'/config', async (req, res, next) => {
const { rawMetadata, tenant, product } = req.body;

const defaultRedirectUrl = 'http://localhost:3000/sso/callback';
const redirectUrl = '["http://localhost:3000/*"]';

try {
await apiController.config({

} catch (err) {

There are a few important things to note in the code above.

defaultRedirectUrl holds the redirect URL to use in the IdP login flow. Jackson will call this URL after completing an IdP login flow.

redirectUrl holds an array containing a list of allowed redirect URLs. Jackson will disallow any redirects that are not on this list.

Next, let's start the express app. The app starts a server and listens on port 3000 (by default) for connections.

npm start

Now, let's visit http://localhost:3000/config, you should see the page with a form.

SAML Config

Here you can add the metadata you've downloaded from Auth0. Fill out the form with a Tenant, Product, and paste the metadata XML content as it is.

I'll use '' for tenant and 'crm' for product.

The response returns a JSON with client_id and client_secret that can be stored against your tenant and product for a more secure OAuth 2.0 flow.

If you do not want to store the client_id and client_secret you can alternatively use client_id=tenant=<tenantID>&product=<productID> and any arbitrary value for client_secret when setting up the OAuth 2.0 flow.

Redirect the users to IdP

Now you have added the SAML metadata, you'll need a route to redirect the users to IdP to start the SAML authentication.

Let's add a new route GET /sso/authorize.

Don't forget to change the values of the tenant and product in the code.

// routes/index.js

router.get('/sso/authorize', async (req, res, next) => {
try {
const tenant = '';
const product = 'crm';

const body = {
response_type: 'code',
client_id: `tenant=${tenant}&product=${product}`,
redirect_uri: 'http://localhost:3000/sso/callback',
state: 'a-random-state-value',

const { redirect_url } = await oauthController.authorize(body);

} catch (err) {

oauthController.authorize() will returns a redirect_url. You should redirect the users to this redirect_url to start the IdP authentication flow.

Handle the SAML Response from IdP

This route becomes the Assertion Consumer Service (ACS) URL of your app. The ACS URL tells your IdP where to POST its SAML Response after authenticating a user.

The SAML Response contains 2 fields: SAMLResponse and RelayState.

// routes/index.js'/sso/acs', async (req, res, next) => {
try {
const { SAMLResponse, RelayState } = req.body;

const body = {

const { redirect_url } = await oauthController.samlResponse(body);

} catch (err) {

Call to the method oauthController.samlResponse() will returns a redirect_url. You should redirect the users to this redirect_url. The query parameters will include the code and state parameters.

Code exchange

Now exchange the code for a token. The token is required to access the user profile.

Let's create a new route GET /sso/callback to handle the callback.

// routes/index.js

router.get('/sso/callback', async (req, res, next) => {
const { code } = req.query;

const tenant = '';
const product = 'crm';

const body = {
client_id: `tenant=${tenant}&product=${product}`,
client_secret: 'client_secret',

try {
// Get the access token
const { access_token } = await oauthController.token(body);

// Get the user information
const profile = await oauthController.userInfo(access_token);

// Add the profile to the express session
req.session.profile = profile;

} catch (err) {

In the above code, replace the value for tenant and product with yours.

Protect the dashboard

Now is the time to fix our GET /dashboard route so that only authenticated users can access it.

Let's fix it by adding a condition to check if the profile exists in the session.

If profile is undefined, redirect the users back to the / otherwise display the profile on the dashboard.

Replace the GET /dashboard route with the below code.

// routes/index.js

router.get('/dashboard', function (req, res, next) {
const { profile } = req.session;

if (profile === undefined) {
return res.redirect('/');

// Pass the profile to the view
res.render('dashboard', {

Replace the views/dashboard.ejs view with the below code.

<!-- views/dashboard.ejs -->

<!DOCTYPE html>
<link rel="stylesheet" href="/stylesheets/style.css" />
<p>Only authenticated users should access this page.</p>

<p>Id - <%= %></p>
<p>Email - <%= %></p>

From the command line, let's restart the express app then visit the authorize the URL http://localhost:3000/sso/authorize.

If you've configured everything okay, it should redirect you to the Auth0 authentication page, then click on the Sign up link and register there

If the authentication is successful, the app will redirect you to the dashboard and display the id, email of the user.



Congratulations, you should now have a functioning SAML SSO integrated with your express.js app using the SAML Jackson and Auth0.


To learn more about SAML Jackson, take a look at the following resources:

Your feedback and contributions are welcome!

· 3 min read
Utkarsh Mehta

One of our products, Hermes is an audit logs service. Currently, Hermes is in the prototype phase and uses a Go REST API server to ingest audit logs and send them to Loki.

We were trying out different databases, ingesters & tools to see which are best suited for Hermes and should be able to scale with high traffic without losing a single audit log & which can search through high amount data efficiently.

Title Image

We decided to benchmark different combinations of ingesters (Vector, Fluentd, Fluent-Bit, etc.) and storage & query tools (Mongodb, Clickhouse, Elasticsearch, etc.).

The first round of benchmarks will be lightweight and extensive benchmarks will follow later once we pick the right tools for Hermes.

Hardware Configuration

The following tests and benchmarks have been performed on a MacBook Pro (14-inch, 2021) with Apple M1 Pro and 16 GB RAM, the tools to be tested were dockerized with docker desktop running with 4 GB Memory, 4 CPUs & 1 GB Swap.

Fluent Bit is a super-fast, lightweight, highly scalable logging and metrics processor and forwarder. It is the preferred choice for cloud and containerized environments. Source: fluent-bit website Clickhouse is the fastest OLAP database on earth. ClickHouse works 100–1000x faster than traditional approaches. Companies like Uber, Cloudflare, Spotify, and eBay use Clickhouse. Source: Clickhouse website

So few pointers before we go ahead,

  1. Fluent-bit is fast at ingesting logs/data, processing them, and sending them to a destination.

  2. Clickhouse is efficient at handling and querying data.

  3. Fluent-bit does not support Clickhouse by default.

  4. The fluent-bit ecosystem lets users write their plugins in Golang and add additional support required.

  5. For faster querying in Clickhouse, an efficient table schema with indexes, compression, etc. should be established.

Clickhouse plugin for fluent-bit

I developed a fluent-bit output plugin for Clickhouse.

Fluent-Bit config

Fluent-bit Configuration

This config makes fluent-bit ingest data via HTTP server listening on port 8888 and sends the data to Clickhouse with configuration stated.

Clickhouse config

I ramped up the number of concurrent requests/queries by modifying the config.xml. After multiple tests, I finalized the following config.

Clickhouse Configuration

Load testing tool

I developed a load testing tool with Node.js that can be used to benchmark REST API-based endpoints of Fluent-bit.

API Benchmarking

Another tool to load test is the querying part of Clickhouse.

Clickhouse Load Testing

The results

These results are dependent on the ram allocated to the Docker engine, in my case, it's(4 GiBs).


Ingester results


Queryer result



  1. Fluent-bit can handle loads up to 2000 req/sec but in the case of bigger batches, the speed goes down drastically. (200 X 10) & (300 X 10)

  2. In the case of long-term light batches, Fluent-bit performs consistently. (10 X 1000)

  3. Fluent-bit performs at average speeds in the case of average loads (50 X 50).


  1. Clickhouse shows the best req/sec performance with an average load (50 X 50).

  2. Also, Clickhouse's performance was pretty satisfactory for all the different variations of records in DB. (1.1 mils, 50k, 25k, 10k, 2k & 1k).

  3. Clickhouse was able to manage short-term high loads and long-term light loads efficiently. (100 X 10) and (10 X 5000).

We will be posting more blogs regarding benchmarks, tools, etc., as we go on to build Hermes and many other dev tools. Please leave comments below.

Thank you!

· 7 min read
Sama - Carlos Samame

You have decided to quit your job and start something on your own, congratulations! Welcome to a new way of living, as our little green friend told us some years ago “do or do not, there is no try”. Resilience and perseverance will be your two new best friends now; we all know that starting a company is not hard at all, but something hard at the beginning of the journey is finding product-market fit, especially if you are selling to enterprises (if you are an open-source founder, make sure you prioritize project-community fit first).

Star Wars Lego

Photo by Mulyadi on Unsplash

Having worked for companies like Amazon Web Services & O2-Telefónica connecting enterprises with startups around the world, there are some best practices that I would like to share. We just have to remember that enterprises are conformed by groups of people, and every person is different. So please, don’t expect the secret sauce or the “right way” to do it. Even though each case will be unique, always look for the patterns of what works best for your company. I like to use the process DIA (Discover – Imagine – Act) to overcome challenges, so let me take you through it.


First, you have to understand the problem that you are solving. Is it really a problem or are you just in love with a good idea? Asking many times “why” will help you understand the hidden problem (the real one), and it will allow you to understand the needs that the enterprise has. Once you understand the needs of the enterprise, it is time to focus on understanding the needs of your user and your buyer, most of the time these are two different stakeholders within the organization. Is the need of the user a priority for the buyer, or is it just a distraction? You will see that in some organizations they are aligned and in others, they cannot even stand each other; so you must take the time to understand the dynamics between these stakeholders, and the culture of the enterprise itself (how they make decisions).

Sales cycles are indeed long if you look at them from a startup’s point of view. Remember that this is the standard speed for enterprises. Startups speak AGILE and Enterprises speak SECURITY, and for many people, these two terms can’t go together (don’t worry, we are proving them wrong @BoxyHQ). Enterprises have got plenty of software they already depend on that needs to work with whatever your product can do for them. Their technology is usually old, I have seen many enterprises with Frankensteins, they think they need to create a third leg to run faster and they end up building unnecessary technologies that affect the quality and the speed of their solutions. You need to focus on the cost of the enterprise (time and resources) to integrate your solution, and to do that you have to make sure that the impact is big enough to be worth it.

To make sure the impact you are generating is relevant to the enterprises focus on a few potential customers, as Jason Lemkin mentions “Almost all big companies now have innovation departments of some sort, as do many divisions and groups. The general idea is to bring in 1–2 new vendors a year that don’t risk taking the core business down but could have a material impact on the bottom line. If you truly can change the way they do business, you can often get a meeting. I’ve done this in both my start-ups in the earliest days with 10+ F500 companies in the first 90 days.”

This Discovery stage is also perfect to understand what your solution needs to have to be compliant; security is key for them. Startups that are not compliant with the enterprises’ requirements could delay the sales cycle, or what is worse they could lose the deal.


With all the information that you now have, it is time to visualize the future. Does your solution need some changes? Do you need new features to be compliant? Or could it be that maybe the enterprise doesn’t need all the features that you had in mind? Take some time to readjust your product as necessary, including how you are going to package it and how you are going to distribute it. Apply all the insights collected in the Discovery stage to test, measure, and iterate.

A common error that I have seen from startups is not focusing on selecting the right partners, and just moving forward with inbound opportunities. Some of them could be good but overall is a distraction to say yes to anyone that wants to resell your solution, you need to plan ahead.

Talking about planning, once you know who your internal sponsor is you need to facilitate the job for them. That is the person that will take your fights internally, so make sure you are giving them the right tools. If they see two concerns about integrating your solution, you should think of additional concerns and imagine how to mitigate each of them. You need to train your sponsor for unexpected scenarios that the decision committee will bring. Usually, enterprises ask for a “request for proposal” (RFP), the more you know about it, the better you will be prepared.

As an imagination exercise, I love Amazon’s Working Backwards process and the PRFAQ - you can learn more about it here. It is helpful to visualize the impact you aim to have and work backwards from your customer needs to create a solution. It is similar to the Design Thinking process, but the PRFAQ adds the manifestation piece.


Now is the time to act! But be careful, another mistake that many startups make is not executing at the right time, they spend too much time thinking (doing research) or they reach out to enterprises before making sure they are ready, burning your bridges. Timing is going to be key for you.

They need to trust you and your solution, every contact point is an opportunity for them to trust you, so make sure to go to these meetings well prepared, doing the right questions but at the same time with some insights on the market, their competitors, technologies, etc. You should be an expert in your niche but at the same time, you should be smart enough to listen. The more you know about them, the better you can adapt your solution and at the same time influence them.

Make sure you have the right metrics for your success cases, it doesn’t matter if you were selling to SMEs before or if you already had a few Proof of Concepts (POCs) with enterprises. Large companies don’t want to feel they are a guinea pig, if you did a POC and you didn’t move forward afterward most executives will not see it as unsuccessful, period.

Be patient, agile enterprises could spend between 6 to 12 months in conversations before signing an agreement, but many could take years (I’ve seen one company spending 3+ years). While you are waiting, make sure you are at the top of their mind, always adding value, not asking for unnecessary coffees. Key people will resign, will get fired, will change roles, so make sure you find a way to navigate these transitions, you don’t want to start from scratch.

Each enterprise is a different world, and there are more things you will find out while spending time with them, but I hope you find this blog post insightful. If you have any comments or questions you would like to discuss, please feel free to reach out. We have free Enterprise-Ready office hours to help startups be compliant and accelerate their sales cycle with enterprises.