Provider Setup

Prepare 1Password or Azure Key Vault so Wire can read credentials from it — service accounts, service principals, and the role assignment people miss

Before you can connect a source, you have to create a credential at the provider that grants Wire read access to the vaults you choose. This page is the walkthrough for each supported provider.

Neither provider requires giving Wire your account password. Both use a scoped, revocable machine credential that you can withdraw at any time without touching your own login.

You never send a vault secret to Wire. You send the credential that lets Wire read one, and Wire reads it at sign-in time only, into memory, for one login run.


1Password

1Password is zero-knowledge, so there is no "give us your password" path. Access is granted through a Service Account token, which begins with ops_.

  1. In 1Password, go to Developer Tools → Service Accounts and create one.
  2. Grant it read access to the vaults you want Wire to use — and only those.
  3. Copy the token. 1Password shows it once.
  4. Connect it as provider: "1password" with the token in the token field.

That's the whole setup. Wire lists the vaults the token can read during the connect check, so a successful connect immediately tells you what it reaches.

To revoke Wire's access later, delete the Service Account in 1Password — or disconnect the source, which deletes the stored token on our side.

Reference: 1Password Service Accounts


Azure Key Vault

Azure needs more setup than 1Password, because access is granted per vault rather than per token.

1. Create an app registration

In the Azure portal, go to Microsoft Entra ID → App registrations → New registration. Give it a name; the defaults are fine for everything else.

From the app's Overview page, note two values you'll need:

  • Application (client) ID → send as client_id
  • Directory (tenant) ID → send as tenant_id

2. Create a client secret

Under Certificates & secrets → Client secrets → New client secret, create one and copy its Value — not its Secret ID. Azure shows the value once.

This is the client_secret field.

Secrets expire. Azure client secrets carry an expiry (commonly 6, 12 or 24 months) and Entra doesn't report it through the token exchange, so Wire can't warn you in advance — credentials_expires_at stays empty for Azure sources. Diary the expiry yourself, and when it comes, rotate rather than reconnecting: rotation keeps the source ID, so every identity bound to it keeps working.

3. Grant the app access to each vault

This is the step most setups miss. Without it the connection authenticates successfully and reads nothing.

For each Key Vault you want Wire to use, open it and go to Access control (IAM) → Add role assignment, then assign your app registration the Key Vault Secrets User role.

If the vault still uses the older access-policy model instead of RBAC, add an access policy granting Get and List on secrets.

Role assignments take a few moments to propagate. A connect that fails immediately after granting the role usually succeeds on a retry a minute later.

4. Collect the vault URLs

Azure has no API for "which vaults may this principal read", so Wire can't discover them — you list them explicitly. Each vault's URL is on its Overview page, in the form:

https://<vault-name>.vault.azure.net

Send them in vault_urls, one per line. Wire verifies every one during connect, so a missing role assignment fails the connect naming the offending vault rather than surfacing later as a mysterious login failure.

Only Key Vault addresses are accepted — the host must end in .vault.azure.net, .vault.usgovcloudapi.net or .vault.azure.cn. Anything else is rejected with INVALID_VAULT_URL.

5. Connect

curl https://api.anakin.io/v1/wire/identity-sources \
  -X POST \
  -H "X-API-Key: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "azure_key_vault",
    "display_name": "Prod Key Vault",
    "tenant_id": "00000000-0000-0000-0000-000000000000",
    "client_id": "00000000-0000-0000-0000-000000000000",
    "client_secret": "your_client_secret_value",
    "vault_urls": "https://my-vault.vault.azure.net\nhttps://other-vault.vault.azure.net"
  }'

Reference: Azure Key Vault RBAC guide


Storing login fields in Key Vault

A Key Vault secret holds a single opaque value, whereas a login usually needs at least a username and a password. There are two ways to bridge that, and both are expressed in the source_ref locator when you sign in.

Two secrets. Store the username and password as separate secrets and point at each:

{
  "fields": {
    "username": { "container": "https://my-vault.vault.azure.net", "key": "acme-user" },
    "password": { "container": "https://my-vault.vault.azure.net", "key": "acme-pass" }
  }
}

One secret, username in a tag. Store the password as the secret's value and add a tag named username to it. Reference the tag with the tag: prefix, inheriting the rest from entry:

{
  "entry":  { "container": "https://my-vault.vault.azure.net", "key": "acme" },
  "fields": { "username": { "property": "tag:username" } }
}

Omit version and Wire always reads the current version — so rotating a password in Key Vault takes effect on the next login with no change on our side.


Troubleshooting

SymptomCauseFix
Connect fails with SOURCE_FORBIDDEN naming a vaultThe app authenticated but has no role on that vaultAssign Key Vault Secrets User on the named vault, then retry
Connect fails with SOURCE_TOKEN_REJECTEDWrong tenant_id / client_id, or the client secret's ID was sent instead of its ValueRe-copy the secret Value from Certificates & secrets
Connect fails with INVALID_VAULT_URLMalformed URL, or no Key Vault exists at itCopy the URL from the vault's Overview page
Connected fine, but browsing a container returns "not found"The container ID is a URL and wasn't percent-encoded into the pathSee List Entries — encode it
Worked before, now SOURCE_AUTH_FAILED everywhereThe client secret expired or was deletedRotate with a new secret; bindings survive
Login fails with SOURCE_FIELD_MISSINGThe secret can't supply a field the login needsCheck missing_fields in the response, then add the field or use per-field refs above

A working source that later starts failing is worth a verify first — it distinguishes a dead credential from a vault whose role assignment was removed, which look identical from a failed login.