Skip to content

Identity & SSO: SAML, OAuth, and Access Management

Identity management is how you answer “who is this user and what can they do?” across an enterprise ecosystem. For CTA scenarios, you must design end-to-end identity solutions that span Salesforce, external systems, portals, and mobile apps — selecting the right protocols, flows, and configurations.

Identity Architecture Overview

flowchart LR
    subgraph "Identity Layer"
        IdP["Identity Provider\n(Who authenticates)"]
        SP["Service Provider\n(Who trusts the IdP)"]
        AuthZ["Authorization Server\n(Who grants access)"]
    end

    subgraph "Protocols"
        SAML["SAML 2.0\n(Web SSO)"]
        OAuth["OAuth 2.0\n(API Authorization)"]
        OIDC["OpenID Connect\n(Authentication + OAuth)"]
    end

    subgraph "Salesforce Features"
        MyDomain["My Domain"]
        CA["Connected Apps"]
        NC["Named Credentials"]
        MFA2["MFA"]
        JIT["JIT Provisioning"]
    end

    IdP --> SAML
    IdP --> OIDC
    SP --> SAML
    AuthZ --> OAuth
    AuthZ --> OIDC
    SAML --> MyDomain
    OAuth --> CA
    OIDC --> CA

    style IdP fill:#1565c0,color:#fff
    style AuthZ fill:#2e7d32,color:#fff
    style SP fill:#e65100,color:#fff

SAML 2.0 Deep Dive

SAML (Security Assertion Markup Language) is the standard for web-based single sign-on. In enterprise Salesforce deployments, SAML is almost always part of the architecture.

SAML Roles

RoleWho Plays ItWhat It Does
Identity Provider (IdP)Corporate IdP (Okta, Azure AD, ADFS, Ping)Authenticates the user, issues SAML assertions
Service Provider (SP)SalesforceTrusts the IdP’s assertion, grants access
PrincipalThe userRequests access, gets redirected

SAML SSO Flow

sequenceDiagram
    participant User
    participant Browser
    participant SF as Salesforce (SP)
    participant IdP as Identity Provider

    User->>Browser: Navigate to Salesforce URL
    Browser->>SF: GET /login
    SF->>Browser: 302 Redirect to IdP (SAML AuthnRequest)
    Browser->>IdP: GET /sso (with AuthnRequest)
    IdP->>IdP: Authenticate user (credentials, MFA)
    IdP->>Browser: POST SAML Response (signed assertion)
    Browser->>SF: POST /saml/SSO (SAML Response)
    SF->>SF: Validate signature, extract attributes
    SF->>SF: Match user (Federation ID, Username, etc.)
    SF->>Browser: 302 Redirect to Salesforce home
    Browser->>User: Salesforce session established

SAML Configuration Decisions

DecisionOptionsRecommendation
SP-initiated vs IdP-initiatedSP-initiated (user goes to SF first) or IdP-initiated (user starts at IdP portal)Support both — SP-initiated for bookmarks, IdP-initiated for portal
User matchingFederation ID, Username, or Custom attributeFederation ID — decouples from Salesforce username changes
JIT provisioningStandard JIT or Custom JIT (Apex handler)Custom JIT when you need to set profile/role/permission sets dynamically
Single LogoutEnabled or disabledEnable — prevents orphaned sessions across systems
CertificateIdP cert in Salesforce, SF cert for signed requestsAlways validate IdP certificate; sign AuthnRequests for sensitive orgs

Salesforce as Identity Provider

Salesforce can also act as the IdP, authenticating users for other SPs.

ScenarioUse Case
SF as IdP to custom appsInternal tools that need SF user authentication
SF as IdP to partner portalsPartners authenticate via Salesforce credentials
SF as IdP in multi-orgOne SF org authenticates users for other SF orgs
SF as IdP with Connected AppsExternal apps use SF login for SSO

CTA Pattern: IdP vs SP Decision

When the scenario has an existing corporate IdP (Okta, Azure AD, ADFS), Salesforce should be the SP. When Salesforce is the system of record for users (common in customer-facing portals), Salesforce can be the IdP. In multi-org scenarios, designate one org as the IdP.

