Skip to main content

Universal Login

Universal Login is a centralized authentication page provided by Guardhouse that handles user login, registration, and authentication flows for your applications.

What is Universal Login?

Universal Login (also known as Hosted Login Page) is a pre-built, customizable login page hosted by Guardhouse. Instead of building your own login UI, you redirect users to the Guardhouse Universal Login URL.

Benefits

  • No Login UI to Maintain - Guardhouse handles all authentication logic
  • Built-in Security - Professional-grade security with password policies, MFA, and fraud detection
  • Customizable Branding - Add your logo, colors, and custom styling
  • Social Connections - Easy integration with Google, GitHub, and other social providers
  • Passwordless Authentication - Support for magic links and SMS OTP
  • Responsive Design - Works seamlessly on desktop, tablet, and mobile
  • Accessibility - WCAG compliant and keyboard navigation

How It Works

┌─────────────────────────────────────┐
│ │
│ Your Application │
│ (SPA, Web, Mobile) │
│ │
└────────────┬──────────────────────┘

│ User clicks login

┌─────────────────────────────────────┐
│ Guardhouse Universal Login │
│ │
│ - Email/Password │
│ - Social Login │
│ - MFA │
│ - Passwordless │
└────────────┬──────────────────────┘

│ Auth successful

┌─────────────────────────────────────┐
│ Redirect to your app │
│ with authorization code │
│ │
└─────────────────────────────────────┘

Configuration

You can customize Universal Login in the Guardhouse Admin Console:

Branding

  • Upload your company logo
  • Set primary and accent colors
  • Configure custom CSS
  • Add custom domains

Authentication Methods

  • Database Connection - Username/password authentication
  • Social Connections - Google, GitHub, Microsoft, etc.
  • Enterprise Connections - SAML, LDAP, Active Directory
  • Passwordless - Email magic links, SMS OTP
  • MFA - Authenticator apps, SMS codes, backup codes

User Experience

  • Password Strength Rules - Enforce minimum password complexity
  • Email Verification - Require email verification on signup
  • Forgot Password Flow - Customizable password reset experience
  • Terms & Privacy - Display your terms of service and privacy policy

Universal Login URL

The Universal Login URL follows this pattern:

https://{tenant-domain}.guardhouse.cloud/authorize

Query Parameters:

ParameterDescription
client_idYour application's Client ID
redirect_uriYour application's callback URL
response_typeMust be code
scopeRequested scopes (e.g., openid profile email)
stateRandom string for CSRF protection
promptlogin or none for login vs silent auth
login_hintPre-fill email or username
nonceRandom string for ID token replay protection

Example Usage

// Redirect to Universal Login
const loginUrl = `https://your-tenant.guardhouse.cloud/authorize?` +
new URLSearchParams({
client_id: 'YOUR_CLIENT_ID',
redirect_uri: 'https://app.example.com/callback',
response_type: 'code',
scope: 'openid profile email',
state: generateRandomState(),
nonce: generateRandomNonce()
}).toString();

// Redirect user to loginUrl
window.location.href = loginUrl;

// Handle callback
const code = new URLSearchParams(window.location.search).get('code');
const state = new URLSearchParams(window.location.search).get('state');

// Validate state to prevent CSRF attacks
if (state !== storedState) {
throw new Error('Invalid state parameter');
}

// Exchange code for tokens (using Authorization Code Flow)
const tokens = await exchangeCodeForTokens(code);

Callback Handling

After successful authentication, Guardhouse redirects users to your redirect_uri with an authorization code:

https://app.example.com/callback?code=AUTH_CODE&state=RANDOM_STATE

Your application should:

  1. Validate State - Verify state matches what you sent
  2. Exchange Code - Send code to Guardhouse token endpoint
  3. Receive Tokens - Get access token, ID token, and refresh token
  4. Create User Session - Store tokens securely and authenticate user

Callback Example

// Handle OAuth callback
async function handleCallback() {
const params = new URLSearchParams(window.location.search);
const code = params.get('code');
const state = params.get('state');

// Validate state (CSRF protection)
if (state !== getStoredState()) {
throw new Error('State mismatch - possible CSRF attack');
}

// Exchange code for tokens
const tokenResponse = await fetch('https://your-tenant.guardhouse.cloud/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
redirect_uri: 'https://app.example.com/callback',
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET', // For confidential clients
}),
}).then(res => res.json());

// Store tokens securely
localStorage.setItem('access_token', tokenResponse.access_token);
localStorage.setItem('refresh_token', tokenResponse.refresh_token);
localStorage.setItem('id_token', tokenResponse.id_token);

// Redirect to app
window.location.href = '/dashboard';
}

Advanced Features

Multi-Factor Authentication (MFA)

Universal Login supports MFA options:

  • Authenticator Apps - TOTP codes via Google Authenticator, Authy
  • SMS Codes - One-time codes sent to user's phone
  • Backup Codes - Recovery codes for emergencies

