Skip to main content

Whaller

This guide explains how to set up Single Sign-On (SSO) between SmartLink and Whaller using SAML 2.0.

Prerequisites

  • Whaller Business or Enterprise subscription
  • Administrative access to Whaller
  • Verified email domain in Whaller
  • Application configured in SmartLink with SAML2

Note: SSO is only available with Whaller's Business and Enterprise plans.

1. Create the application

  1. Log in to SmartLink as an administrator
  2. Go to ApplicationsAdd
  3. Create a new application:
    • Name: Whaller
    • URL: https://[your-organization].whaller.com
    • Description: Secure enterprise social network
    • Icon: Choose the Whaller icon

2. Configure SAML2

  1. In the Authentication tab
  2. Select SAML2
  3. Configure the following parameters:
    • Entity ID: [appid]
    • ACS URL: https://[your-organization].whaller.com/saml/acs
    • Format NameID: emailAddress
    • App ID: [appid] (automatically generated unique identifier)

3. Retrieve the metadata

Note the following URLs:

  • IdP Metadata: https://[your-smartlink].link.vaultys.org/api/saml2/[appid]/metadata
  • SSO URL: https://[your-smartlink].link.vaultys.org/api/saml2/[appid]/sso
  • SLO URL: https://[your-smartlink].link.vaultys.org/api/saml2/[appid]/slo
  • Entity ID: [appid]
  • X.509 Certificate: Download from SmartLink

Configuration in Whaller

1. Access SSO settings

  1. Log in to Whaller as an administrator
  2. Go to AdministrationSettingsAuthentication
  3. In the SSO SAML section, click on Configure

2. Identity provider configuration

Configure the SAML parameters:

  • IdP Entity ID: [appid]
  • SSO URL: https://[your-smartlink].link.vaultys.org/api/saml2/[appid]/sso
  • SLO URL: https://[your-smartlink].link.vaultys.org/api/saml2/[appid]/slo
  • X.509 Certificate: Paste the certificate from SmartLink
  • Binding: HTTP-POST

3. Attribute configuration

Whaller AttributeSAML AttributeRequired
Emailemail
First NamefirstName
Last NamelastName
Display NamedisplayName
Servicedepartment
Job Titletitle
Managermanager
Locationlocation

4. Domain configuration

  1. In Allowed Domains
  2. Add your company domains
  3. Enable Force SSO for these domains

Sphere and Permissions Configuration

Sphere Types

spheres:
- type: "corporate"
name: "Enterprise"
visibility: "public"
auto_add_users: true
moderation: true
features:
- news
- events
- documents
- messages

- type: "project"
name: "Projects"
visibility: "private"
invitation_only: true
features:
- tasks
- calendar
- documents
- chat

- type: "community"
name: "Communities"
visibility: "discoverable"
join_approval: true
features:
- discussions
- polls
- ideas
- wiki

Roles and Permissions

{
"roles": {
"admin": {
"permissions": [
"manage_spheres",
"manage_users",
"manage_settings",
"view_analytics",
"export_data"
],
"saml_groups": ["smartlink-whaller-admins"]
},
"manager": {
"permissions": [
"create_spheres",
"moderate_content",
"invite_users",
"manage_sphere_settings"
],
"saml_groups": ["smartlink-managers"]
},
"contributor": {
"permissions": [
"create_content",
"comment",
"share",
"upload_files"
],
"saml_groups": ["smartlink-users"]
},
"reader": {
"permissions": [
"view_content",
"react",
"download_files"
],
"saml_groups": ["smartlink-external", "smartlink-guests"]
}
}
}

Group Synchronization

<!-- SAML Assertion for groups -->
<saml:Attribute Name="groups">
<saml:AttributeValue>smartlink-whaller-admins</saml:AttributeValue>
<saml:AttributeValue>smartlink-department-hr</saml:AttributeValue>
<saml:AttributeValue>smartlink-project-alpha</saml:AttributeValue>
</saml:Attribute>

Specific Features

Security and Privacy

{
"security_features": {
"encryption": {
"at_rest": "AES-256",
"in_transit": "TLS 1.3",
"end_to_end": true
},
"data_sovereignty": {
"hosting": "France",
"no_third_party_access": true,
"gdpr_compliant": true
},
"content_control": {
"watermark": true,
"download_restrictions": true,
"copy_protection": false,
"expiring_content": true
},
"audit": {
"access_logs": true,
"activity_tracking": true,
"export_logs": true
}
}
}

Document Management

documents:
storage:
quota_per_sphere: "50GB"
quota_per_user: "10GB"
max_file_size: "2GB"

versioning:
enabled: true
max_versions: 10
auto_cleanup: "after_90_days"

collaboration:
co_editing: true
commenting: true
approval_workflow: true

supported_formats:
- documents: [".pdf", ".doc", ".docx", ".odt"]
- spreadsheets: [".xls", ".xlsx", ".ods"]
- presentations: [".ppt", ".pptx", ".odp"]
- images: [".jpg", ".png", ".gif", ".svg"]
- videos: [".mp4", ".avi", ".mov"]

Analytics and Reporting

{
"analytics": {
"dashboard": {
"active_users": "daily/weekly/monthly",
"content_creation": "posts/comments/files",
"engagement_rate": "views/interactions",
"sphere_activity": "per_sphere_metrics"
},
"reports": {
"user_activity": {
"frequency": "weekly",
"format": "pdf",
"recipients": ["admins"]
},
"content_moderation": {
"frequency": "daily",
"auto_flag": true,
"ai_assistance": true
},
"compliance": {
"gdpr_report": "monthly",
"audit_trail": "continuous",
"data_retention": "automated"
}
}
}
}