OAuth 2.0 Flows

OAuth 2.0 is the authorization framework for API access. Each flow is designed for a specific use case — choosing the wrong flow creates security vulnerabilities.

OAuth Flow Selection

flowchart TD
    Start["What type of client\nneeds API access?"] --> Q1{"Is there a\nhuman user?"}

    Q1 -->|Yes| Q2{"Is it a web app\nwith a server?"}
    Q1 -->|No| Q3{"Is it a\nserver-to-server\nintegration?"}

    Q2 -->|Yes| AuthCode["Authorization Code Flow\n(+ PKCE recommended)"]
    Q2 -->|No| Q4{"Is it a mobile\nor SPA app?"}

    Q4 -->|Yes| AuthCodePKCE["Authorization Code Flow\nwith PKCE (required)"]
    Q4 -->|No| Device["Device Flow\n(CLI tools, IoT)"]

    Q3 -->|Yes| Q5{"Does the server have\na certificate/key?"}
    Q5 -->|Yes| JWT["JWT Bearer Flow"]
    Q5 -->|No| ClientCred["Client Credentials Flow"]

    Q1 -.->|"Already have\nSAML assertion"| SAMLBearer["SAML Bearer Flow"]

    style AuthCode fill:#2e7d32,color:#fff
    style AuthCodePKCE fill:#2e7d32,color:#fff
    style JWT fill:#1565c0,color:#fff
    style ClientCred fill:#1565c0,color:#fff
    style SAMLBearer fill:#e65100,color:#fff
    style Device fill:#4a148c,color:#fff

Flow 1: Authorization Code

The standard web server flow for applications with a backend.

sequenceDiagram
    participant User
    participant App as Web Application
    participant SF as Salesforce

    User->>App: Click "Login with Salesforce"
    App->>SF: GET /authorize (client_id, redirect_uri, scope)
    SF->>User: Login page + consent screen
    User->>SF: Enter credentials + approve
    SF->>App: 302 Redirect with authorization code
    App->>SF: POST /token (code + client_secret)
    SF->>App: Access token + refresh token
    App->>SF: API calls with access token

When to use: Web applications with a secure backend server that can store the client secret.

Security considerations: The client secret must never be exposed to the browser. Always use HTTPS for redirect URIs.

Flow 2: Authorization Code with PKCE

Enhanced authorization code flow for public clients (mobile apps, SPAs) that cannot securely store a client secret.

sequenceDiagram
    participant User
    participant App as Mobile/SPA App
    participant SF as Salesforce

    App->>App: Generate code_verifier + code_challenge
    App->>SF: GET /authorize (client_id, code_challenge, redirect_uri)
    SF->>User: Login page + consent screen
    User->>SF: Approve
    SF->>App: 302 Redirect with authorization code
    App->>SF: POST /token (code + code_verifier)
    SF->>SF: Verify code_verifier matches code_challenge
    SF->>App: Access token + refresh token

When to use: Mobile apps, single-page applications, desktop apps — any client that cannot securely store secrets.

Flow 3: JWT Bearer

Server-to-server authentication using a signed JWT. No user interaction required.

sequenceDiagram
    participant Server as Integration Server
    participant SF as Salesforce

    Server->>Server: Create JWT (iss=client_id, sub=username, aud=login.salesforce.com)
    Server->>Server: Sign JWT with private key
    Server->>SF: POST /token (grant_type=jwt-bearer, assertion=signed_JWT)
    SF->>SF: Validate JWT signature with stored public cert
    SF->>SF: Verify claims (issuer, subject, audience, expiry)
    SF->>Server: Access token (no refresh token)

When to use: Backend integrations, middleware (MuleSoft, Dell Boomi), scheduled jobs that run as a specific user.

Key details:

  • Requires pre-authorized Connected App with uploaded certificate
  • The sub claim specifies which Salesforce user to impersonate
  • No refresh token is issued — generate a new JWT when the access token expires
  • The Connected App must have “Use digital signatures” enabled

