Skip to content

ts identity-source ​

Show, create, change, test, or delete an identity source, or move accounts between sources. Reach for test first when directory users suddenly cannot sign in, and for set to rotate a secret or take a provider off the sign-in page without opening the Administration site.

Usage ​

text
ts identity-sources [--deleted] [--csv] [--no-trunc]
ts identity-source <name|id>
ts identity-source new <name> --type=TYPE [--login-prefix=PREFIX] [--new-people=MODE] [--<setting>=VALUE]...
ts identity-source set <name|id> <property> <value>
ts identity-source test <name|id>
ts identity-source delete <name|id> [--force]
ts identity-source accounts <name|id>
ts identity-source move <name|id> <to-name|id> <account-id>...

Description ​

An identity source is where an account comes from: the built-in Internal source, an Active Directory or LDAP directory, or an OpenID Connect, SAML, or OAuth 2.0 provider. Every account belongs to exactly one source, and a sign-in is matched only against the accounts and identities of the source it came through. ts identity-sources lists every source with its type, its New People choice, whether the sign-in page shows it, and how many accounts it holds. The Service Accounts source is never listed. A deleted source is listed only with --deleted, and only while it still holds accounts, marked (deleted).

Every singular form names a source by its ID, the last column of the list, or by its name in any case. An ID names a deleted source as well as a live one. A name names the live source that has it, and names a deleted source only when no live source and no other deleted source has that name; once a deleted source's name has been given again, name it by its ID. A deleted source can be printed, and its accounts listed and moved out of it; set, test, and delete refuse it. The same sources appear in the Administration site under Identity → Identity Sources.

New People ​

Each source decides what happens when someone signs in through it and matches no account. new takes it as --new-people, set as the new-people property, and the Administration site shows it as New People:

ValueIn the Administration siteAn unmatched sign-in
ExistingAccountsOnlyLink to an Existing AccountIs refused. The person must connect the identity to an account they already have.
SelfRegistrationSign UpIs offered the signup page.
JustInTimeCreate an AccountGets an account at the first sign-in, or claims by name an account made ahead of time in this source.

What a type accepts:

  • Active Directory, LDAP — JustInTime only.
  • OpenID Connect, SAML — any of the three. A new one starts on ExistingAccountsOnly.
  • OAuth 2.0 — ExistingAccountsOnly or SelfRegistration. An OAuth 2.0 provider never creates an account at sign-in.
  • Internal — ExistingAccountsOnly. Its accounts are made by an administrator.

SelfRegistration is accepted only while the source is on the sign-in page, and a source that signs people up cannot leave it. A new source is not on the sign-in page, so it cannot start on SelfRegistration. Order the two changes accordingly: to open signup, set show-on-sign-in-page true first and new-people SelfRegistration second; to close it, set new-people ExistingAccountsOnly first and show-on-sign-in-page false second.

JustInTime on a provider gives an account to anyone the identity provider signs in, with no terms step. Choose it only for your own organization's identity provider.

Creating a Source ​

new requires --type: ActiveDirectory (or ad), GenericLdap (ldap), OpenIdConnect (oidc), Saml (saml), or OAuth2 (oauth2). Besides --login-prefix and --new-people, it takes the settings of that type as options:

  • OpenID Connect — --metadata-url, --client-id, --client-secret, --scopes.
  • SAML — --metadata-url and --service-provider-entity-id, this server's entity ID. The entity ID is required.
  • OAuth 2.0 — --authorization-endpoint, --token-endpoint, --user-information-endpoint, and --client-id are required. --client-secret, --email-list-endpoint, --scopes, and the user document fields (--subject-field, --login-name-field, --display-name-field, --email-field, --email-verified-field) are optional.
  • Active Directory, LDAP — none. Create the source, then set its host, port, base-dn, bind-method, transport, username, and password.

An option that is not a setting of the type is refused before anything is sent. A new provider is not on the sign-in page; put it there with set <name> show-on-sign-in-page true. A placed provider is still left out until a sign-in can start through it, for example while it has no metadata URL or this server cannot read its metadata. The Administration site marks such a provider Shown, not offered and says why.

Changing a Source ​

