Setup SAML
Configure SAML 2.0 for enterprise single sign-on integration with your AI applications and MCP servers.
Overview
Security Assertion Markup Language (SAML) 2.0 is an XML-based standard for exchanging authentication and authorization data between identity providers and service providers. SAML is commonly used in enterprise environments for single sign-on (SSO).
Benefits of SAML
- Enterprise Integration: Works with existing enterprise identity systems
- Single Sign-On: Users authenticate once across multiple applications
- Centralized Management: IT administrators control access from one location
- Security: Strong security with digital signatures and encryption
- Compliance: Meets enterprise security and compliance requirements
SAML Configuration
1. Configure SAML in Authsec
Set up SAML as an identity provider connection:
- Navigate to Connections → Enterprise
- Click Create Connection → SAML
- Configure the connection settings:
{
"name": "Enterprise SAML",
"strategy": "samlp",
"options": {
"sign_in_endpoint": "https://idp.company.com/sso/saml",
"sign_out_endpoint": "https://idp.company.com/slo/saml",
"x509_signing_cert": "-----BEGIN CERTIFICATE-----\nMIIC...\n-----END CERTIFICATE-----",
"tenant_domain": "company.com",
"domain_aliases": ["company.com", "subsidiary.com"],
"sign_saml_request": true,
"signature_algorithm": "rsa-sha256",
"digest_algorithm": "sha256"
}
}
2. Metadata Configuration
Service Provider Metadata
Authsec provides metadata for your identity provider:
<?xml version="1.0" encoding="UTF-8"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
entityID="https://your-domain.authsec.com">
<md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIIDEjCCAfqgAwIBAgIJALV...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="https://your-domain.authsec.com/login/callback"
index="0" isDefault="true"/>
</md:SPSSODescriptor>
</md:EntityDescriptor>
Identity Provider Metadata
Configure your IdP metadata in Authsec:
{
"idp_metadata": {
"entity_id": "https://idp.company.com",
"sso_url": "https://idp.company.com/sso/saml",
"slo_url": "https://idp.company.com/slo/saml",
"certificate": "-----BEGIN CERTIFICATE-----\nMIIC...\n-----END CERTIFICATE-----"
}
}
3. Attribute Mapping
Map SAML attributes to user properties:
{
"attribute_mapping": {
"user_id": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
"email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"given_name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",
"family_name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
"groups": "http://schemas.microsoft.com/ws/2008/06/identity/claims/groups",
"department": "http://schemas.company.com/identity/claims/department",
"employee_id": "http://schemas.company.com/identity/claims/employeeid"
}
}
Implementation
Web Application Integration
import { AuthsecClient } from '@authsec/sdk';
const authsec = new AuthsecClient({
domain: 'your-domain.authsec.com',
clientId: 'your-client-id'
});
// Initiate SAML login
function loginWithSAML() {
const authUrl = authsec.buildAuthorizeUrl({
response_type: 'code',
scope: 'openid profile email',
connection: 'samlp-enterprise' // SAML connection name
});
window.location.href = authUrl;
}
Handle SAML Response
// Handle SAML authentication callback
async function handleSAMLCallback(req, res) {
try {
const { code } = req.query;
// Exchange code for tokens
const tokens = await authsec.exchangeCodeForTokens({
code: code,
redirect_uri: 'https://yourapp.com/callback'
});
// Get user information
const user = await authsec.getUserInfo(tokens.access_token);
// Process SAML attributes
const enterpriseUser = {
id: user.sub,
email: user.email,
name: user.name,
department: user.department,
employeeId: user.employee_id,
groups: user.groups || [],
lastLogin: new Date()
};
// Store user session
req.session.user = enterpriseUser;
req.session.accessToken = tokens.access_token;
res.redirect('/dashboard');
} catch (error) {
console.error('SAML authentication failed:', error);
res.redirect('/login?error=saml_failed');
}
}
Group-Based Authorization
// Check user group membership for authorization
function checkGroupMembership(user, requiredGroups) {
const userGroups = user.groups || [];
return requiredGroups.some(group => userGroups.includes(group));
}
// Middleware for group-based access control
function requireGroups(groups) {
return (req, res, next) => {
if (!req.session.user) {
return res.status(401).json({ error: 'Not authenticated' });
}
if (!checkGroupMembership(req.session.user, groups)) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
next();
};
}
// Usage
app.get('/admin/users', requireGroups(['IT-Admins', 'HR-Managers']), (req, res) => {
// Only users in IT-Admins or HR-Managers groups can access
res.json({ users: getUserList() });
});
Advanced Configuration
Just-In-Time (JIT) Provisioning
Automatically create users when they first log in:
{
"jit_provisioning": {
"enabled": true,
"connection": "samlp-enterprise",
"user_creation": {
"enabled": true,
"sync_attributes": true
},
"profile_sync": {
"enabled": true,
"sync_on_login": true,
"attributes": ["name", "email", "department", "groups"]
}
}
}
Single Logout (SLO)
Configure single logout to end sessions across all applications:
// Initiate single logout
async function singleLogout() {
try {
// Revoke local tokens
await authsec.revokeToken(req.session.refreshToken);
// Clear local session
req.session.destroy();
// Redirect to SAML SLO endpoint
const sloUrl = authsec.buildLogoutUrl({
connection: 'samlp-enterprise',
returnTo: 'https://yourapp.com/'
});
res.redirect(sloUrl);
} catch (error) {
console.error('Single logout failed:', error);
res.redirect('/');
}
}
Custom SAML Attributes
Handle custom enterprise attributes:
// Process custom SAML attributes
function processCustomAttributes(samlUser) {
return {
standardProfile: {
id: samlUser.sub,
email: samlUser.email,
name: samlUser.name
},
enterpriseProfile: {
employeeId: samlUser['http://schemas.company.com/identity/claims/employeeid'],
department: samlUser['http://schemas.company.com/identity/claims/department'],
manager: samlUser['http://schemas.company.com/identity/claims/manager'],
costCenter: samlUser['http://schemas.company.com/identity/claims/costcenter'],
location: samlUser['http://schemas.company.com/identity/claims/location']
},
permissions: {
aiAccess: checkAIPermissions(samlUser.groups),
mcpTools: getMCPToolAccess(samlUser.department),
dataAccess: getDataAccessLevel(samlUser.groups)
}
};
}
Security Best Practices
Certificate Management
// Validate SAML certificates
function validateSAMLCertificate(cert) {
try {
const x509 = new crypto.X509Certificate(cert);
// Check certificate validity
const now = new Date();
if (now < x509.validFrom || now > x509.validTo) {
throw new Error('Certificate is expired or not yet valid');
}
// Verify certificate chain if applicable
return true;
} catch (error) {
console.error('Certificate validation failed:', error);
return false;
}
}
Signature Verification
// Verify SAML response signature
function verifySAMLSignature(samlResponse, certificate) {
try {
const verify = crypto.createVerify('RSA-SHA256');
verify.update(samlResponse);
return verify.verify(certificate, signature, 'base64');
} catch (error) {
console.error('Signature verification failed:', error);
return false;
}
}
Assertion Validation
// Validate SAML assertions
function validateSAMLAssertion(assertion) {
const checks = {
// Check assertion is not expired
notExpired: () => {
const conditions = assertion.Conditions;
const now = new Date();
return now >= new Date(conditions.NotBefore) &&
now <= new Date(conditions.NotOnOrAfter);
},
// Check audience restriction
audienceValid: () => {
const audience = assertion.Conditions.AudienceRestriction.Audience;
return audience === 'https://your-domain.authsec.com';
},
// Check subject confirmation
subjectConfirmed: () => {
const confirmation = assertion.Subject.SubjectConfirmation;
return confirmation.Method === 'urn:oasis:names:tc:SAML:2.0:cm:bearer';
}
};
return Object.values(checks).every(check => check());
}
Troubleshooting
Common Issues
- Certificate Errors: Verify certificate format and validity
- Attribute Mapping: Check attribute names match IdP configuration
- Clock Skew: Ensure server times are synchronized
- Signature Failures: Verify signing certificates and algorithms
- Redirect Loops: Check callback URL configuration
Debug SAML Responses
// Debug SAML response
function debugSAMLResponse(samlResponse) {
try {
// Decode base64 SAML response
const decoded = Buffer.from(samlResponse, 'base64').toString('utf-8');
// Parse XML
const parser = new xml2js.Parser();
parser.parseString(decoded, (err, result) => {
if (err) {
console.error('XML parsing failed:', err);
return;
}
console.log('SAML Response:', JSON.stringify(result, null, 2));
// Extract key information
const assertion = result.Response.Assertion[0];
console.log('Subject:', assertion.Subject[0].NameID[0]._);
console.log('Attributes:', assertion.AttributeStatement[0].Attribute);
});
} catch (error) {
console.error('SAML response debug failed:', error);
}
}
Validation Tools
Use online tools to validate SAML configuration:
- SAML Response validators
- Certificate validators
- Metadata validators
- Clock skew checkers
Enterprise Integration Examples
Active Directory Federation Services (ADFS)
{
"name": "ADFS Connection",
"strategy": "samlp",
"options": {
"sign_in_endpoint": "https://adfs.company.com/adfs/ls/",
"x509_signing_cert": "MIIDEjCCA...",
"tenant_domain": "company.com",
"field_map": {
"email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
}
}
}
Okta SAML Integration
{
"name": "Okta SAML",
"strategy": "samlp",
"options": {
"sign_in_endpoint": "https://company.okta.com/app/authsec_app/exk.../sso/saml",
"x509_signing_cert": "MIIDpDCCAoygAw...",
"tenant_domain": "company.com"
}
}
Azure AD SAML
{
"name": "Azure AD SAML",
"strategy": "samlp",
"options": {
"sign_in_endpoint": "https://login.microsoftonline.com/.../saml2",
"x509_signing_cert": "MIIC8DCCAdigAwIBA...",
"tenant_domain": "company.onmicrosoft.com"
}
}