Flow 4: Client Credentials

Server-to-server flow where the integration authenticates as itself, not as a specific user.

sequenceDiagram
    participant Server as Integration Server
    participant SF as Salesforce

    Server->>SF: POST /token (grant_type=client_credentials, client_id, client_secret)
    SF->>SF: Validate credentials
    SF->>SF: Run as the Connected App's designated user
    SF->>Server: Access token

When to use: Service-to-service integrations where no specific user context is needed. The integration runs as the Connected App’s execution user.

Client Credentials Limitations

  • Introduced in Winter ‘23 (API v56.0), broadly GA in Summer ‘23 (v58.0)
  • Runs as the Connected App’s execution user — all CRUD/FLS applies to that user
  • No refresh token issued
  • Must be explicitly enabled on the Connected App

Flow 5: SAML Bearer

Exchanges a SAML assertion for an OAuth access token. Bridges SAML-based SSO with API access.

sequenceDiagram
    participant App as Application
    participant IdP as SAML IdP
    participant SF as Salesforce

    App->>IdP: Request SAML assertion
    IdP->>App: SAML assertion (signed)
    App->>SF: POST /token (grant_type=saml2-bearer, assertion=SAML)
    SF->>SF: Validate SAML assertion
    SF->>App: Access token

When to use: When you already have SAML infrastructure and need API access without re-authenticating the user. Common in enterprise middleware scenarios.

Flow 6: Device Flow

For devices with limited input capabilities (IoT devices, CLI tools, smart TVs).

sequenceDiagram
    participant Device
    participant User
    participant SF as Salesforce

    Device->>SF: POST /token (grant_type=device_code)
    SF->>Device: device_code + user_code + verification_url
    Device->>User: Display "Go to URL, enter code: ABCD-1234"
    User->>SF: Navigate to URL, enter code, login, approve
    loop Poll for token
        Device->>SF: POST /token (device_code)
        SF->>Device: authorization_pending (or access_token)
    end
    SF->>Device: Access token + refresh token

When to use: IoT devices, CLIs, TVs, kiosks — any device where typing credentials is impractical.

OAuth Flow Comparison

FlowUser InteractionClient SecretRefresh TokenBest For
Authorization CodeYesYes (server-side)YesWeb apps with backend
Auth Code + PKCEYesNoYesMobile, SPA
JWT BearerNoNo (uses cert)NoServer-to-server
Client CredentialsNoYesNoService accounts
SAML BearerNo (uses existing SAML)NoNoSAML-to-OAuth bridge
DeviceYes (separate device)NoYesIoT, CLI

OpenID Connect (OIDC)

OpenID Connect adds an authentication layer on top of OAuth 2.0, providing an ID token (JWT) with user identity information. Use SAML 2.0 for enterprise web SSO with existing IdPs, OAuth 2.0 for API-only authorization, and OIDC for modern web/mobile apps needing both login and API access.

CTA Decision Framework

  • Enterprise web SSO with existing IdP: SAML 2.0
  • API access for integrations: OAuth 2.0 (JWT Bearer or Client Credentials)
  • Modern web/mobile app needing both login and API: OpenID Connect
  • Legacy system integration: SAML Bearer to bridge to OAuth

Multi-IdP and Hub-and-Spoke SSO Patterns

Enterprise scenarios often involve multiple identity providers — different business units, acquired companies, or partner organizations each with their own IdP. The CTA board expects you to know these advanced patterns.

Multi-IdP Routing Architecture

flowchart TD
    User["User navigates to\nSalesforce My Domain"] --> LD["Login Discovery Page\n(My Domain login handler)"]
    LD --> Route{"Route based on\nemail domain or\nuser attribute"}
    Route -->|"@corp-hq.com"| IdP1["Corporate IdP\n(Azure AD)"]
    Route -->|"@acquired-co.com"| IdP2["Acquired Company IdP\n(Okta)"]
    Route -->|"@partner.com"| IdP3["Partner IdP\n(ADFS)"]
    Route -->|"No SSO match"| Direct["Direct Salesforce Login\n(+ MFA)"]

    IdP1 -->|"SAML Assertion"| SF["Salesforce\n(Service Provider)"]
    IdP2 -->|"SAML Assertion"| SF
    IdP3 -->|"SAML Assertion"| SF
    Direct --> SF

    style LD fill:#1565c0,color:#fff
    style SF fill:#2e7d32,color:#fff

