HubSpot
This guide explains how to set up Single Sign-On (SSO) between SmartLink and HubSpot using SAML 2.0.
Prerequisites
- HubSpot Enterprise (Marketing Hub, Sales Hub, Service Hub, or CMS Hub)
- Super Admin access to HubSpot
- Verified email domain in HubSpot
- Application configured in SmartLink with SAML2
Note: SAML SSO is available only with HubSpot Enterprise plans.
Configuration in SmartLink
1. Create the application
- Log in to SmartLink as an administrator
- Go to Applications → Add
- Create a new application:
- Name: HubSpot
- URL:
https://app.hubspot.com - Description: CRM and marketing automation platform
- Icon: Choose the HubSpot icon
2. Configure SAML2
- In the Authentication tab
- Select SAML2
- Configure the following parameters:
- Entity ID:
https://[your-smartlink].link.vaultys.org/[appid] - ACS URL:
https://app.hubspot.com/login/saml - Format NameID:
emailAddress - App ID:
[appid](automatically generated unique identifier)
- Entity ID:
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/sso/[appid] - SLO URL:
https://[your-smartlink].link.vaultys.org/api/saml2/slo/[appid] - Entity ID:
https://[your-smartlink].link.vaultys.org/[appid] - X.509 Certificate: Download from SmartLink
Configuration in HubSpot
1. Access SSO settings
- Log in to HubSpot as a Super Admin
- Click on the Settings icon (⚙️)
- In the left menu: Account Defaults → Security
- Click on the Single Sign-On tab
2. Identity Provider configuration
Click on Configure SSO and fill in:
Identity Provider Settings
- Identity Provider Single Sign-On URL:
https://[your-smartlink].link.vaultys.org/api/saml2/sso/[appid] - Identity Provider Identifier:
[appid] - Verification Certificate: Paste the X.509 certificate from SmartLink
Service Provider Settings (provided by HubSpot)
Note these values to configure in SmartLink if necessary:
- Audience URI (SP Entity ID):
https://api.hubspot.com - Sign on URL:
https://app.hubspot.com/login/saml
3. Attribute configuration
Configure the SAML attribute mapping:
| HubSpot Attribute | SAML Attribute | Required |
|---|---|---|
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress | ✅ | |
| First Name | http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname | ✅ |
| Last Name | http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname | ✅ |
| Groups | groups | ❌ |
4. Domain configuration
- In Security → Login Verification
- Add your company domains
- Enable Require SSO for these domains
Team and Permissions Configuration
Team Structure
{
"teams": {
"Sales": {
"permissions": ["contacts:read", "contacts:write", "deals:read", "deals:write"],
"saml_group": "smartlink-sales"
},
"Marketing": {
"permissions": ["marketing:all", "content:write", "campaigns:manage"],
"saml_group": "smartlink-marketing"
},
"Service": {
"permissions": ["tickets:all", "feedback:read", "knowledge:write"],
"saml_group": "smartlink-support"
},
"Admin": {
"permissions": ["super-admin"],
"saml_group": "smartlink-hubspot-admins"
}
}
}
Custom Roles
Create roles in HubSpot:
- Settings → Users & Teams → Roles
- Create roles corresponding to your SmartLink groups
- Assign appropriate permissions
Partitions (HubSpot Enterprise)
To isolate data between teams:
partitions:
- name: "EMEA Sales"
teams: ["sales-emea"]
objects: ["contacts", "companies", "deals"]
- name: "Americas Sales"
teams: ["sales-americas"]
objects: ["contacts", "companies", "deals"]
- name: "Marketing Global"
teams: ["marketing"]
objects: ["marketing-emails", "workflows", "forms"]
Configuration Testing
1. Connection Test
- Open a private browsing window
- Go to app.hubspot.com
- Click on Log in with SSO
- Enter your company email
- You will be redirected to SmartLink
- After authentication, you will access HubSpot
2. Permissions Test
// Test via the HubSpot API
const hubspot = require('@hubspot/api-client');
const hubspotClient = new hubspot.Client({
accessToken: process.env.HUBSPOT_ACCESS_TOKEN
});
async function testPermissions() {
try {
// Test reading contacts
const contacts = await hubspotClient.crm.contacts.basicApi.getPage();
console.log('Contacts access: ✓');
// Test deal creation
const deal = await hubspotClient.crm.deals.basicApi.create({
properties: {
dealname: 'Test SSO Deal',
amount: '1000'
}
});
console.log('Deal creation: ✓');
} catch (error) {
console.error('Permission denied:', error.message);
}
}
3. Mobile Verification
HubSpot mobile apps support SSO:
- HubSpot Mobile App
- HubSpot Keyboard (iOS)
- HubSpot CRM Scanner
Integration with Workflows
Authentication-Based Triggers
// Custom workflow triggered on SSO login
{
"trigger": {
"type": "user_login",
"conditions": {
"auth_method": "saml",
"user_group": "smartlink-new-users"
}
},
"actions": [
{
"type": "send_email",
"template": "welcome_sso_user",
"to": "{{user.email}}"
},
{
"type": "assign_onboarding_tasks",
"tasks": ["complete_profile", "watch_training", "setup_signature"]
}
]
}
Automations with SSO Groups
# Script to automatically assign leads
def assign_leads_by_sso_group(user_email, sso_groups):
if 'smartlink-sales-emea' in sso_groups:
assign_to_team('EMEA Sales', user_email)
elif 'smartlink-sales-americas' in sso_groups:
assign_to_team('Americas Sales', user_email)
else:
assign_to_team('Global Sales Pool', user_email)
Integration Configuration
HubSpot App Marketplace
Apps in the marketplace work with SSO:
{
"marketplace_apps": {
"salesforce": {
"sso_compatible": true,
"additional_auth": "oauth2"
},
"slack": {
"sso_compatible": true,
"workspace_linking": true
},
"zoom": {
"sso_compatible": true,
"calendar_sync": true
}
}
}
Webhooks and API
Webhooks configuration with SSO authentication:
// Secure webhook endpoint
app.post('/webhooks/hubspot', verifyHubSpotSignature, async (req, res) => {
const { subscriptionType, objectId, propertyName, propertyValue } = req.body;
// Check user permissions via SSO
const user = await getUserFromWebhook(req);
if (!hasPermission(user, subscriptionType)) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
// Process the webhook
await processWebhook(req.body);
res.status(200).send();
});
Troubleshooting
"Invalid SAML Response" Error
Issue: The SAML response is invalid
Solution:
- Verify that the Entity ID is
[appid]in SmartLink - Check the X.509 certificate (PEM format, without header/footer)
- Ensure the ACS URL is:
https://app.hubspot.com/login/saml - Check the logs in HubSpot: Settings → Audit Logs
"User not authorized for this account" Error
Issue: The user does not have access to the HubSpot account
Solution:
- Verify that the email domain is added and verified
- Ensure the user is provisioned in HubSpot
- Check the user's permissions in Users & Teams
Teams Not Assigned
Issue: Users are not in the correct teams
Solution:
<!-- Correct format of SAML assertion for groups -->
<saml:Attribute Name="groups">
<saml:AttributeValue>smartlink-hubspot-sales</saml:AttributeValue>
<saml:AttributeValue>smartlink-hubspot-emea</saml:AttributeValue>
</saml:Attribute>
Issues with Mobile Applications
Issue: Unable to connect via the mobile app
Solution:
- Ensure Allow mobile SSO option is enabled
- Use the in-app browser, not an external browser
- Verify that the SSL certificate is valid and recognized
Security
Recommended Configuration
{
"security_settings": {
"enforce_sso": true,
"session_timeout": "12h",
"require_2fa_for_api": true,
"ip_restrictions": {
"enabled": true,
"allowed_ips": ["203.0.113.0/24"]
},
"api_key_rotation": "90d",
"audit_log_retention": "2y",
"sensitive_data_masking": true
}
}
Compliance
- GDPR: HubSpot is GDPR compliant with available DPA
- SOC 2 Type II: Certification available
- ISO 27001: Certified
- Privacy Shield: EU-US/Swiss-US Framework
Backup and Recovery
Recovery plan in case of SSO issues:
- Backup Super Admin Account with local authentication
- API keys for emergency programmatic access
- Documentation of recovery procedures
- Contact HubSpot Enterprise support: 24/7 priority support
User Migration
Batch Migration Script
import pandas as pd
from hubspot import HubSpot
from datetime import datetime
def migrate_users_to_sso(csv_file):
"""Bulk migration to SSO"""
api_client = HubSpot(access_token=ADMIN_TOKEN)
users_df = pd.read_csv(csv_file)
migration_report = []
for index, user in users_df.iterrows():
try:
# Disable password authentication
api_client.settings.users.update(
user_id=user['user_id'],
properties={
'authentication_method': 'saml_only',
'password_login_enabled': False
}
)
# Send notification
send_migration_email(user['email'])
migration_report.append({
'user': user['email'],
'status': 'success',
'timestamp': datetime.now()
})
except Exception as e:
migration_report.append({
'user': user['email'],
'status': 'failed',
'error': str(e)
})
return pd.DataFrame(migration_report)