Passwordless Authentication

Options for passwordless authentication:

  • Email Magic Links - Users receive a login link via email
  • SMS OTP - Users receive a one-time code via SMS
  • Biometric - WebAuthn support for fingerprint/face recognition (coming soon)

Social Authentication

Supported social identity providers:

  • Google
  • GitHub
  • Microsoft
  • Apple
  • Facebook
  • LinkedIn
  • SAML (enterprise)
  • OIDC (custom providers)

Customization

Custom CSS

Add custom styles to Universal Login:

  1. Go to Guardhouse Admin Console
  2. Navigate to Branding > Custom CSS
  3. Add your custom CSS rules
  4. Save and preview

Custom Domain

Host Universal Login on your custom domain:

  1. Go to Guardhouse Admin Console
  2. Navigate to Branding > Custom Domain
  3. Add your domain (e.g., auth.yourcompany.com)
  4. Configure DNS with Guardhouse's CNAME records
  5. Wait for DNS propagation

Security

Universal Login implements security best practices:

  • HTTPS Only - All authentication over encrypted connections
  • CSRF Protection - State parameter validation
  • PKCE Support - For SPA and native apps
  • Rate Limiting - Prevents brute force attacks
  • Secure Password Storage - Hashed with bcrypt
  • Session Management - Secure cookie policies
  • Audit Logging - Track all authentication events

Troubleshooting

Common Issues

"Invalid redirect_uri" Error

Ensure your redirect_uri:

  • Is exactly registered in Guardhouse Admin Console
  • Uses HTTPS (no HTTP allowed)
  • Is properly URL-encoded
  • Matches case exactly

"State mismatch" Error

  • State parameter doesn't match what you sent
  • Check you're storing and comparing state correctly
  • Clear old state values between login attempts

"Access denied" Error

  • User cancelled login flow
  • User denied required permissions/consents
  • Check your scope requirements

Best Practices

  1. Use State Parameter - Always generate and validate random state strings
  2. Use PKCE for SPAs - Prevent authorization code interception
  3. Secure Token Storage - Use httpOnly cookies, not localStorage
  4. Implement Logout - Clear tokens and redirect to Universal Login logout endpoint
  5. Handle Errors - Provide clear error messages to users
  6. Test All Flows - Test login, logout, and error scenarios

Example: Complete Flow

// Complete authentication flow with Universal Login

class AuthService {
constructor(clientId, redirectUri) {
this.clientId = clientId;
this.redirectUri = redirectUri;
this.stateStore = new Map();
}

login() {
const state = this.generateState();
this.stateStore.set(state.key, state.value);

const loginUrl = new URL(`https://your-tenant.guardhouse.cloud/authorize`);
loginUrl.searchParams.set('client_id', this.clientId);
loginUrl.searchParams.set('redirect_uri', this.redirectUri);
loginUrl.searchParams.set('response_type', 'code');
loginUrl.searchParams.set('scope', 'openid profile email');
loginUrl.searchParams.set('state', state.value);
loginUrl.searchParams.set('nonce', this.generateNonce());

window.location.href = loginUrl.toString();
}

async handleCallback() {
const params = new URLSearchParams(window.location.search);
const code = params.get('code');
const state = params.get('state');

// Validate state
const storedState = this.stateStore.get(this.extractStateKey(state));
if (!storedState || storedState !== state) {
throw new Error('Invalid state parameter');
}

// Exchange code for tokens
const tokens = await this.exchangeCodeForTokens(code);

// Store tokens
this.storeTokens(tokens);

// Clean up state
this.stateStore.delete(this.extractStateKey(state));

return tokens;
}

logout() {
// Clear tokens
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
localStorage.removeItem('id_token');

// Redirect to Universal Login logout
window.location.href = 'https://your-tenant.guardhouse.cloud/oauth/logout?' +
new URLSearchParams({
post_logout_redirect_uri: this.redirectUri
}).toString();
}

generateState() {
return {
key: 'state_' + Date.now() + '_' + Math.random().toString(36),
value: Math.random().toString(36).substring(2, 15)
};
}

extractStateKey(state) {
return state.split('_')[0];
}

generateNonce() {
return Math.random().toString(36).substring(2, 15);
}

async exchangeCodeForTokens(code) {
const response = await fetch('https://your-tenant.guardhouse.cloud/oauth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
redirect_uri: this.redirectUri,
client_id: this.clientId,
client_secret: 'YOUR_CLIENT_SECRET',
}),
});

return await response.json();
}

storeTokens(tokens) {
// Store in httpOnly cookie (recommended)
// or use your SDK's token management
}
}

// Usage
const auth = new AuthService(
'YOUR_CLIENT_ID',
'https://app.example.com/callback'
);

// Trigger login
auth.login();

// Handle callback (in your callback route)
const tokens = await auth.handleCallback();

Next Steps