Hub-and-Spoke SSO (Identity Broker)

When an organization has many SPs and IdPs, an identity broker centralizes authentication routing and protocol translation.

flowchart LR
    subgraph Legend
        direction LR
        L1[🟢 NEW]
        L2[⚪ KEEPING]
        L3[🔴 RETIRING]
        L4[🟠 INTEGRATION LAYER]
    end

    subgraph "Identity Sources (Spokes)"
        AD["Active Directory"]
        Google["Google Workspace"]
        PartnerIdP["Partner ADFS"]
    end

    subgraph Broker["Integration Layer — Identity Broker"]
        BrokerSvc["Okta / Azure AD B2C\n(Identity Broker)"]
    end

    subgraph "Service Providers (Spokes)"
        SF["Salesforce"]
        App1["Custom Web App"]
        App2["Other SaaS"]
    end

    AD -->|"LDAP / Kerberos\ncredentials"| BrokerSvc
    Google -->|"OIDC\nID token"| BrokerSvc
    PartnerIdP -->|"SAML\nassertion"| BrokerSvc
    BrokerSvc -->|"SAML 2.0\nfederated assertion"| SF
    BrokerSvc -->|"OIDC\nID + access token"| App1
    BrokerSvc -->|"SAML 2.0\nfederated assertion"| App2

    style Broker fill:#e65100,color:#fff
    style BrokerSvc fill:#e65100,color:#fff
    style SF fill:#1565c0,color:#fff
    style AD fill:#868e96,color:#fff
    style Google fill:#868e96,color:#fff
    style PartnerIdP fill:#868e96,color:#fff
    style App1 fill:#868e96,color:#fff
    style App2 fill:#868e96,color:#fff

CTA Pattern: When to Recommend an Identity Broker

Recommend a centralized identity broker when: (1) multiple IdPs exist across business units or partner organizations, (2) different IdPs use different protocols (LDAP, Kerberos, SAML, OIDC), (3) centralized MFA enforcement is required, or (4) the organization is consolidating after M&A activity. The broker translates all protocols into a single standard (usually SAML 2.0) that Salesforce consumes.

Token Lifecycle

Understanding the OAuth token lifecycle is essential for diagnosing integration issues and designing secure token policies.

sequenceDiagram
    participant Client as Client App
    participant SF as Salesforce

    Client->>SF: OAuth flow (authorize + token exchange)
    SF->>Client: Access Token (short-lived) + Refresh Token (long-lived)

    loop API Calls
        Client->>SF: API request + Access Token
        SF->>Client: Response (200 OK)
    end

    Note over Client,SF: Access Token expires (session timeout)
    Client->>SF: API request + expired Access Token
    SF->>Client: 401 Unauthorized

    Client->>SF: POST /token (grant_type=refresh_token, refresh_token)
    SF->>SF: Validate refresh token + check policy
    SF->>Client: New Access Token (+ rotated Refresh Token if rotation enabled)

    Note over Client,SF: Refresh Token revoked, expired, or rotated
    Client->>SF: POST /token (refresh_token=revoked_token)
    SF->>Client: invalid_grant error
    Note over Client: Must re-authenticate via full OAuth flow

Token Policy Configuration

PolicyOptionsSecurity Impact
Refresh token expiryNever / After X time / If unused for X timeShorter = more secure, more re-auth friction
Refresh token rotationEnabled (Spring ‘24+) / DisabledRotation invalidates old tokens, limiting compromise window
Session timeout15 min to 24 hoursControls access token effective lifetime
Token revocationPer user / Per Connected App / All tokensEmergency response to compromised credentials

