modular-sso
Implement SSO as a Modular
Quick Start
Choose your authentication mode:
- Modular SSO: You manage users and sessions (covered here)
- Full-Stack Auth: Scalekit manages users and sessions (built-in SSO)
This skill covers Modular SSO for applications with existing user management.
Implementation Workflow
Copy this checklist and track progress:
Authentication Integration Progress:
- [ ] Step 1: Configure Modular Auth mode
- [ ] Step 2: Install and configure Scalekit SDK
- [ ] Step 3: Implement authorization URL generation
- [ ] Step 4: Handle IdP-initiated SSO (RECOMMENDED)
- [ ] Step 5: Process authentication callback
- [ ] Step 6: Validate tokens and extract user profile
- [ ] Step 7: Test SSO integration
- [ ] Step 8: Set up customer onboarding flow
Step 1: Configure Modular Auth Mode
Action: Configure environment for Modular SSO:
- Navigate to Dashboard > Authentication > General
- Under "Full-Stack Auth" section, click "Disable Full-Stack Auth"
Result: System ready for modular integration.
Step 2: Install and Configure SDK
Installation
Choose the SDK for the project's tech stack:
Node.js:
npm install @scalekit-sdk/node
Python:
pip install scalekit-sdk-python
Go:
go get github.com/scalekit-inc/scalekit-sdk-go
Java:
<dependency>
<groupId>com.scalekit</groupId>
<artifactId>scalekit-sdk-java</artifactId>
</dependency>
Environment Configuration
Add these credentials to .env file (fetch from Dashboard > Developers > Settings > API credentials):
SCALEKIT_ENVIRONMENT_URL=<environment-url>
SCALEKIT_CLIENT_ID=<client-id>
SCALEKIT_CLIENT_SECRET=<client-secret>
Step 3: Generate Authorization URL
Create authorization URL to redirect users to their identity provider.
SSO Connection Selectors (Priority Order)
Use ONE of these identifiers (evaluated in precedence order):
- connectionId (highest) - Direct SSO connection reference
- organizationId - Routes to organization's active SSO
- loginHint - Extracts domain from email to find connection
Implementation Pattern
Node.js:
const scalekit = new ScalekitClient(
process.env.SCALEKIT_ENVIRONMENT_URL,
process.env.SCALEKIT_CLIENT_ID,
process.env.SCALEKIT_CLIENT_SECRET
);
const options = {
organizationId: 'org_15421144869927830', // OR
connectionId: 'conn_15696105471768821', // OR
loginHint: 'user@example.com'
};
const authUrl = scalekit.getAuthorizationUrl(
'https://yourapp.com/auth/callback',
options
);
// Redirect user to authUrl
Python:
from scalekit import ScalekitClient, AuthorizationUrlOptions
scalekit = ScalekitClient(
os.getenv('SCALEKIT_ENVIRONMENT_URL'),
os.getenv('SCALEKIT_CLIENT_ID'),
os.getenv('SCALEKIT_CLIENT_SECRET')
)
options = AuthorizationUrlOptions()
options.organization_id = 'org_15421144869927830'
auth_url = scalekit.get_authorization_url(
redirect_uri='https://yourapp.com/auth/callback',
options=options
)
Direct URL (no SDK):
<SCALEKIT_ENVIRONMENT_URL>/oauth/authorize?
response_type=code&
client_id=<CLIENT_ID>&
redirect_uri=<CALLBACK_URL>&
scope=openid profile email&
organization_id=<ORG_ID>
Step 4: Handle IdP-Initiated SSO
CRITICAL: Implement this to support users who start login from their identity provider portal.
Why This Matters
IdP-initiated SSO converts potentially insecure flows into secure SP-initiated flows, protecting against SAML assertion theft and replay attacks.
Configuration Required
- Set initiate login endpoint: Dashboard > Authentication > Redirects
- Configure endpoint:
https://yourapp.com/login
Implementation
Node.js:
app.get('/login', async (req, res) => {
const { idp_initiated_login, error, error_description } = req.query;
if (error) {
return res.status(400).json({ message: error_description });
}
if (idp_initiated_login) {
// Decode JWT to extract connection details
const claims = await scalekit.getIdpInitiatedLoginClaims(idp_initiated_login);
const options = {
connectionId: claims.connection_id,
organizationId: claims.organization_id,
loginHint: claims.login_hint,
state: claims.relay_state
};
const authUrl = scalekit.getAuthorizationUrl(
'https://yourapp.com/auth/callback',
options
);
return res.redirect(authUrl);
}
// Handle normal login flow
});
Python:
@app.route('/login')
async def handle_login():
idp_initiated_login = request.args.get('idp_initiated_login')
error = request.args.get('error')
if error:
return {'error': request.args.get('error_description')}, 400
if idp_initiated_login:
claims = await scalekit.get_idp_initiated_login_claims(idp_initiated_login)
options = AuthorizationUrlOptions()
options.connection_id = claims.get('connection_id')
options.organization_id = claims.get('organization_id')
options.state = claims.get('relay_state')
auth_url = scalekit.get_authorization_url(
redirect_uri='https://yourapp.com/auth/callback',
options=options
)
return redirect(auth_url)
Step 5: Process Authentication Callback
Handle the callback after successful IdP authentication.
Callback Endpoint Setup
- Create endpoint:
/auth/callback - Register in Dashboard > Authentication > Redirect URLs > Allowed Callback URLs
Implementation
Node.js:
app.get('/auth/callback', async (req, res) => {
const { code, error, error_description } = req.query;
if (error) {
return res.status(400).json({ error: error_description });
}
try {
// Exchange code for user profile and tokens
const result = await scalekit.authenticateWithCode(
code,
'https://yourapp.com/auth/callback'
);
// Extract user information
const userEmail = result.user.email;
const userName = result.user.givenName + ' ' + result.user.familyName;
const userId = result.user.id;
// Create session for authenticated user
req.session.user = {
id: userId,
email: userEmail,
name: userName
};
res.redirect('/dashboard');
} catch (err) {
res.status(500).json({ error: 'Authentication failed' });
}
});
Python:
@app.route('/auth/callback')
async def auth_callback():
code = request.args.get('code')
error = request.args.get('error')
if error:
return {'error': request.args.get('error_description')}, 400
result = scalekit.authenticate_with_code(
code,
'https://yourapp.com/auth/callback'
)
# Create session
session['user'] = {
'id': result.user.id,
'email': result.user.email,
'name': f"{result.user.given_name} {result.user.family_name}"
}
return redirect('/dashboard')
Step 6: Validate Tokens
ALWAYS validate tokens before trusting claims.
Node.js:
// Validate ID token
const idTokenClaims = await scalekit.validateToken(result.idToken);
// Validate access token
const accessTokenClaims = await scalekit.validateToken(result.accessToken);
Python:
id_token_claims = scalekit.validate_token(result['id_token'])
access_token_claims = scalekit.validate_token(result['access_token'])
Token Structure
ID Token includes:
email: User's email addressgiven_name,family_name: User's namesub: Unique user identifier (format:connectionId;userId)oid: Organization IDamr: Authentication method (SSO connection ID)
Access Token includes:
sub: User identifierexp: Expiration timestampclient_id: Your application client ID
Step 7: Test SSO Integration
Use the built-in IdP Simulator for comprehensive testing.
Test Organization Setup
Your environment includes pre-configured test organization with domains:
@example.com@example.org
Testing Workflow
- Find test organization: Dashboard > Organizations
- Use test selector: Pass one of these in authorization URL:
- Email with
@example.comdomain - Test organization's connection ID
- Organization ID
- Email with
- Simulate SSO flow: IdP Simulator appears (mimics customer's IdP)
- Complete authentication: Enter test credentials
- Verify callback: Check user profile received correctly
Test Scenarios
Test ALL three scenarios:
- SP-initiated SSO: User starts login from your app
- IdP-initiated SSO: User starts from IdP portal
- Domain-based routing: User enters email, auto-routes to IdP
Step 8: Customer Onboarding
Enable SSO for enterprise customers through self-service Admin Portal.
Quick Onboarding
Create organization: Dashboard > Organizations > New Organization
Generate portal link (Node.js):
const portalLink = await scalekit.organization.generatePortalLink(
'org_32656XXXXXX0438'
);
// Share this link with customer's IT admin
console.log('Admin Portal:', portalLink.location);
Share link: Send to customer's IT administrator via email/Slack
Share setup guide: Include the Scalekit SSO setup guide — provider-specific steps for Okta, Azure AD, Google Workspace, and others.
Embedded Portal (Advanced)
Embed Admin Portal in your app for seamless experience:
// Backend: Generate portal link
const portalLink = await scalekit.organization.generatePortalLink(orgId);
res.json({ portalUrl: portalLink.location });
<!-- Frontend: Embed in iframe -->
<iframe
src="${portalUrl}"
width="100%"
height="600"
frameborder="0"
allow="clipboard-write">
</iframe>
Advanced Patterns
Pre-Check SSO Availability
Prevent failed redirects by checking SSO configuration before redirecting:
Node.js:
const domain = email.split('@').toLowerCase(); [reddit](https://www.reddit.com/r/ClaudeAI/comments/1qb1024/ultimate_claude_skillmd_autobuilds_any_fullstack/)
const connections = await scalekit.connections.listConnectionsByDomain({
domain
});
if (connections.length > 0) {
// SSO available - redirect to IdP
const authUrl = scalekit.getAuthorizationUrl(redirectUri, {
domainHint: domain
});
return res.redirect(authUrl);
} else {
// No SSO - show password login
return showPasswordLogin();
}
Domain Verification
Enable seamless routing by verifying customer domains:
- Customer verifies domain (e.g.,
@megacorp.org) in Admin Portal - Users sign in without organization selection
- Scalekit auto-routes based on email domain
Session Management Best Practices
Set secure session configuration:
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // HTTPS only
httpOnly: true, // Prevent XSS
maxAge: 86400000, // 24 hours
sameSite: 'lax' // CSRF protection
}
}));
Implement session refresh:
// Check token expiration
if (Date.now() / 1000 > accessTokenClaims.exp) {
// Redirect to re-authentication
return res.redirect('/login');
}
Integration with Existing Auth Systems
Auth0 Integration
Configure Scalekit as Custom Social Connection in Auth0:
- Auth0 Dashboard > Authentication > Social > Create Connection
- Use Scalekit OAuth2 endpoints
- Map Scalekit user attributes to Auth0 profile
Firebase Integration
Add Scalekit as Custom Auth Provider:
- Use Firebase Custom Token generation
- Exchange Scalekit tokens for Firebase tokens
- Maintain session with Firebase SDK
AWS Cognito Integration
Configure Scalekit as SAML Identity Provider:
- Cognito User Pool > Identity Providers > SAML
- Use Scalekit metadata URL
- Map attributes to Cognito user attributes
Security Checklist
Before production deployment, verify:
- Environment variables stored securely (never in code)
- HTTPS enforced on all endpoints
- Tokens validated before trusting claims
- Session cookies use
secureandhttpOnlyflags - CSRF protection enabled
- Callback URLs registered in Scalekit dashboard
- Error messages don't expose sensitive information
- Rate limiting implemented on auth endpoints
- Logging configured (without exposing tokens)
Troubleshooting
"Invalid redirect_uri" Error
Cause: Callback URL not registered in dashboard Fix: Add URL to Dashboard > Authentication > Redirect URLs
"Organization not found" Error
Cause: Invalid organization ID or user doesn't belong to organization Fix: Verify organization ID and user's email domain
IdP-Initiated SSO Not Working
Cause: Initiate login URL not configured Fix: Set URL in Dashboard > Authentication > Redirects
Token Validation Fails
Cause: Token expired or invalid signature Fix: Check token expiration and environment URL configuration
Common Patterns
Multi-Tenant Architecture
// Determine organization from subdomain
const subdomain = req.hostname.split('.');
const organization = await getOrganizationBySubdomain(subdomain);
const authUrl = scalekit.getAuthorizationUrl(redirectUri, {
organizationId: organization.scalekitOrgId
});
Step-Up Authentication
// Require re-authentication for sensitive operations
if (requiresStepUp && !session.recentAuth) {
return res.redirect('/auth/step-up');
}
Logout Implementation
app.post('/logout', (req, res) => {
req.session.destroy();
res.redirect('/');
});
Reference
Scalekit Dashboard: https://app.scalekit.com
Connection Selector Precedence: connectionId > organizationId > loginHint
Token Expiration: ID tokens expire in 15 minutes, access tokens in 24 hours
Admin Portal Events: Listen for sso.enabled, sso.disabled, session.expired
Support: docs.scalekit.com
Implementation Notes
Always validate tokens: Never trust token claims without validation
Handle errors gracefully: Show user-friendly messages, log details internally
Test all scenarios: SP-initiated, IdP-initiated, and domain-based routing
Enable domain verification: Provides best user experience
Use progressive enhancement: Start with basic SSO, add advanced features iteratively
Monitor authentication flows: Track success rates and common failure points
More from scalekit-inc/skills
setup-scalekit
Use when a developer is new to Scalekit and needs guidance on where to start, doesn't know which auth plugin or skill to choose, wants to connect an AI agent or agentic workflow to third-party services (Gmail, Slack, Notion, Google Calendar), needs OAuth or tool-calling auth for agents, wants to add authentication to a project but hasn't chosen an approach yet, or needs to install the Scalekit plugin for their AI coding tool (Claude Code, Codex, Copilot CLI, Cursor, or other agents).
11implementing-scalekit-fsa
Implements Scalekit full-stack authentication (FSA) including sign-up, login, logout, and secure session management using JWT tokens. Use when building or integrating user authentication with the Scalekit SDK across Node.js, Python, Go, or Java — or when the user asks about auth flows, OAuth callbacks, token refresh, or session handling with Scalekit.
4integrating-agent-auth
Integrates Scalekit Agent Auth into a project to handle OAuth flows, token storage, and automatic refresh for third-party services (Gmail, Slack, Notion, Calendar). Use when a user needs to connect to an external service, authorize OAuth access, fetch access or refresh tokens, or execute API calls on behalf of a user.
4adding-mcp-oauth
Guides users through adding OAuth 2.1 authorization to Model Context Protocol (MCP) servers using Scalekit. Use when setting up MCP servers, implementing authentication for AI hosts like Claude Desktop, Cursor, or VS Code, or when users mention MCP security, OAuth, or Scalekit integration.
3sk-actions-custom-provider
Create or review Scalekit custom providers/connectors for proxy-only usage. Use this skill when the task is to gather API docs, infer whether a connector is OAuth, Basic, Bearer, or API Key, determine required tracked fields like domain or version, generate provider JSON, check for existing custom providers, show update diffs, run approved create or update curls, and print resolved delete curls.
3implementing-fsa-logout
Implements a complete logout flow for Scalekit FSA integrations by clearing application session cookies and redirecting the browser to Scalekit’s /oidc/logout endpoint to invalidate the Scalekit session. Use when adding or fixing logout in Node.js, Python, Go, or Java web apps that use Scalekit OIDC.
2