Auth Guard Module
The Auth Guard module allows your Crowdin app to implement additional authentication and authorization checks during the user login flow. This module is executed after standard authentication (password, MFA, device verification) but before granting access to the organization.
Module Type
Section titled “Module Type”- Type:
auth-guard - Scope: Organization
- Available in: Crowdin Enterprise
Use Cases
Section titled “Use Cases”- Compliance Checks: Enforce organization-specific security policies
- Multi-factor Authorization: Add custom authorization steps beyond standard MFA
Verification Types
Section titled “Verification Types”The Auth Guard module supports three verification types:
1. Direct Type (Backend-only)
Section titled “1. Direct Type (Backend-only)”Server-to-server verification without user interaction.
Use when:
- Verification can be done automatically (country check, the user has an assigned task)
- No user input needed
- Fast response time (< 10 seconds)
2. Redirect Type (External Page)
Section titled “2. Redirect Type (External Page)”Redirects user to an external page for verification.
Use when:
- User interaction required (accept terms, solve captcha)
- Need full page control
- Validation with external authorization server
3. IFrame Type (Embedded UI)
Section titled “3. IFrame Type (Embedded UI)”Displays verification page in an iframe within Crowdin.
Use when:
- Want to keep user within Crowdin interface
- Need custom UI but don’t want full redirect
- Building interactive verification
Configuration Examples
Section titled “Configuration Examples”The following examples demonstrate different ways to configure Auth Guard modules. You can customize the implementation based on your specific requirements.
Basic Example (Direct Type)
Section titled “Basic Example (Direct Type)”import { createApp } from '@crowdin/app-project-module';
createApp({ identifier: 'my-security-app', name: 'Security App', clientId: process.env.CROWDIN_CLIENT_ID, clientSecret: process.env.CROWDIN_CLIENT_SECRET, baseUrl: process.env.BASE_URL,
authGuard: { name: 'Country Whitelist Check', description: 'Verifies user country', options: { type: 'direct', applyToAdmin: false }, verify: async ({ userId, organizationId, ipAddress }) => { // Check country from IP address const allowed = await checkCountryAllowlist(organizationId, ipAddress);
if (allowed) { return { success: true }; }
return { success: false, message: 'Access denied: Authorization from Russia is forbidden' }; } }});Example: Multiple Auth Guard Modules
Section titled “Example: Multiple Auth Guard Modules”authGuard: [ { key: 'country-check', name: 'Country Whitelist', options: { type: 'direct' }, verify: async ({ ipAddress, organizationId }) => { // Country verification logic return { success: true }; } }, { key: 'device-trust', name: 'Company Device Verification', options: { type: 'redirect', url: '/device-verification' }, verify: async ({ code, userId }) => { if (!code) { return { success: false }; // Trigger redirect }
// Verify code from redirect const valid = await verifyDeviceCode(code, userId); return { success: valid }; } }]Example: Redirect Type
Section titled “Example: Redirect Type”authGuard: { name: 'Company Device Verification', options: { type: 'redirect', url: '/device-verification' // User-facing URL }, verify: async ({ code, userId }) => { if (!code) { // No code yet, user will be redirected return { success: false }; }
// Verify code and check if device was verified const deviceVerified = await verifyDeviceCode(code, userId);
if (deviceVerified) { return { success: true }; }
return { success: false, message: 'Device verification failed' }; }}On the redirect page (/device-verification), your application could implement logic such as:
- Verifying device fingerprint or certificate
- Checking browser version and security settings
- Validating company device requirements
- Generating a verification code
- Redirecting back to Crowdin with the code and state parameter:
https://accounts.crowdin.com/{domain}/guard/callback?state={STATE}&code={CODE}
The only requirement is to redirect back with the state parameter and either a code (success) or error (failure).
Example: IFrame Type with UI Module
Section titled “Example: IFrame Type with UI Module”authGuard: { name: 'Translation Agency Terms', description: 'Accept translation agency terms to continue', options: { type: 'iframe', url: '/terms-acceptance-iframe' }, settingsUiModule: { uiPath: path.join(__dirname, 'public'), fileName: 'terms-settings.html' }, verify: async ({ code, userId, context }) => { if (!code) { return { success: false }; }
const termsAccepted = await verifyTermsAcceptance(code, userId);
if (termsAccepted) { return { success: true }; }
return { success: false, message: 'Terms must be accepted to continue' }; }}Module Properties
Section titled “Module Properties”| Property | Type | Required | Description |
|---|---|---|---|
key | string | No | Unique identifier (auto-generated if not provided) |
name | string | No | Display name for the verification step |
description | string | No | Description shown to users (primarily for iframe type) |
options | object | No | Module configuration options |
options.type | string | No | Verification type: direct, redirect, or iframe (default: direct) |
options.applyToAdmin | boolean | No | Apply to administrators (default: false, owner always bypassed) |
options.url | string | No* | User-facing URL for redirect and iframe types (required for those types) |
settingsUiModule | object | No | UI module for settings configuration |
verify | function | Yes | Verification logic function |
Verify Function Parameters
Section titled “Verify Function Parameters”The verify function receives an object with:
{ client?: Crowdin; // Crowdin API client context?: CrowdinContextInfo; // JWT context information userId: number; // User ID organizationId: number; // Organization ID ipAddress: string; // User's IP address moduleKey: string; // Module key identifier code?: string; // Verification code (for redirect/iframe)}Verify Function Response
Section titled “Verify Function Response”Required: The function must return an object with a success boolean property:
{ success: boolean; // Whether verification passed message?: string; // Optional error/info message}Important: Always return HTTP 200. Use success: false to indicate failed verification, not HTTP error codes.
IFrame Type Implementation Example
Section titled “IFrame Type Implementation Example”For iframe type, you can create an HTML page that uses the Crowdin Apps SDK. Here’s an example:
<!DOCTYPE html><html><head> <title>Translation Agency Terms</title> <script src="https://cdn.crowdin.com/apps/dist/iframe.js"></script></head><body> <h1>Translation Agency Terms of Service</h1> <div class="terms-content"> <p>Please read and accept our translation agency terms to continue...</p> <!-- Terms content here --> </div>
<button id="accept">Accept Terms</button> <button id="decline">Decline</button>
<script> const urlParams = new URLSearchParams(window.location.search); const jwtToken = urlParams.get('jwtToken'); const state = urlParams.get('state');
document.getElementById('accept').addEventListener('click', async () => { // Generate verification code after user accepts terms const code = await generateCode(jwtToken, state);
// Send success to Crowdin AP.verifyAuth({ code: code }); });
document.getElementById('decline').addEventListener('click', () => { AP.verifyAuth({ error: 'User declined terms' }); });
async function generateCode(token, state) { const response = await fetch('/api/generate-code', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ state }) }); const data = await response.json(); return data.code; } </script></body></html>Role-Based Application
Section titled “Role-Based Application”By default, Auth Guard modules are applied to:
- Regular users: Always
- Administrators: Only if
applyToAdmin: true - Organization owner: Never (always bypassed)
Security Requirements
Section titled “Security Requirements”These are mandatory security requirements for Auth Guard modules:
- Token Validation: JWT tokens are automatically validated by the framework
- State Management: The state parameter is managed by Crowdin - you must return it unchanged in callbacks
- HTTPS Required: All communication must use HTTPS in production
- Timeout Handling:
- Direct type: Must respond within 10 seconds
- Redirect/IFrame type: State expires in 5 minutes
- JWT tokens expire in 15 minutes
Recommended Best Practices
Section titled “Recommended Best Practices”These are recommended practices for implementing Auth Guard modules:
- Fail Securely: Consider defaulting to denying access if verification cannot be completed
- Clear Messages: Provide user-friendly error messages to help users understand what went wrong
- Performance: Optimize API response time, especially for direct type (< 10 seconds)
- Logging: Consider logging all verification attempts for security auditing
- Monitoring: Consider tracking verification success rates and response times
Platform Limitations
Section titled “Platform Limitations”These are platform-level limitations you need to be aware of:
- Direct type timeout: 10 seconds maximum response time
- State expiration: 5 minutes for redirect/iframe flows
- JWT expiration: 15 minutes
- Code usage: Verification codes should be single-use only
- Owner bypass: Organization owner always bypasses auth guards