How to Add SSO to Your App in 10 Minutes
A step-by-step guide to integrating Single Sign-On into your application using SAML or OAuth, with code examples and TitaniumVault's free tier.
Single Sign-On (SSO) lets your users authenticate once and access multiple applications without logging in again. It is the standard for enterprise software, and your customers will ask for it. The good news is that with TitaniumVault, you can add SSO to your application in about ten minutes. This guide walks you through every step, from creating your account to testing a working login flow.
Prerequisites
Before you start, make sure you have the following ready:
- A web application with a backend that can handle HTTP redirects (Node.js, Python, Ruby, Go, Rust, or any other server-side language)
- HTTPS enabled on your application, even in development (SSO protocols require secure connections)
- A basic understanding of how cookies or JWT tokens work for session management
- About ten minutes of uninterrupted time
You do not need prior experience with SAML or OAuth. This guide covers both protocols from scratch and explains when to choose each one.
Step 1: Create Your TitaniumVault Account
Head to titanium-vault.com/register and sign up for a free account. The free tier includes SSO support for up to 50 users, which is more than enough for development and testing. No credit card is required.
Once you have verified your email, log into the TitaniumVault dashboard. You will land on the organization overview page. Take note of your Organization ID and API base URL—you will need both in a moment.
Organization ID: org_a1b2c3d4e5
API Base URL: https://api.titanium-vault.com
Step 2: Configure Your Application
In the TitaniumVault dashboard, navigate to Applications and click Create Application. Fill in the following fields:
- Application Name: A human-readable name your users will see on the login screen (e.g., “Acme Dashboard”)
- Application URL: The root URL of your app (e.g.,
https://app.acme.com) - Callback URL: The endpoint in your app that will receive the authentication response (e.g.,
https://app.acme.com/auth/callback) - Logout URL: Where users should be redirected after signing out (e.g.,
https://app.acme.com/login)
After saving, TitaniumVault generates a Client ID and Client Secret for OAuth, or an IdP Metadata URL for SAML. Keep these credentials safe. Never expose your Client Secret in frontend code or commit it to version control.
Step 3: Choose Your Protocol — SAML vs OAuth
TitaniumVault supports both SAML 2.0 and OAuth 2.0 / OpenID Connect. The right choice depends on your use case:
| Criteria | SAML 2.0 | OAuth 2.0 / OIDC |
|---|---|---|
| Best for | Enterprise web apps, legacy systems | Modern web and mobile apps, APIs |
| Token format | XML-based assertions | JSON Web Tokens (JWT) |
| Complexity | Higher (XML parsing, certificate management) | Lower (JSON, simple HTTP flows) |
| Mobile support | Limited | Excellent |
| Enterprise adoption | Very high (Active Directory, Okta, etc.) | Growing rapidly |
If you are building a modern web application and want the simplest integration path, go with OAuth 2.0 / OpenID Connect. If your enterprise customers specifically require SAML (which is common in healthcare, finance, and government), choose SAML. TitaniumVault supports both, so you can always add the other protocol later.
Step 4: Integrate SSO into Your Application
Now for the actual code. Below are working examples for both protocols. Pick the one that matches your choice from Step 3.
Option A: OAuth 2.0 / OpenID Connect
The OAuth flow works in three stages: redirect the user to TitaniumVault, receive an authorization code at your callback URL, and exchange that code for user information.
1. Redirect the user to the TitaniumVault authorization endpoint:
// Generate a random state parameter to prevent CSRF attacks
const state = crypto.randomBytes(32).toString('hex');
session.oauthState = state;
// Build the authorization URL
const authUrl = new URL('https://api.titanium-vault.com/oauth/authorize');
authUrl.searchParams.set('client_id', process.env.TV_CLIENT_ID);
authUrl.searchParams.set('redirect_uri', 'https://app.acme.com/auth/callback');
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('scope', 'openid profile email');
authUrl.searchParams.set('state', state);
// Redirect the user's browser
res.redirect(authUrl.toString());2. Handle the callback and exchange the authorization code for tokens:
// In your /auth/callback route handler
app.get('/auth/callback', async (req, res) => {
const { code, state } = req.query;
// Verify the state parameter matches what we stored
if (state !== req.session.oauthState) {
return res.status(403).send('Invalid state parameter');
}
// Exchange the authorization code for tokens
const tokenResponse = await fetch(
'https://api.titanium-vault.com/oauth/token',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'authorization_code',
client_id: process.env.TV_CLIENT_ID,
client_secret: process.env.TV_CLIENT_SECRET,
code: code,
redirect_uri: 'https://app.acme.com/auth/callback',
}),
}
);
const tokens = await tokenResponse.json();
// tokens.access_token - for API calls
// tokens.id_token - contains user identity claims
// Decode the ID token to get user information
const payload = JSON.parse(
Buffer.from(tokens.id_token.split('.')[1], 'base64').toString()
);
// Create a session for the user
req.session.user = {
id: payload.sub,
email: payload.email,
name: payload.name,
};
res.redirect('/dashboard');
});That is the entire OAuth flow. Your user clicks “Sign in with SSO,” gets redirected to TitaniumVault (where their identity provider handles authentication), and comes back to your app with a valid session.
Option B: SAML 2.0
SAML uses XML-based assertions and requires a bit more setup, but it is the protocol most large enterprises expect. Here is how to configure it:
1. Configure your Service Provider (SP) metadata:
// SAML Service Provider configuration
const samlConfig = {
// Your application's entity ID (unique identifier)
entityId: 'https://app.acme.com/saml/metadata',
// Where TitaniumVault sends the SAML response
assertionConsumerServiceUrl: 'https://app.acme.com/saml/acs',
// TitaniumVault's IdP metadata URL (from your dashboard)
idpMetadataUrl:
'https://api.titanium-vault.com/saml/metadata/org_a1b2c3d4e5',
// The certificate TitaniumVault uses to sign assertions
// Download this from Settings > SAML > Signing Certificate
idpCertificate: fs.readFileSync('./certs/titaniumvault.pem', 'utf-8'),
// Your private key for signing SAML requests (optional but recommended)
privateKey: fs.readFileSync('./certs/sp-private-key.pem', 'utf-8'),
// Require signed assertions for security
wantAssertionsSigned: true,
};2. Handle the SAML assertion at your Assertion Consumer Service (ACS) endpoint:
// In your /saml/acs route handler
app.post('/saml/acs', async (req, res) => {
const samlResponse = req.body.SAMLResponse;
// Decode and parse the base64-encoded SAML response
const decoded = Buffer.from(samlResponse, 'base64').toString('utf-8');
// Validate the XML signature against the IdP certificate
// Use a SAML library for this - never parse XML manually
const assertion = await validateSamlResponse(decoded, samlConfig);
if (!assertion.isValid) {
return res.status(403).send('Invalid SAML assertion');
}
// Extract user attributes from the assertion
const user = {
id: assertion.nameId,
email: assertion.attributes['email'],
firstName: assertion.attributes['firstName'],
lastName: assertion.attributes['lastName'],
groups: assertion.attributes['groups'] || [],
};
// Create a session for the user
req.session.user = user;
// Redirect to the originally requested page or dashboard
const relayState = req.body.RelayState || '/dashboard';
res.redirect(relayState);
});For SAML, always use a well-maintained library to parse and validate assertions. Parsing XML and verifying signatures by hand is error-prone and opens you up to XML signature wrapping attacks. Popular libraries include passport-saml for Node.js, python3-saml for Python, and ruby-saml for Ruby.
Step 5: Test Your Integration
TitaniumVault provides a built-in test identity provider so you can verify your integration without connecting a real IdP like Okta or Azure AD. Here is how to test:
- Enable the test IdP: In your TitaniumVault dashboard, go to Applications > Your App > Testing and toggle on the test identity provider.
- Create a test user: Add a test user with an email and password in the testing panel. This user exists only in the test IdP and is completely isolated from production.
- Trigger the login flow: Open your application and click your “Sign in with SSO” button. You should be redirected to the TitaniumVault test login page.
- Authenticate: Log in with the test user credentials. You should be redirected back to your callback URL with a valid token or SAML assertion.
- Verify user data: Check that the user session in your application contains the correct email, name, and any other attributes you configured.
If anything goes wrong, the TitaniumVault dashboard shows detailed logs for every authentication attempt. Navigate to Logs > Authentication to see the full request and response for each SSO event, including any error messages and stack traces.
Common Pitfalls and How to Avoid Them
After helping thousands of developers integrate SSO, here are the mistakes we see most often:
1. Not Validating the State Parameter (OAuth)
The state parameter in OAuth exists to prevent cross-site request forgery (CSRF) attacks. Always generate a unique, random state value before redirecting the user, store it in the session, and verify it matches when the user returns. Skipping this check means an attacker could trick a user into logging in as someone else.
2. Exposing Client Secrets in Frontend Code
Your OAuth Client Secret must only ever live on your backend server, in environment variables or a secrets manager. If it appears in browser JavaScript, mobile app bundles, or version control, consider it compromised. Rotate it immediately from the TitaniumVault dashboard if this happens.
3. Not Validating SAML Signatures
Every SAML assertion is signed by the identity provider. If you do not validate this signature against the IdP's certificate, an attacker can forge assertions and impersonate any user. Always use a trusted SAML library that handles signature validation, and always check both the response signature and the assertion signature.
4. Hardcoding Callback URLs
Your callback URL must match exactly what is registered in TitaniumVault. A trailing slash mismatch, a different port number, or using HTTP instead of HTTPS will cause the flow to fail. Use environment variables for callback URLs so each environment (development, staging, production) has the correct value.
5. Ignoring Token Expiration
Both OAuth access tokens and SAML assertions have expiration times. Build your session management to respect these. When a token expires, redirect the user through the SSO flow again or use a refresh token (if your OAuth configuration includes one) to obtain a new access token silently.
6. Not Implementing Single Logout
Single Sign-On should come with Single Logout (SLO). When a user logs out of one application, they should be logged out of all applications in the SSO session. TitaniumVault supports both SAML SLO and OAuth session revocation. Implement logout properly so users do not remain authenticated in your app after leaving the SSO session.
Next Steps
You now have a working SSO integration. Here is what to do next to make it production-ready:
- Add role mapping: Map identity provider groups to roles in your application. TitaniumVault lets you configure attribute mappings so you can automatically assign admin, editor, or viewer roles based on the user's IdP groups.
- Enable MFA enforcement: Use TitaniumVault's MFA policies to require multi-factor authentication for all SSO users. This adds a second layer of security on top of the identity provider's own authentication.
- Configure provisioning: Set up SCIM (System for Cross-domain Identity Management) to automatically create, update, and deactivate user accounts when changes happen in the identity provider. This keeps your user directory in sync without manual effort.
- Set up audit logging: TitaniumVault logs every authentication event. Integrate these logs with your SIEM or monitoring system to detect anomalies and meet compliance requirements.
- Add a second protocol: If you started with OAuth, consider adding SAML support for enterprise customers who require it (or vice versa). With TitaniumVault, the same application can support both protocols simultaneously.
- Test with real identity providers: Connect a real IdP like Okta, Azure AD, Google Workspace, or OneLogin. TitaniumVault has pre-built connectors for all of these, with step-by-step configuration guides in the dashboard.
SSO is one of the most impactful features you can add to your application. Enterprise customers expect it, and with TitaniumVault, implementing it does not have to be a multi-sprint project. Get started with our free tier or explore our pricing plans for production use.