set changes one property at a time. Every source takes name, description, login-prefix, and new-people. A provider also takes show-on-sign-in-page (true or false) and display-order, its position on the sign-in page counted from 0, where the other providers close up around it. A SAML source takes treat-email-as-verified, and an Entra OpenID Connect or SAML source takes recheck-with-graph, which rechecks its accounts with Microsoft Graph. The rest are the settings of the source's type:

  • Active Directory, LDAP — host, port, base-dn, bind-method (Anonymous, Simple, or Negotiate), transport (Plain or Ldaps), username, password, page-size.
  • OpenID Connect — metadata-url, client-id, client-secret, native-client-id, scopes, enable-single-logout.
  • SAML — metadata-url, service-provider-entity-id, name-id-format, request-signing, signing-key, signature-algorithm, login-name-attribute, subject-attribute, given-name-attribute, surname-attribute, groups-attribute, graph-client-id, graph-client-secret, enable-single-logout.
  • OAuth 2.0 — authorization-endpoint, token-endpoint, user-information-endpoint, email-list-endpoint, client-id, client-secret, scopes, subject-field, login-name-field, display-name-field, email-field, email-verified-field.

A property outside these is refused with the list the source accepts. Boolean properties take true or false and nothing else, and display-order and page-size take a whole number; both are checked before anything is written. An unrecognized bind-method or transport keeps the stored one, so print the source afterwards to confirm the change. A simple bind is the only one that connects over Ldaps.

Secrets are write-only: client-secret, graph-client-secret, password, and signing-key. Print shows only whether one is stored, with its last four characters where the server keeps them, and --format=json carries the same cue, never the value. An empty secret keeps the stored one; any other empty value clears its setting. To replace a secret, supply the new value.

Each change is made from the revision set has just read, so a change someone else saved in between is refused rather than overwritten. Once people have signed in through a source, the settings that decide who they are cannot change: an issuer or identity provider entity ID, the service provider entity ID, a subject attribute or field, the NameID format, a directory's user ID attribute or domain. To point people at another identity provider, create another source and move the accounts to it. The built-in Internal source takes only a new description.

A source's Accepted Tenants, the Entra tenants it accepts sign-ins from, are not editable from ts; edit them on the source's page under Identity → Identity Sources. --format=json shows them as tenants. The sign-in page's guest access, terms, and password settings are under Identity → Authentication.

Testing, Deleting, and Moving Accounts ​

test connects to an Active Directory or LDAP source's directory with its saved settings and binds as its service account. A failed test exits -3 and prints the directory's own error, which is usually enough to tell a bad credential from an unreachable host. Directory accounts and groups are reconciled at sign-in, so there is no sync to run.

delete confirms first. It takes the source off the sign-in page and disables its accounts, which ends their sessions; the accounts are kept, with their workspaces and files, until you move or delete them, and the source's groups stay but grant nothing. The built-in Internal source cannot be deleted, and a delete that would leave Administrators with no enabled member is refused. To stop people signing in through a provider, take it off the sign-in page instead: deleting it disables accounts that may have no other way in. ts identity-sources --deleted lists a deleted source while it still holds accounts.

accounts lists the accounts a source holds, deleted or not: each one's login name, first and last name, whether it is enabled, and its ID, which is what move takes. The ID column is never truncated.

move moves accounts, named by the IDs accounts lists, from one source to another: all of them or none. Each account keeps its enabled state and what it owns, is signed out everywhere, and loses its identity and group memberships in the source it leaves; an Internal password is cleared. The destination has to be able to sign every account in: a directory, a source whose New People is JustInTime, or a source in which each account already has an identity. Internal is never a destination. A move is refused for your own account, and where the memberships it ends would leave Administrators with no enabled member. A deleted source's accounts are moved the same way, naming the deleted source as the one they move from. A deleted source is never a destination.

Creating, changing, placing, deleting, and moving are all recorded in the operator audit log with the acting administrator, so ts audit can answer who changed the sign-in configuration and when.

Options ​

