Support account passwords in a custom connector
When Owlie creates an account through your connector, it can give the account a random password that nobody sees and Owlie doesn't keep. To support that, your manifest marks the account's password field as a credential and ships a default password block, and your handlers keep the password out of everything they return or throw.
Owlie never reveals, stores or chooses a person's password. After an account exists, only passwords the person sets reach it: a change or reset they make themselves, an account claim or password reset started by their IT team, or Set password in My access. Owlie sends those changes to a custom connector that runs on a gateway, as it does to the connectors it ships. A custom connector that runs in Owlie's cloud sets the initial password only: Owlie can't stop its requests at a change's deadline there, so a resource on it can't link its accounts to the person's password or let people set it themselves. Run the connector on a gateway to change its passwords after creation.
Mark the password field
Declare the password as one string property of the account entity's schema, with both
writeOnly: true and "x-sensitive": true. Owlie treats a property with both as a credential: it
never sends it in an attribute update, never stores it, and shows it as Write-only and
Sensitive in the attribute list.
"password": {
"type": "string",
"title": "Password",
"writeOnly": true,
"x-sensitive": true,
"x-provisioning": { "writableOn": ["PROVISION"] }
}
- Never use the password as an identifier. The manifest check refuses an
identifier_pathsentry or anx-identifierproperty that is a credential, because Owlie records identifiers and reuses them to find the account. x-provisioning.writableOnmust includePROVISIONso the account can get its initial password.SET_PASSWORDdeclares that an update can change it later. LeavingwritableOnout allows both.x-provisioningcan only sit on a top-level property: for a password nested inside an object, put it on that object.- Declare
x-provisioning.passwordHistory: trueonly when your connector really enforces the target's password history and minimum age when asked to. Without it, the resource's Check password history setting stays at its default.
Give new accounts a password
Add a default password block to the account entity's provisioning_profile. Each resource that
uses your connector starts with a copy, which an administrator can change on the resource's
Provisioning tab, in the Password step.
"provisioning_profile": {
"password": {
"paths": ["password"],
"initial_length": 24,
"policy": { "min_length": 12 }
}
}
| Field | What it does |
|---|---|
paths | Required. One to four credential properties, each set to the same password. A nested password is a dotted path, such as passwordProfile.password. |
initial_length | The random initial password's length, 12–128. Defaults to 24. |
policy | The target's own rules: min_length (1–128) and classes (how many of lowercase, uppercase, digits and symbols, 1–4). Every password a person sets for the account must meet them. |
on_change | Plain values sent with every later password change, such as a flag that would otherwise force a change at next sign-in. Each must be a declared field an update can write, never a sensitive field or an identifier. |
Owlie generates a new password for every create attempt and writes it into the create request. Don't
map the password field in the resource's attribute mappings, with genPassword(...) or anything
else: saving the resource refuses a mapping at a credential.
Keep the password out of results, errors and logs
Owlie removes the password from a create result that echoes it, and from error text it records. Your own code can still leak it, so:
- Never log a handler's input.
- Return a record without the password.
omitPasswordFieldsfrom@owlie/connectors/sdk/v2drops everypasswordkey at any depth; remove a password under another name yourself. - Pass every error from a request that carries the password through
scrubPasswordFromError(error, password). It removes the password, raw or JSON-escaped, from the error's message, details, response body and causes, and keeps the error's class and status. Provider errors often quote the request, and a short password doesn't look like a secret to generic scrubbing.
Handle a password in the update handler
A connector on a gateway receives a person's password changes as ordinary updates that carry the
block's paths and on_change values, as Owlie's own connectors do. If your API's update can set a
password, write the update handler to the same rules:
- Send the password and the
on_changevalues in one request, and passctx.optionsto it ({ ...ctx.options, json }) so the call's deadline applies. - Throw
passwordRefusal(reasonCode)only when the provider definitely refused the password:PASSWORD_POLICY(it breaks the target's rules),PASSWORD_MASTERED_ELSEWHERE(another system owns the password),NO_PASSWORD_IDENTITY(the account has no password to set) orNOT_PERMITTED(the connection may not set it). Owlie shows its own sentence for each code, never the provider's text. - Let a timeout, a server error, a lost connection or a rate limit through as
ctx.httpraised it. The provider may have applied the password, so Owlie reports the change as unconfirmed and asks the person to set it again, instead of trying a newer password while the old request could still land. Treat a rate limit the provider reports as a 403 as a retryableQUOTA_EXCEEDEDerror, not a refusal.
Test and document it
Test the password path through the real HTTP client rather than a stubbed one, and check that:
- the handler's result contains no password, even when the provider echoes it back;
- an error that quotes a short password, such as
Ab7!, leaves the handler without it; - a server error, a timeout and a lost connection arrive without a refusal reason;
- a rate limit stays retryable.
In the connector's README, name the permissions or roles the connection needs to set passwords, and list any provider answer you took from documentation rather than a live tenant.