Connected Apps

Connected Apps are the configuration object in Salesforce that controls OAuth and SAML integration points.

Connected App Settings That Matter

SettingImpactWhen to Change Default
Permitted UsersAll users / Admin approvedSet to Admin approved for sensitive integrations
IP RelaxationEnforce IP restrictions or relaxRelax for mobile apps that roam networks
Refresh Token PolicyExpiration, rotationSet expiration for security; rotate for compromised tokens
ScopesAPI, refresh_token, full, web, etc.Grant minimum required scopes
Callback URLWhere tokens are sentMust match exactly; use HTTPS
Digital SignaturesCertificate for JWT BearerRequired for JWT Bearer flow
Run AsExecution user for Client CredentialsSet to an integration user with minimum access

My Domain

My Domain is required for SSO, Lightning components, and API access. It provides a unique, branded login URL.

My Domain Impact on Identity

  • Required before configuring SAML SSO
  • Required for Lightning Web Components
  • Controls login page behavior (login form, SSO buttons, social sign-on)
  • Can redirect automatically to IdP (skip Salesforce login page)
  • Custom login flows via Login Discovery

My Domain and Existing Integrations

Deploying or changing My Domain breaks existing integrations that use the generic login.salesforce.com or instance.salesforce.com URLs. All OAuth callback URLs, SAML endpoints, and API base URLs must be updated. Plan this change carefully in large enterprises.

JIT (Just-in-Time) Provisioning

JIT provisioning automatically creates or updates Salesforce user accounts during SSO login.

Standard JIT vs Custom JIT

FeatureStandard JITCustom JIT (Apex SSOJitHandler)
User creationYes, based on SAML attributesYes, with custom logic
User updatesYes, on every loginYes, with custom logic
Profile assignmentStatic (one profile per SSO config)Dynamic (based on SAML attributes or external data)
Permission setsNot supportedYes, assign dynamically
Role assignmentStaticDynamic
Federation ID mappingAutomaticCustom logic
Error handlingLimitedFull Apex exception handling

When to Use Custom JIT

Use custom JIT (Apex SSOJitHandler) when you need to: assign profiles dynamically based on department, assign permission sets based on role, populate custom fields, create related records (contact, account), or handle complex user matching logic.

Multi-Factor Authentication (MFA)

MFA is required for all Salesforce direct logins. Understanding MFA architecture is essential for CTA scenarios.

MFA Options

MethodTypeBest For
Salesforce AuthenticatorPush notification + locationMost internal users
TOTP Authenticator appsTime-based codes (Google Auth, Authy)Broad compatibility
Security Keys (U2F/WebAuthn)Physical hardware keysHigh-security environments
Built-in AuthenticatorsBiometrics (Touch ID, Face ID, Windows Hello)Convenience + security

MFA in SSO Scenarios

When SSO is configured, MFA responsibility depends on the architecture:

ScenarioWho Handles MFAConfiguration
Corporate IdP with MFAIdP handles MFA before SAML assertionNo MFA config needed in Salesforce
Salesforce as IdPSalesforce handles MFAConfigure MFA in Salesforce
SSO without IdP MFAMust add MFA at Salesforce or IdP levelConfigure either side — IdP preferred
Direct login fallbackSalesforce handles MFAAlways required for direct logins

Single Logout (SLO)

Single Logout ensures that logging out of one system terminates sessions across all connected systems. Configure SLO for security-sensitive environments. IdP-initiated SLO (logout at IdP terminates all SP sessions) is most common. SP-initiated SLO (logout at Salesforce notifies IdP) is also supported but not all downstream systems honor it.

Named Credentials

Named Credentials store callout authentication details, keeping secrets out of code. See Programmatic Security for detailed Named Credential architecture and usage patterns.

Social Sign-On

Social Sign-On (Google, Facebook, LinkedIn, Apple) is best suited for customer portals where it reduces friction for consumer users. For partner portals, LinkedIn provides professional identity verification. For internal Salesforce, always prefer corporate SSO over social sign-on.

Sources