FlagDescriptionDefault/ValuesNotes
--typeType of a new source.ActiveDirectory (ad), GenericLdap (ldap), OpenIdConnect (oidc), Saml (saml), OAuth2 (oauth2)new only, and required there.
--login-prefixLogin prefix of a new source.new only. Change it later with set <name> login-prefix <value>.
--new-peopleWhat a new source does with someone it matches to no account.ExistingAccountsOnly, SelfRegistration, JustInTimenew only. Defaults to the first value the type accepts. SelfRegistration is refused here, because a new source is not on the sign-in page yet.
--metadata-urlDiscovery or federation metadata URL.http(s) URLnew only; OpenID Connect and SAML.
--client-idClient ID.new only; OpenID Connect and OAuth 2.0. Required for OAuth 2.0.
--client-secretClient secret.new only; OpenID Connect and OAuth 2.0. Lands in shell history; see the examples.
--scopesScopes, space-separated.new only; OpenID Connect and OAuth 2.0.
--service-provider-entity-idThis server's entity ID.URInew only; required for SAML.
--authorization-endpointAuthorization endpoint.URLnew only; required for OAuth 2.0.
--token-endpointToken endpoint.URLnew only; required for OAuth 2.0.
--user-information-endpointUser information endpoint.URLnew only; required for OAuth 2.0.
--email-list-endpointEmail list endpoint.URLnew only; OAuth 2.0, optional.
--subject-fieldUser document field holding the subject.new only; OAuth 2.0.
--login-name-fieldUser document field holding the login.new only; OAuth 2.0.
--display-name-fieldUser document field holding the display name.new only; OAuth 2.0.
--email-fieldUser document field holding the email.new only; OAuth 2.0.
--email-verified-fieldUser document field saying the email is verified.new only; OAuth 2.0.
--force, -fDelete without confirming.delete only. Required when there is no terminal.
--deletedAlso list deleted sources that still hold accounts.ts identity-sources only. Each is marked (deleted).
--csvTab-separated output, nothing truncated.ts identity-sources only.
--no-truncDo not truncate columns.ts identity-sources only.

Examples ​

bash
# What identity sources are there, and which are on the sign-in page?
ts identity-sources

# One source in full, including whether its secret is stored
ts identity-source Entra

# Add an OpenID Connect provider and put it on the sign-in page
ts identity-source new Entra --type=oidc \
  --metadata-url=https://login.example.com/.well-known/openid-configuration \
  --client-id=6f21c8e0-91a4-4b7d-8e33-2a6f5c1d0b88 \
  --client-secret="$OIDC_SECRET"
ts identity-source set Entra show-on-sign-in-page true

# Add a SAML provider
ts identity-source new Okta --type=saml \
  --metadata-url=https://example.okta.com/app/abc123/sso/saml/metadata \
  --service-provider-entity-id=urn:turbo:example

# Add an OAuth 2.0 provider that people sign up through
ts identity-source new GitHub --type=oauth2 \
  --authorization-endpoint=https://github.com/login/oauth/authorize \
  --token-endpoint=https://github.com/login/oauth/access_token \
  --user-information-endpoint=https://api.github.com/user \
  --client-id=Iv1.8a61f9b3a7aba766 --client-secret="$GITHUB_SECRET"
ts identity-source set GitHub show-on-sign-in-page true
ts identity-source set GitHub new-people SelfRegistration

# Add an Active Directory, then give it its connection
ts identity-source new CORP --type=ad --login-prefix=CORP
ts identity-source set CORP host dc01.corp.example.net
ts identity-source set CORP port 636
ts identity-source set CORP bind-method Simple
ts identity-source set CORP transport Ldaps
ts identity-source set CORP base-dn "DC=corp,DC=example,DC=net"
ts identity-source set CORP username svc-turbo
ts identity-source set CORP password "$BIND_PASSWORD"

# Directory sign-ins are failing: is the directory answering?
ts identity-source test CORP

# Rotate a client secret after rotating it at the identity provider
ts identity-source set Entra client-secret "$NEW_OIDC_SECRET"

# Close signup and take a provider off the sign-in page, in this order
ts identity-source set GitHub new-people ExistingAccountsOnly
ts identity-source set GitHub show-on-sign-in-page false

# Move two accounts to the corporate directory; each is bound to its directory account at its next sign-in
ts identity-source move Okta CORP c41f0d8a-2b77-4c19-9e0a-1d3b6f2e5a90 5b3b91f5-7ff6-4615-b8b3-a26e30d03c16

# Retire a source; its accounts are disabled and kept
ts identity-source delete Okta --force

# A deleted source's accounts are kept: find them and move them to the corporate directory
ts identity-sources --deleted
ts identity-source accounts Okta
ts identity-source move Okta CORP c41f0d8a-2b77-4c19-9e0a-1d3b6f2e5a90 5b3b91f5-7ff6-4615-b8b3-a26e30d03c16
bash
# A secret typed literally is recorded in shell history and visible in the
# process list. Read it from an environment variable or a prompt instead.
ts identity-source set Entra client-secret hunter2

