Skip to main content

Identity providers

The identityProviders block lists the identity providers that vouch for users. Each entry describes how Defakto verifies and reads the provider's tokens, and optionally how people sign in through the provider.

An identity provider is used in two ways:

  • Workloads present the provider's tokens. A workload exchanges a user's ID token or access token for an on-behalf-of token, or a user's access token for a Transaction Token. The idTokens and accessTokens blocks describe how Defakto accepts these tokens.
  • People sign in through the provider. An OAuth client, such as an MCP client, sends a person to sign in, and Defakto redirects the person to the provider. The login block describes this.

Example​

identityProviders:
- name: corp-idp
issuer: https://idp.example.com
idTokens:
audiences: [web-app]
claimValidationRules:
- claim: email_verified
requiredValue: true
accessTokens:
audiences: [https://api.example.com]
login:
clientID: <client-id-at-your-identity-provider>
clientAuth:
method: private_key_jwt
scopes: [openid, email]

Fields​

An entry has a name, an issuer, and at least one of idTokens, accessTokens, and login.

FieldRequiredDescriptionExample
nameYesA name for the entry. Token policy rules refer to the entry by this name, in match.user.identityProvider. A DNS label, unique across all named entries in the section.corp-idp
issuerYesThe provider's issuer URL. Tokens from the provider must carry it as iss. Each entry must have a different issuer. Defakto reads the provider's discovery document from <issuer>/.well-known/openid-configuration, and verifies tokens with the signing keys it lists. The discovery document's issuer must equal this value.https://idp.example.com
idTokensAt least one of idTokens, accessTokens, and loginHow Defakto accepts the provider's OpenID Connect ID tokens. See Token type blocks.
accessTokensAt least one of idTokens, accessTokens, and loginHow Defakto accepts the provider's access tokens. See Token type blocks.
loginAt least one of idTokens, accessTokens, and loginHow people sign in through the provider. Only one provider can have it. See login.

Token type blocks​

The idTokens and accessTokens blocks have the same fields, and each applies to one kind of token. Configure a block only for each kind of token your workloads will exchange. For example, if your workloads exchange only ID tokens, leave out accessTokens.

FieldRequiredDescription
audiencesYes, for tokens that workloads presentWho the tokens must be issued for, as named in their aud claim. Not used for sign-in, which always checks the ID token's audience against login.clientID.
claimValidationRulesNoRules that every token of this kind must satisfy. See claimValidationRules.

Access tokens must be JWTs with an aud claim.

How a presented token is matched​

When a workload presents a token, Defakto uses the request's subject_token_type to choose the block: urn:ietf:params:oauth:token-type:id_token selects idTokens, and urn:ietf:params:oauth:token-type:access_token selects accessTokens. The token's iss must match exactly one entry for that kind of token, and its JWT typ header must be consistent with the kind. Defakto rejects a token that matches no entry.

claimValidationRules​

Rules that every token of this kind must satisfy, in addition to the issuer and audience checks. All rules must hold. Use them to narrow a provider's tokens to your organization, or to require a property of the token. On idTokens, the rules also apply to the ID tokens Defakto receives when people sign in.

FieldRequiredDescriptionExample
claimYesThe name of a top-level claim. iss and aud are rejected, because issuer and audiences check them.email_verified
requiredValueYesThe value the claim must have, compared exactly, including its JSON type. A string, number, or boolean. true doesn't match "true". A token that doesn't have the claim fails the rule.true

Make sure the provider includes each claim that a rule checks. When people sign in, some providers include a claim in the ID token only when Defakto requests a matching scope, such as email for email_verified. Add that scope to login.scopes.

User identifier​

Defakto identifies the user by the sub claim in the provider's tokens, and writes it into the tokens it issues for the user:

Token Defakto issuesWhere the user appears
On-behalf-of tokenobo.sub. The top-level sub is the acting workload.
Transaction Token for a usersub
Access token from a sign-insub

The value is set at the first exchange, and carried unchanged through later re-exchanges.

login​

How people sign in through the provider, when an OAuth client such as an MCP client asks for an access token for a person. Only one identity provider can have login. People sign in through that provider in every flow that needs a person to sign in.

FieldRequiredDescriptionExample
clientIDYesDefakto's client ID in the provider, from the application you register for Defakto.<client-id-at-your-identity-provider>
clientAuthYesHow Defakto authenticates to the provider. See clientAuth.method: private_key_jwt
scopesNo. Default [openid, profile, email].The scopes Defakto requests from the provider to sign the person in. Must include openid. Add the scopes your provider needs to include the claims that claimValidationRules check on idTokens.[openid, email]

Register <publicBaseURL>/oauth/upstream-callback as a redirect URI in the provider's application.

The ID token from sign-in​

Sign-in uses OpenID Connect. Defakto sends the person to the provider, and when they've signed in, the provider returns an ID token that says who they are. Defakto verifies the ID token and reads the person's identifier from its sub claim.

For most providers, that's all sign-in needs, so most providers with login have no idTokens block. Add one in these cases:

  • Your identity provider requires a rule. Some identity providers, such as Google, use one issuer for many organizations. For these identity providers, Defakto requires a rule that accepts only people from your organization, such as a rule on your Google Workspace domain. For the providers and the rule each one requires, see Issuer-specific validation rules.
  • You want to add your own checks on the ID token, with claimValidationRules. For example, to require a verified email address.

This provider requires a verified email address for sign-in. It requests the email scope, so that the provider includes email_verified in the ID token:

identityProviders:
- name: corp-idp
issuer: https://idp.example.com
login:
clientID: <client-id-at-your-identity-provider>
clientAuth:
method: private_key_jwt
scopes: [openid, email]
idTokens:
claimValidationRules:
- claim: email_verified
requiredValue: true

clientAuth​

How Defakto authenticates to another authorization server: to an identity provider in login, or to an external service in grant.clientCredentials. Some identity providers need specific clientAuth settings. See provider guides.

FieldRequiredDescriptionExample
methodYesprivate_key_jwt or client_secret_basic. See below.private_key_jwt
audienceNo. Allowed only with private_key_jwt.The audience of Defakto's signed JWT. By default, it's the authorization server's token endpoint, found in its discovery metadata, as OpenID Connect specifies, and most providers accept it. Set audience only if a provider guide gives a value for your provider, or your provider requires a different audience.https://auth.example.net
secretRef.nameRequired with client_secret_basicThe name of the Kubernetes Secret that holds the client secret.vendor-api
secretRef.keyRequired with client_secret_basicThe key in the Secret that holds the client secret.clientSecret

private_key_jwt​

Defakto signs a JWT (RFC 7523) with the trust domain's OAuth signing key, and the authorization server verifies it with Defakto's published keys. No secret is stored. Register your trust domain's OAuth JWKS Endpoint as the client's JWKS URL in the authorization server, so that it picks up new keys when Defakto rotates them. Find the OAuth JWKS Endpoint in the Defakto console, under your trust domain's Settings > Trust domain URLs, or in the output of defakto trust-domain info <trust-domain>.

With the default audience, or a URL on the authorization server's own host, Defakto's JWT has the client ID as both iss and sub. With any other audience, such as api://AzureADTokenExchange, it has your trust domain's OAuth issuer as iss and urn:defakto:oauth-client:<clientID> as sub, as federated credentials expect.

client_secret_basic​

Defakto sends a client secret, read from a Kubernetes Secret that you create and manage in the namespace where your Trust Domain Servers run. If you run several Trust Domain Server deployments, create the Secret for each one. Each Trust Domain Server reads the Secret each time it uses it, so a changed secret takes effect without a restart. The Secret must have:

  • The label defakto.security/credential: oauth-server
  • The annotation defakto.security/issuer, set to the issuer the secret authenticates to: the identity provider's issuer for login, or authorizationServer.issuer for an external service
apiVersion: v1
kind: Secret
metadata:
name: vendor-api
namespace: <Trust Domain Server namespace>
labels:
defakto.security/credential: oauth-server
annotations:
defakto.security/issuer: https://auth.example.net
type: Opaque
stringData:
clientSecret: <client-secret>

Trust Domain Servers can read the Secret only when oauthClientSecrets is enabled in your Helm values. List the name of every Secret that holds a client secret. Without names, Trust Domain Servers can read every Secret in their namespace:

trustDomainDeployment:
deployment:
oauthClientSecrets:
enabled: true
names: [vendor-api]

If the Secret is missing, isn't labeled, names a different issuer, or isn't readable because oauthClientSecrets isn't enabled or doesn't list it, requests that need it fail, and the audit event records secret_unusable.

Issuer-specific validation rules​

Defakto trusts an identity provider by its issuer. For most providers, the issuer belongs to one organization, so a token with that issuer comes from your organization's directory. Some providers use one issuer for every organization they serve. For those providers, a matching issuer only proves that someone has an account at the provider, so Defakto requires a claim validation rule that pins your organization.

Issuers that require a rule. An entry with one of these issuers is rejected unless it has a claimValidationRules rule for the listed claim, with an exact value:

ProviderIssuerRequired rule
Googlehttps://accounts.google.comhd set to your Google Workspace domain. Personal Google accounts and Google Cloud service accounts share this issuer, but their tokens have no hd value, so they aren't allowed.
Slack (Sign in with Slack)https://slack.comhttps://slack.com/team_id set to your Slack workspace ID
GitLab.com CI/CDhttps://gitlab.comnamespace_id set to the ID of your group
GitHub Actionshttps://token.actions.githubusercontent.comrepository_owner_id set to your organization's ID
Buildkitehttps://agent.buildkite.comorganization_id
HCP Terraformhttps://app.terraform.ioterraform_organization_id
Pulumi Cloudhttps://api.pulumi.com/oidcorg
Vercel, global issuer modehttps://oidc.vercel.comowner_id set to your team's ID. Team issuer mode needs no rule.
Codefreshhttps://oidc.codefresh.ioaccount_id
Scalrhttps://scalr.ioscalr_account_id
Ona (formerly Gitpod)https://app.gitpod.ioorganization_id

An entry that has only login needs the rule too. Put it in an idTokens block, because Defakto checks the ID token from sign-in with that block's rules.

Issuers that aren't accepted. These issuers serve many organizations, and their tokens don't identify the organization in a way that a rule can check:

ProviderIssuerInstead
Salesforcehttps://login.salesforce.com, https://test.salesforce.comUse your organization's My Domain issuer
Microsoft personal accountshttps://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0Use your organization's Microsoft Entra tenant issuer
Apple (Sign in with Apple)https://appleid.apple.com
LinkedInhttps://www.linkedin.com/oauth
GitLab.com sign-inhttps://gitlab.comUse a GitLab Self-Managed or GitLab Dedicated issuer. GitLab.com CI/CD shares this issuer, and is accepted with its required rule.
Amazon Cognito identity poolshttps://cognito-identity.amazonaws.comUse an Amazon Cognito user pool issuer
sandboxes.cloudhttps://sandboxes.cloud
Upboundhttps://proidc.upbound.io
DVC Studiohttps://studio.datachain.ai/api
Shisho Cloudhttps://tokens.cloud.shisho.dev
GitHub (vstoken)https://vstoken.actions.githubusercontent.com
GitHub audit log streaminghttps://oidc-configuration.audit-log.githubusercontent.com
IBM Turbonomic SaaShttps://rh-oidc.s3.us-east-1.amazonaws.com/<id>, https://oidc.op1.openshiftapps.com/<id>
Microsoft Sentinelhttps://sts.windows.net/33e01921-4d64-4f8c-a055-5bdaffd5e33d

Validation​

When you apply the configuration, Defakto also rejects:

  • Two entries with the same issuer
  • login on more than one entry
  • Removing a token type block or login from an entry while a token policy rule refers to it with via
  • Removing an entry while a token policy rule refers to it