Portal Community

ExternalClaimsMapper

// ExternalClaimsMapper — converts ExternalIdentityClaims → IDInfo
public sealed class ExternalClaimsMapper
{
    public IDInfo MapToIDInfo(
        ExternalIdentityClaims external,
        FederationProviderConfig config)
    {
        // Map external groups to BizFirstGO role names
        var roles = external.Groups
            .Select(g => config.GroupMapping.TryGetValue(g, out var role) ? role : null)
            .Where(r => r is not null)
            .Select(r => r!)
            .Distinct()
            .ToList();

        // Determine tenant ID
        var tenantId = config.TenantIdConfig.Source switch
        {
            TenantIdSource.Static  => config.TenantIdConfig.Value,
            TenantIdSource.Claim   => external.RawClaims.GetValueOrDefault(config.TenantIdConfig.ClaimName) ?? "",
            TenantIdSource.Mapping => config.TenantIdConfig.TenantMapping
                .GetValueOrDefault(external.RawClaims.GetValueOrDefault(config.TenantIdConfig.ClaimName) ?? "") ?? "",
            _ => ""
        };

        return new IDInfo
        {
            UserId      = external.UserId,
            TenantId    = tenantId,
            Email       = external.Email,
            DisplayName = external.DisplayName ?? external.Email,
            Roles       = roles,
            IsServiceAccount = false
        };
    }
}

Claims Mapping Reference

BizFirstGO IDInfoPassportOktaAzure ADAuth0Keycloak
UserIdsubsuboidsubsub
TenantIdtenant_idtenant_idstatic mapping from tidhttps://bfgo.com/tenant_idtenant_id
Emailemailemailemail or upnemailemail
DisplayNamenamenamenamenamename
Rolesroles[]groups[] → mappedroles[] → mappedhttps://bfgo.com/roles[]realm_roles[] → mapped

Tenant ID Resolution Strategies

The most critical claim to map correctly is TenantId. BizFirstGO offers three resolution strategies:

StrategyConfigUse Case
Static"source": "static", "value": "tenant-abc"Single-tenant deployment where all users belong to one BizFirstGO tenant
Claim"source": "claim", "claimName": "tenant_id"Multi-tenant — each user has a tenant_id custom attribute in the IdP
Mapping Table"source": "mapping", "claimName": "tid", "tenantMapping": {...}Map Azure AD tenant IDs or Okta org IDs to BizFirstGO tenant IDs
// Example: mapping Azure AD tenant ID → BizFirstGO tenant ID
{
  "tenantIdConfig": {
    "source": "mapping",
    "claimName": "tid",
    "tenantMapping": {
      "aad-tenant-id-company-a": "tenant-abc",
      "aad-tenant-id-company-b": "tenant-def",
      "aad-tenant-id-company-c": "tenant-ghi"
    }
  }
}
Unmapped Groups Are Silently Ignored

If an external group is not in the groupMapping or roleMapping table, it is silently ignored — no error, no BizFirstGO role. A user who only has unmapped groups will have no BizFirstGO roles and will likely be denied access. Always audit your group mapping table after changes to the external IdP's group structure.