Whaller API

Client API with SSO Authentication

import requests
from datetime import datetime

class WhallerAPI:
def __init__(self, domain, api_key):
self.base_url = f"https://{domain}.whaller.com/api/v2"
self.headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}

def get_user_by_sso_email(self, email):
"""Get a user by their SSO email"""
response = requests.get(
f"{self.base_url}/users",
params={'email': email},
headers=self.headers
)
return response.json()

def create_sphere(self, name, sphere_type, members):
"""Create a new sphere"""
data = {
'name': name,
'type': sphere_type,
'members': members,
'settings': {
'moderation': True,
'invitation_only': False
}
}
response = requests.post(
f"{self.base_url}/spheres",
json=data,
headers=self.headers
)
return response.json()

def post_message(self, sphere_id, content, attachments=None):
"""Post a message in a sphere"""
data = {
'content': content,
'attachments': attachments or [],
'visibility': 'all_members'
}
response = requests.post(
f"{self.base_url}/spheres/{sphere_id}/messages",
json=data,
headers=self.headers
)
return response.json()

Webhooks

// Whaller webhooks configuration
app.post('/webhook/whaller', async (req, res) => {
const { event, data } = req.body;
const signature = req.headers['x-whaller-signature'];

// Verify the signature
if (!verifyWhallerSignature(signature, req.body)) {
return res.status(401).json({ error: 'Invalid signature' });
}

switch(event) {
case 'user.created':
await handleNewUser(data);
break;

case 'sphere.created':
await syncSphereToExternalTools(data);
break;

case 'message.posted':
await processNewMessage(data);
break;

case 'document.uploaded':
await scanDocument(data);
break;

case 'user.deactivated':
await handleUserDeactivation(data);
break;
}

res.status(200).json({ received: true });
});

Configuration Testing

1. Connection Test

  1. Log out of Whaller
  2. Go to https://[your-organization].whaller.com
  3. Click on SSO Login
  4. Enter your company email
  5. You are redirected to SmartLink
  6. After authentication, you access Whaller

2. Permission Verification

# Test via API
curl -X GET "https://[your-organization].whaller.com/api/v2/me" \
-H "Authorization: Bearer YOUR_API_TOKEN"

3. Mobile Testing

Available Whaller applications:

  • Whaller iOS (App Store)
  • Whaller Android (Google Play)
  • Full SSO support on mobile

Troubleshooting

"SAML assertion invalid" Error

Issue: The SAML assertion is rejected

Solution:

  1. Verify that the Entity ID is [appid]
  2. Check the X.509 certificate format
  3. Ensure the ACS URL is: https://[your-organization].whaller.com/saml/acs
  4. Check the logs: AdministrationLogsSSO

Users Not Created Automatically

Issue: Automatic provisioning is not working

Solution:

  1. Check that auto-provisioning is enabled in Whaller
  2. Ensure that the required attributes are present:
    • email
    • firstName
    • lastName
  3. Verify that the email domain is allowed

Sphere Access Issue

Issue: SSO user does not have access to the correct spheres

Solution:

  1. Check SAML group synchronization
  2. Review automatic assignment rules
  3. Verify sphere permissions
  4. Ensure the user is active

Timeout Error

Issue: SSO connection expires too quickly

Solution:

  1. Increase the SAML assertion validity period (5-10 minutes)
  2. Verify clock synchronization between servers
  3. Configure the ClockSkew parameter in Whaller

Security

{
"security_settings": {
"enforce_sso": true,
"session_duration": "8h",
"idle_timeout": "30m",
"ip_filtering": {
"enabled": false,
"whitelist": []
},
"password_policy": {
"min_length": 12,
"require_special": true,
"require_numbers": true,
"rotation": "90d"
},
"data_protection": {
"encryption": "AES-256",
"key_management": "HSM",
"backup": "daily",
"retention": "7y"
}
}
}

Compliance

  • GDPR: Fully compliant, hosted in France
  • SecNumCloud: Qualification in progress
  • ISO 27001: Certified
  • HDS: Accredited Health Data Host

User Migration

Migration Script

import csv
from whaller_api import WhallerAPI
import logging

class WhallerSSOMigration:
def __init__(self, domain, api_key):
self.api = WhallerAPI(domain, api_key)
self.logger = logging.getLogger(__name__)

def migrate_users(self, csv_file):
"""Migrate users to SSO"""
results = []

with open(csv_file, 'r', encoding='utf-8') as file:
reader = csv.DictReader(file)

for user in reader:
try:
# Search for the user
existing_user = self.api.get_user_by_email(user['email'])

if existing_user:
# Enable SSO
self.api.enable_sso(existing_user['id'])

# Update groups
self.api.update_user_groups(
existing_user['id'],
user['groups'].split(',')
)

results.append({
'email': user['email'],
'status': 'migrated'
})
else:
# Create with SSO
self.api.create_sso_user(user)
results.append({
'email': user['email'],
'status': 'created'
})

except Exception as e:
self.logger.error(f"Migration error for {user['email']}: {e}")
results.append({
'email': user['email'],
'status': 'error',
'message': str(e)
})

return results

Resources