Filip Kajetaniak
04/01/2026, 1:08 PMsu claim set to true with a specified expiry time. Can we narrow down the step up only to a specific action? We're building a fintech app where we want to perform the step up before financial transactions but we want to make sure that the su claim can be used only to a specific transaction, for example user is allowed to perform a transaction for X EUR to Y bank account. Are there any articles / examples that cover that scenario?DevRev
04/01/2026, 1:09 PM// After successful step-up (su: true in JWT)
const resp = await descopeClient.otp.signIn<loginId, {stepup: true}, token|deliveryMethod>;
Then validate the specific transaction using Fine-Grained Authorization (FGA):
• Check if the user has permission for the specific amount
• Verify recipient account authorization
• Validate transaction-specific attributes
FGA Documentation
For more details on implementing relationship-based permissions (ReBAC) and attribute-based rules (ABAC), refer to the FGA documentation which covers the necessary controls to handle your transaction-specific requirements.
This pattern provides both the security of step-up authentication and the granular control needed for financial transactions.Akash Jivane
04/01/2026, 1:28 PMsu claim in the JWT is intentionally kept generic (a boolean + expiry) and doesn't natively bind to a specific transaction. However, you can absolutely achieve what you're describing by combining step-up with custom claims and/or FGA (Fine-Grained Authorization).
Here's the pattern we'd recommend for your fintech use case:
1. Encode transaction context into custom claims at step-up time When triggering step-up, pass the transaction details as custom data so they get embedded into the JWT:
// Trigger step-up with transaction-specific context
await descopeClient.flow.start("step-up-flow", {
customClaims: {
txn_amount: 500,
txn_currency: "EUR",
txn_recipient: "IBAN_XXXXXXXX",
txn_id: "txn_abc123"
}
});
2. Validate on your backend When the token reaches your backend, verify both the su: true claim and the transaction-specific claims match the operation being attempted:
// Backend validation
const { su, txn_id, txn_amount, txn_recipient } = decodedToken;
if (!su || txn_id !== requestedTxnId || txn_amount !== requestedAmount) {
return res.status(403).json({ error: "Step-up token not valid for this transaction" });
}
3. Keep the step-up expiry short Set a tight suExpiresIn (e.g., 60–120 seconds) so the elevated token can only be used in a narrow window, reducing replay risk.
4. Optionally layer FGA on top For even more granular control (e.g., does this user have permission to send to this recipient account at all?), you can use Descope's ReBAC/ABAC — docs here: https://docs.descope.com/authorization/rebac
Descope handles the authentication elevation (step-up), but the transaction-specific authorization lives in your claims validation logic or FGA rules. The two work together rather than one replacing the other.
Let me know if this helps you!Filip Kajetaniak
04/01/2026, 1:29 PM