Output ​

text
NAME      TYPE             NEW PEOPLE            SIGN-IN PAGE  ACCOUNTS  ID
Internal  Internal         ExistingAccountsOnly  -             4         0b6f3c55-2a1e-4f7b-9d3c-8e5a1f2b7c90
CORP      ActiveDirectory  JustInTime            -             482       3d9a7c1e-5b2f-4e8a-a1c6-7f0e2d4b9a13
Entra     OpenIdConnect    ExistingAccountsOnly  shown         211       4f21c8e0-91a4-4b7d-8e33-2a6f5c1d0b88
GitHub    OAuth2           SelfRegistration      shown         37        8a1c7e42-90bb-4d15-a3f7-6c2e0b9d4517

With --deleted, each deleted source that still holds accounts is listed too:

text
NAME            TYPE             NEW PEOPLE            SIGN-IN PAGE  ACCOUNTS  ID
Internal        Internal         ExistingAccountsOnly  -             4         0b6f3c55-2a1e-4f7b-9d3c-8e5a1f2b7c90
CORP            ActiveDirectory  JustInTime            -             482       3d9a7c1e-5b2f-4e8a-a1c6-7f0e2d4b9a13
Entra           OpenIdConnect    ExistingAccountsOnly  shown         211       4f21c8e0-91a4-4b7d-8e33-2a6f5c1d0b88
GitHub          OAuth2           SelfRegistration      shown         37        8a1c7e42-90bb-4d15-a3f7-6c2e0b9d4517
Okta (deleted)  Saml             JustInTime            -             2         7f3e2d1c-0b9a-4876-a543-210fedcba987

accounts prints the accounts a source holds:

text
USERNAME  FIRST NAME  LAST NAME  ENABLED  ID
ada       Ada         Lovelace   no       c41f0d8a-2b77-4c19-9e0a-1d3b6f2e5a90
grace     Grace       Hopper     no       5b3b91f5-7ff6-4615-b8b3-a26e30d03c16

A deleted source prints a Deleted: line, its deletion time in UTC, after its name.

text
Name:        Entra
Type:        OpenIdConnect
New people:  ExistingAccountsOnly
Prefix:      -
Sign-in:     shown, position 0
ID:          4f21c8e0-91a4-4b7d-8e33-2a6f5c1d0b88
Settings:
  metadata-url:         https://login.example.com/.well-known/openid-configuration
  issuer:               https://login.example.com
  client-id:            6f21c8e0-91a4-4b7d-8e33-2a6f5c1d0b88
  client-secret:        configured (…4f2a)
  native-client-id:     -
  scopes:               openid profile email
  enable-single-logout: false

Settings are printed under the names set takes. A few are read-only and set refuses them: an OpenID Connect source's issuer and a SAML source's identity-provider-entity-id, which the server pins from the provider's metadata, and a directory's domain-sid and user-object-id-attribute. A directory prints its connection the same way, with its password only as configured or not set:

text
Settings:
  host:                     dc01.corp.example.net
  port:                     636
  base-dn:                  DC=corp,DC=example,DC=net
  bind-method:              Simple
  transport:                Ldaps
  username:                 svc-turbo
  password:                 configured
  page-size:                500
  domain-sid:               S-1-5-21-1004336348-1177238915-682003330
  user-object-id-attribute: objectGUID

Exit Codes ​

0 on success, including a test that connects. -1 when the command or the server refuses the change: new without --type or with a setting of another type, set with a property the source does not take or a value of the wrong kind, a name or login prefix another source has, a New People value the type does not accept, SelfRegistration for a source off the sign-in page or a signup source taken off it, a change made from a stale read, a setting that people's sign-ins now depend on, a test of a source that is not a directory, a delete or move that would leave Administrators with no enabled member, a move the destination could not sign in, a set, test, or delete of a deleted source, a move to a deleted source, or a name several deleted sources share. -3 when the connection test fails, and when the server itself cannot be reached. -4 when no account is signed in. -5 when the account is not a Server Administrator. -6 when no source matches the name or ID, including the destination of a move.

  • ts user — The accounts a source holds; --directory names a source.
  • ts group — Groups, each of which belongs to one identity source.
  • ts login — Signs you in through the server's sign-in page, which offers the providers placed on it.
  • ts settings — authentication-type follows the sign-in page these sources are placed on.
  • ts audit — Who changed the sign-in configuration, and when.