Appendix H: B2B Sync Templates
DOCUMENT CATEGORY: Reference SCOPE: Cross-tenant sync templates PURPOSE: JSON templates for Entra ID B2B sync MASTER REFERENCE: Microsoft Learn - Cross-Tenant Sync
Status: Active
Overview
This appendix contains JSON template files for configuring Entra ID B2B Cross-Tenant Synchronization (CTS) between a management tenant and customer tenants.
These templates provision users as Member type (not Guest), enabling:
- Full RBAC/PIM support
- Seamless Azure portal experience
- Native Azure Local management capabilities
Template Files
| File | Description | Deployed To |
|---|---|---|
customer-inbound-policy.json | Cross-tenant access policy allowing CTS inbound | Customer Tenant |
management-outbound-policy.json | Cross-tenant access policy for outbound sync | Management Tenant |
cts-application.json | CTS application instantiation template | Management Tenant |
cts-credentials.json | Target tenant credentials configuration | Management Tenant |
cts-provisioning-job.json | Provisioning job with attribute mappings | Management Tenant |
cts-group-assignment.json | Group assignment to CTS configuration | Management Tenant |
Template Variables
Replace these placeholders before deployment:
| Variable | Description | Example |
|---|---|---|
{{CUSTOMER_TENANT_ID}} | Customer's Entra ID tenant ID | a1b2c3d4-e5f6-7890-abcd-ef1234567890 |
{{CUSTOMER_NAME}} | Customer name for display purposes | Infinite azurelocal Corp |
{{MGMT_TENANT_ID}} | Management tenant ID | 00000000-aaaa-bbbb-cccc-111111111111 |
{{SERVICE_PRINCIPAL_ID}} | CTS service principal ID (from app instantiation) | 12345678-1234-1234-1234-123456789abc |
{{APP_ROLE_ID}} | App role ID (from app instantiation) | 87654321-4321-4321-4321-cba987654321 |
{{JOB_ID}} | Provisioning job ID (from job creation) | abcd1234-5678-90ab-cdef-1234567890ab |
Service Groups
| Variable | Group Name | Description |
|---|---|---|
{{GROUP_ID_OPERATIONS}} | Operations | Core operations team |
{{GROUP_ID_SUPPORT}} | Support | Support team |
{{GROUP_ID_ENGINEERING}} | Engineering | Implementation engineers |
{{GROUP_ID_ADMINS}} | Admins | Administrative access |
Deployment Order
1. Customer Tenant (requires customer admin)
Deploy customer-inbound-policy.json
2. Azure Local Cloud MGMT (requires Azure Local Cloud admin)
- Add customer tenant to cross-tenant access settings
- Deploy
Azure Local Cloud-outbound-policy.json - Deploy
cts-application.json→ save SERVICE_PRINCIPAL_ID and APP_ROLE_ID - Deploy
cts-credentials.json - Deploy
cts-provisioning-job.json→ save JOB_ID - Deploy
cts-group-assignment.jsonfor each required group - Start provisioning job
Customer Inbound Policy
This policy is deployed to the Customer Tenant to allow inbound CTS from the management tenant.
{
"tenantId": "{{MGMT_TENANT_ID}}",
"b2bCollaborationInbound": {
"usersAndGroups": {
"accessType": "allowed",
"targets": [
{
"target": "AllUsers",
"targetType": "user"
}
]
},
"applications": {
"accessType": "allowed",
"targets": [
{
"target": "AllApplications",
"targetType": "application"
}
]
}
},
"b2bCollaborationOutbound": {
"usersAndGroups": {
"accessType": "blocked"
},
"applications": {
"accessType": "blocked"
}
},
"automaticUserConsentSettings": {
"inboundAllowed": true
},
"trustSettings": {
"isCompliantDeviceTrusted": true,
"isHybridAzureADJoinedDeviceTrusted": true,
"isMfaTrusted": true
},
"crossTenantSynchronization": {
"enabled": true
}
}
- b2bCollaborationInbound: Allows users and applications from Azure Local Cloud
- automaticUserConsentSettings.inboundAllowed: Auto-consents synced users
- trustSettings: Trusts MFA, compliant devices, and hybrid-joined devices
- crossTenantSynchronization.enabled: Enables CTS inbound
Management Outbound Policy
This policy is deployed to the management tenant to allow outbound sync to customer tenants.
{
"tenantId": "{{CUSTOMER_TENANT_ID}}",
"b2bCollaborationOutbound": {
"usersAndGroups": {
"accessType": "allowed",
"targets": [
{
"target": "{{GROUP_ID_OPERATIONS}}",
"targetType": "group"
},
{
"target": "{{GROUP_ID_SUPPORT}}",
"targetType": "group"
},
{
"target": "{{GROUP_ID_ENGINEERING}}",
"targetType": "group"
},
{
"target": "{{GROUP_ID_ADMINS}}",
"targetType": "group"
}
]
},
"applications": {
"accessType": "allowed",
"targets": [
{
"target": "AllApplications",
"targetType": "application"
}
]
}
},
"automaticUserConsentSettings": {
"outboundAllowed": true
},
"trustSettings": {
"isCompliantDeviceTrusted": true,
"isHybridAzureADJoinedDeviceTrusted": true,
"isMfaTrusted": true
},
"crossTenantSynchronization": {
"enabled": true
}
}
CTS Application Template
Creates the Cross-Tenant Synchronization application in the management tenant.
{
"displayName": "CTS to {{CUSTOMER_NAME}}",
"description": "Cross-Tenant Synchronization application for automated user provisioning to {{CUSTOMER_NAME}}",
"signInAudience": "AzureADMultipleOrgs",
"web": {
"redirectUris": [],
"logoutUrl": null,
"implicitGrantSettings": {
"enableAccessTokenIssuance": false,
"enableIdTokenIssuance": false
}
},
"requiredResourceAccess": [
{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess": [
{
"id": "5b567255-7703-4780-807c-7be8301ae99b",
"type": "Role"
},
{
"id": "df021288-bdef-4463-88db-98f22de89214",
"type": "Role"
}
]
}
]
}
CTS Credentials Template
Configures target tenant credentials for the provisioning job.
{
"value": [
{
"key": "TargetTenantId",
"value": "{{CUSTOMER_TENANT_ID}}"
}
]
}
CTS Provisioning Job Template
Defines the synchronization rules and attribute mappings.
{
"templateId": "Azure2Azure",
"code": "CTS-{{CUSTOMER_NAME}}",
"description": "Cross-Tenant Synchronization provisioning job to {{CUSTOMER_NAME}}",
"enabled": true,
"sourceIdentity": {
"type": "AzureActiveDirectory",
"id": "{{MGMT_TENANT_ID}}"
},
"targetIdentity": {
"type": "AzureActiveDirectory",
"id": "{{CUSTOMER_TENANT_ID}}"
},
"synchronizationRules": [
{
"name": "USER_OUTBOUND_USER",
"sourceDirectory": "AzureActiveDirectory",
"targetDirectory": "AzureActiveDirectory",
"objectMappings": [
{
"sourceObjectName": "User",
"targetObjectName": "User",
"attributeMappings": [
{
"source": { "name": "userPrincipalName", "type": "Attribute" },
"target": { "name": "userPrincipalName", "type": "Attribute" },
"applyOnce": false
},
{
"source": { "name": "displayName", "type": "Attribute" },
"target": { "name": "displayName", "type": "Attribute" },
"applyOnce": false
},
{
"source": { "name": "mail", "type": "Attribute" },
"target": { "name": "mail", "type": "Attribute" },
"applyOnce": false
},
{
"source": { "value": "true", "type": "Constant" },
"target": { "name": "showInAddressList", "type": "Attribute" },
"applyOnce": false
},
{
"source": { "value": "Member", "type": "Constant" },
"target": { "name": "userType", "type": "Attribute" },
"applyOnce": true
}
]
}
]
}
]
}
The userType: Member constant ensures synced users get full portal access, RBAC, and PIM eligibility - not limited Guest access.
Deployment Commands
Replace Variables
# Replace variables (example using sed)
sed -e 's/{{CUSTOMER_TENANT_ID}}/actual-tenant-id/g' \
-e 's/{{CUSTOMER_NAME}}/CustomerName/g' \
customer-inbound-policy.json > customer-inbound-policy-deploy.json
Deploy Using Azure CLI
# Deploy cross-tenant access policy
az rest --method PATCH \
--url "https://graph.microsoft.com/v1.0/policies/crossTenantAccessPolicy/partners/{{CUSTOMER_TENANT_ID}}" \
--body '@customer-inbound-policy-deploy.json' \
--headers Content-Type=application/json
Deploy Using PowerShell
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "Policy.ReadWrite.CrossTenantAccess"
# Update cross-tenant access policy
$policy = Get-Content -Path "customer-inbound-policy-deploy.json" | ConvertFrom-Json
Update-MgPolicyCrossTenantAccessPolicyPartner -CrossTenantAccessPolicyConfigurationPartnerTenantId $CustomerTenantId -BodyParameter $policy
Verification
Check Sync Status
# Get provisioning job status
Get-MgServicePrincipalSynchronizationJob -ServicePrincipalId $ServicePrincipalId
# Get provisioning logs
Get-MgAuditLogProvisioning -Filter "jobId eq '$JobId'" -Top 10
Verify User Sync
# In customer tenant - check synced users
Get-MgUser -Filter "userType eq 'Member' and creationType eq 'Invitation'" | Select-Object DisplayName, UserPrincipalName, UserType
Troubleshooting
Sync Not Starting
- Verify cross-tenant access policies on both tenants
- Check CTS is enabled in both policies
- Verify group assignments include target groups
- Check provisioning job is enabled
Users Not Appearing as Members
- Verify
userType: Memberin attribute mappings - Check
applyOnce: truefor userType (prevents overwrite) - Re-provision affected users
Permission Errors
- Verify Microsoft Graph API permissions granted
- Check admin consent provided
- Verify service principal has required roles