102 lines
4.6 KiB
Markdown
102 lines
4.6 KiB
Markdown
# Authentication — platform keys, OAuth, restricted API keys
|
||
|
||
## Authentication
|
||
|
||
How your app authenticates and accesses Stripe data for merchants who install it.
|
||
|
||
**Canonical page:** https://docs.stripe.com/stripe-apps/api-authentication
|
||
|
||
Read this page using WebFetch before implementing authentication patterns.
|
||
|
||
## Three authentication types
|
||
|
||
Stripe Apps supports three authentication methods, configured via `stripe_api_access_type` in the app manifest:
|
||
|
||
| Auth type | Manifest value | How it works | Best for |
|
||
| --- | --- | --- | --- |
|
||
| Restricted API key (recommended) | `restricted_api_key` | Stripe generates a scoped key at install; merchant provides it to your system | Private apps, simpler integrations, apps that don’t need Connect-style access |
|
||
| Platform keys | `platform` | Your secret key + `Stripe-Account` header to act on behalf of installers | Public/marketplace apps that need to act across many merchants |
|
||
| OAuth 2.0 | `oauth` | Standard OAuth flow generates access tokens per-account | Apps where merchant must be merchant-of-record |
|
||
|
||
### Choosing the right type
|
||
|
||
**Default to restricted API keys** unless you have a specific reason to use platform keys or OAuth. RAKs are simpler, more secure (scoped permissions), and don’t create a Connect-style relationship.
|
||
|
||
Use a different type when:
|
||
|
||
1. **You need Connect webhook fanout** (events from all merchants to one endpoint): Platform keys.
|
||
2. **You’re building a public marketplace app acting across many merchants:** Platform keys.
|
||
3. **The merchant must be the merchant-of-record for charges:** OAuth.
|
||
4. **Private app or fewer merchants, no Connect fanout needed:** Restricted API keys (simplest).
|
||
|
||
## Platform keys
|
||
|
||
Your app’s API key acts on behalf of a merchant’s account using the `Stripe-Account` header:
|
||
|
||
```javascript
|
||
// Use a restricted API key when possible; fall back to secret key only for platform-key apps
|
||
const stripe = require("stripe")(process.env.STRIPE_API_KEY);
|
||
|
||
await stripe.customers.list({}, {
|
||
stripeAccount: "acct_xxxxx", // the merchant's account ID
|
||
});
|
||
```
|
||
|
||
**How to get the merchant’s account ID:**
|
||
|
||
- From a webhook event: `event.account`
|
||
- From `fetchStripeSignature` payload: the signed data includes `account_id`
|
||
- From the UI extension: `userContext.account.id` (top-level prop)
|
||
|
||
**Key fact:** Platform keys use the same `Stripe-Account` header mechanism as Stripe Connect. Installers are NOT onboarded as connected accounts in the traditional sense — the header simply authorizes your key to access their account within the app’s declared permissions.
|
||
|
||
## OAuth 2.0
|
||
|
||
Use OAuth when the connected account needs to be the merchant of record for charges, or when you need the merchant’s own Stripe identity on API calls.
|
||
|
||
Most apps do NOT need OAuth. Use platform keys unless you specifically need this.
|
||
|
||
For implementation, read: https://docs.stripe.com/stripe-apps/pkce-oauth-flow
|
||
|
||
## Restricted API keys
|
||
|
||
With RAK apps, Stripe generates a restricted key at install time with only the permissions your app declared. The merchant copies this key to your system.
|
||
|
||
Key differences from platform keys:
|
||
|
||
- No Connect-style relationship is created
|
||
- Can’t use Connect webhook fanout (each merchant manages their own webhooks)
|
||
- Simpler model for private apps or apps with fewer merchants
|
||
|
||
## Authenticating the UI to your backend (fetchStripeSignature)
|
||
|
||
`fetchStripeSignature` proves to your backend that a request came from a legitimate app installation.
|
||
|
||
Key facts:
|
||
|
||
- The signed payload contains `user_id` and `account_id` by default (field order matters)
|
||
- You can include additional data by passing it to `fetchStripeSignature(extraPayload)`
|
||
- Backend verifies with `stripe.webhooks.signature.verifyHeader()`
|
||
- The signing secret (starts with `absec_...`) is generated on first `stripe apps upload`
|
||
|
||
For the full implementation pattern, read: https://docs.stripe.com/stripe-apps/build-backend
|
||
|
||
## Identifying the installing merchant
|
||
|
||
When a merchant installs your app, Stripe sends an `account.application.authorized` event. When they uninstall, it sends `account.application.deauthorized`.
|
||
|
||
Store the account ID from `event.account` to make future API calls on their behalf.
|
||
|
||
## Permission scopes
|
||
|
||
Use the CLI to add permissions to your app:
|
||
|
||
```bash
|
||
stripe apps grant permission "customer_read" "Read customer data to show in the Dashboard"
|
||
stripe apps grant permission "event_read" "Receive webhook events"
|
||
```
|
||
|
||
This updates `stripe-app.yaml` with the correct format automatically.
|
||
|
||
**When you change permissions:** existing users must re-authorize. The app returns an invalid-request error for undeclared permissions until the user re-authorizes. See `publishing.md` for details.
|