Blind Signing
Blind signing lets a trusted app skip the 1auth transaction, message, or EIP-712 review iframe and start the passkey signing ceremony immediately. The user still sees the browser or platform WebAuthn prompt; only the 1auth review UI is hidden.
Use this for flows where your own app UI already showed the user what they are signing, such as a checkout button that displays the item, amount, recipient, and chain before the user clicks Sign.
Do not use blind signing as a substitute for consent. Your app becomes responsible for presenting the action clearly before calling the SDK.
Requirements
Blind signing is only available after the user has already signed in or signed up with 1auth.
Before a blind signing request can complete:
- the user must have an active passkey session,
- the requesting origin must be trusted or registered,
- your app must call a signing method after an explicit user action,
- your app UI should show the payload, amount, recipient, and any risk context before calling the SDK.
If the user needs to sign in, sign up, or approve app trust, 1auth will not hide that flow. Authentication and signup remain visible.
Configure the client
Set blind_signing: true when you initialize OneAuthClient.
import { OneAuthClient } from "@rhinestone/1auth";
export const client = new OneAuthClient({
providerUrl: "https://passkey.1auth.box",
clientId: "webshop",
blind_signing: true,
sponsorship: {
accessTokenUrl: "/api/sponsorship/access-token",
extensionTokenUrl: "/api/sponsorship/extension-token",
},
});With this configuration, supported signing calls from this client request blind signing by default.
Supported methods
Blind signing applies to SDK signing flows that normally open the 1auth review iframe:
sendIntent()sendBatchIntent()signMessage()signTypedData()signWithModal()
It does not apply to authWithModal(), signup, login, recovery, or
permission-grant dialogs.
Per-call overrides
You can override the client default for a single request.
await client.signMessage({
username: "alice@example.com",
message: "Approve checkout order #123",
blind_signing: false,
});This is useful when most of your app can use blind signing, but selected high-risk actions should still show 1auth's review UI.
You can also enable blind signing for one request without changing the client default:
await client.sendIntent({
accountAddress,
targetChain: 8453,
calls: [
{
to: merchantAddress,
data: transferCalldata,
value: "0",
},
],
blind_signing: true,
});Checkout example
Configure blind signing on the shared client, not on every checkout intent.
export const oneAuth = new OneAuthClient({
providerUrl: "https://passkey.1auth.box",
clientId: "checkout",
blind_signing: true,
});import { PayButton } from "@rhinestone/1auth/react";
export function CheckoutButton() {
return (
<PayButton
client={oneAuth}
intent={{
targetChain: 8453,
calls: [paymentCall],
tokenRequests: [usdcRequest],
}}
onSuccess={(result) => {
console.log("Paid:", result.transactionHash);
}}
>
Pay $24.00
</PayButton>
);
}The user clicks your button, 1auth prepares and signs the intent in a hidden iframe, and the browser passkey prompt appears. After the user approves the passkey prompt, the SDK continues with intent execution.
Failure behavior
Blind signing requests fail closed when 1auth would need to show a required consent step.
Common cases:
- no active passkey session: ask the user to sign in with
authWithModal(), then retry the signing call, - untrusted or unregistered app origin: complete the visible trust flow before using blind signing,
- WebAuthn cancellation or platform failure: surface the SDK error and let the user retry from your app UI.
Blind signing vs Headless Mode
Blind signing still uses 1auth's passkey signer. The iframe is hidden, but the user's passkey produces the signature.
Headless Mode is different: your app provides signatures from another validator or signer, and 1auth does not run the passkey signing dialog at all.