Lucca
This guide explains how to set up single sign-on (SSO) between SmartLink and Lucca using SAML 2.0 or OpenID Connect.
Prerequisites
- Lucca account with SSO module enabled
- Administrative access to Lucca
- Application configured in SmartLink with SAML2 or OpenID Connect
- Verified email domain
Note: SSO requires activating the SSO module in your Lucca contract.
Configuration with OpenID Connect (Recommended)
Configuration in SmartLink
1. Create the application
- Log in to SmartLink as an administrator
- Go to Applications → Add
- Create a new application:
- Name: Lucca
- URL:
https://[your-instance].ilucca.net - Description: Complete HR suite (Figgo, Pagga, Timmi, etc.)
- Icon: Choose the Lucca icon
2. Configure OpenID Connect
- In the Authentication tab
- Select OpenID Connect
- Note the information:
- Client ID:
lucca-xxxxxx - Client Secret:
secret-xxxxxx - App ID:
[appid](automatically generated unique identifier)
- Client ID:
3. Redirect URLs
Add to Allowed Redirect URLs:
https://[your-instance].ilucca.net/identity/oidc/callback
https://[your-instance].ilucca.net/auth/oidc/callback
Configuration in Lucca
1. Access SSO settings
- Log in to Lucca as an administrator
- Go to Configuration → Settings → Authentication
- Click on Single Sign-On (SSO)
- Select OpenID Connect
2. Identity provider configuration
Configure the following parameters:
- Discovery URL:
https://[your-smartlink].link.vaultys.org/api/oidc/[appid]/.well-known/openid-configuration - Client ID:
lucca-xxxxxx(from SmartLink) - Client Secret:
secret-xxxxxx(from SmartLink) - Scopes:
openid profile email groups
3. Attribute mapping
| Lucca Attribute | OpenID Claim | Required |
|---|---|---|
email | ✅ | |
| First Name | given_name | ✅ |
| Last Name | family_name | ✅ |
| Employee ID | employee_number | ❌ |
| Department | department | ❌ |
| Manager | manager_email | ❌ |
Configuration with SAML 2.0
Configuration in SmartLink
1. Configure SAML2
- In the Lucca application
- Authentication tab → SAML2
- Configure:
- Entity ID:
https://[your-smartlink].link.vaultys.org/[appid] - ACS URL:
https://[your-instance].ilucca.net/identity/saml2/acs - NameID Format:
emailAddress
- Entity ID:
2. Retrieve metadata
Note the URLs:
- IdP Metadata:
https://[your-smartlink].link.vaultys.org/api/saml2/[appid]/metadata - SSO URL:
https://[your-smartlink].link.vaultys.org/api/saml2/sso/[appid] - SLO URL:
https://[your-smartlink].link.vaultys.org/api/saml2/slo/[appid] - Entity ID:
https://[your-smartlink].link.vaultys.org/[appid]
Configuration in Lucca
- In Configuration → Authentication → SAML 2.0
- Import the metadata or configure manually:
- IdP Entity ID:
[appid] - SSO URL:
https://[your-smartlink].link.vaultys.org/api/saml2/sso/[appid] - X.509 Certificate: Import from SmartLink
- IdP Entity ID:
Lucca Modules Configuration
Figgo (Leave Management)
{
"figgo_settings": {
"auto_provision": true,
"sync_managers": true,
"default_leave_policy": "standard",
"sso_groups_mapping": {
"smartlink-managers": "validateur_n1",
"smartlink-hr": "administrateur_rh",
"smartlink-employees": "collaborateur"
}
}
}
Pagga (Payroll Management)
{
"pagga_settings": {
"restricted_access": true,
"allowed_groups": ["smartlink-hr", "smartlink-payroll"],
"permissions": {
"smartlink-payroll": ["edit_bulletins", "export_dsn"],
"smartlink-hr": ["view_bulletins", "manage_employees"],
"smartlink-managers": ["view_team_bulletins"]
}
}
}
Timmi (Time Management)
timmi_configuration:
projects:
sync_with_sso_groups: true
default_access: "member"
time_tracking:
mandatory: true
validation_workflow: "manager"
permissions:
smartlink-project-managers:
- create_projects
- manage_budgets
- view_all_timesheets
smartlink-employees:
- submit_timesheet
- view_own_timesheet
Poplee Core HR
{
"poplee_settings": {
"employee_sync": {
"source": "sso",
"update_on_login": true,
"fields_mapping": {
"department": "{{department}}",
"job_title": "{{title}}",
"manager": "{{manager_email}}",
"location": "{{office_location}}"
}
}
}
}
Data Synchronization
Lucca API with SSO
const axios = require('axios');
class LuccaAPIClient {
constructor(apiKey, domain) {
this.apiKey = apiKey;
this.baseUrl = `https://${domain}.ilucca.net/api/v3`;
}
async syncUserFromSSO(ssoUserData) {
// Search for the user by email
const user = await this.getUserByEmail(ssoUserData.email);
if (!user) {
// Create the user
return await this.createUser({
mail: ssoUserData.email,
firstName: ssoUserData.given_name,
lastName: ssoUserData.family_name,
department: ssoUserData.department,
authenticationMode: 'sso'
});
} else {
// Update the user
return await this.updateUser(user.id, {
department: ssoUserData.department,
jobTitle: ssoUserData.title
});
}
}
async getUserByEmail(email) {
const response = await axios.get(`${this.baseUrl}/users`, {
headers: { 'Authorization': `lucca application=${this.apiKey}` },
params: { mail: email }
});
return response.data.items[0];
}
}
Lucca Webhooks
// Endpoint to receive Lucca webhooks
app.post('/webhook/lucca', async (req, res) => {
const { event, data } = req.body;
switch(event) {
case 'user.created':
// Synchronize with SmartLink if needed
await syncNewUserToSmartLink(data);
break;
case 'leave.approved':
// Notify via SmartLink
await sendNotification(data.userId, 'Your leave request has been approved');
break;
case 'timesheet.submitted':
// Trigger validation workflow
await triggerValidationWorkflow(data);
break;
}
res.status(200).json({ success: true });
});
Configuration Testing
1. Connection Test
- Log out of Lucca
- Go to
https://[your-instance].ilucca.net - Click on Sign in with SSO
- Enter your work email
- Authenticate via SmartLink
- Verify access to different Lucca modules
2. Permissions Test
# Test API with SSO authentication
curl -X GET "https://[your-instance].ilucca.net/api/v3/users/me" \
-H "Authorization: lucca application=YOUR_API_KEY"
3. Mobile Testing
Lucca Mobile applications support SSO:
- Figgo Mobile (iOS/Android)
- Timmi Mobile
- Lucca Mobile (unified app)
Troubleshooting
Error "SSO Authentication Failed"
Issue: SSO authentication is not working
Solution:
- Verify that the Entity ID is
[appid]for SAML - For OIDC, check the Discovery URL
- Ensure the email exists in Lucca
- Check the logs: Configuration → Authentication Logs
Groups Not Synchronized
Issue: Lucca roles do not match SmartLink groups
Solution:
// Correct configuration of claims for groups
{
"groups_claim": "groups",
"groups_mapping": {
"smartlink-rh": "ADMIN_RH",
"smartlink-managers": "MANAGER",
"smartlink-employees": "COLLABORATEUR"
}
}
Error "User Not Authorized for This Module"
Issue: SSO user does not have access to certain modules
Solution:
- Check the licenses assigned in Lucca
- Verify the user role permissions
- Ensure the module is enabled for the user
Manager Synchronization Issue
Issue: Hierarchy is not correctly synchronized
Solution:
<!-- SAML attribute for the manager -->
<saml:Attribute Name="manager_email">
<saml:AttributeValue>manager@entreprise.fr</saml:AttributeValue>
</saml:Attribute>
Security
Recommended Configuration
{
"security_settings": {
"enforce_sso": true,
"session_timeout": "8h",
"ip_filtering": {
"enabled": true,
"allowed_ips": ["10.0.0.0/8", "192.168.0.0/16"]
},
"api_security": {
"token_rotation": "30d",
"rate_limiting": true,
"audit_api_calls": true
},
"data_protection": {
"encryption_at_rest": true,
"anonymize_exports": true,
"gdpr_compliant": true
}
}
}
GDPR Compliance
Lucca is GDPR compliant with:
- Data hosting in France
- Right to be forgotten
- Data portability
- Encryption of sensitive data
- Complete audit trail
Migration of Existing Users
Migration Script
import csv
import requests
from datetime import datetime
class LuccaSSOMigration:
def __init__(self, api_key, instance):
self.api_key = api_key
self.instance = instance
self.api_url = f"https://{instance}.ilucca.net/api/v3"
def migrate_users_to_sso(self, user_list_file):
"""Batch migration to SSO"""
results = []
with open(user_list_file, 'r', encoding='utf-8') as file:
reader = csv.DictReader(file)
for user in reader:
try:
# Enable SSO for the user
self.enable_sso_for_user(user['email'])
# Disable password authentication
self.disable_password_auth(user['id'])
# Send migration email
self.send_migration_email(user['email'])
results.append({
'email': user['email'],
'status': 'success',
'timestamp': datetime.now()
})
except Exception as e:
results.append({
'email': user['email'],
'status': 'failed',
'error': str(e)
})
return results
def enable_sso_for_user(self, email):
# Implement SSO activation via Lucca API
pass