OAuth 2.0
JWT
Authorization
XSUAA

XSUAA — Authorization & Trust Management

SAP BTP's OAuth 2.0 authorization server — the engine behind all BTP application security. Manages scopes, role templates, role collections, and JWT token issuance for every BTP application.

XSUAA OAuth 2.0 Authorization Flow
Rendering diagram…

Executive Summary

XSUAA (Extended Services for User Account and Authentication) is SAP BTP's OAuth 2.0 Authorization Server. It issues JWT access tokens that contain user identity, tenant information, and granted scopes. Every BTP application must be registered in XSUAA (via xs-security.json), and every service call must validate the JWT token before granting access to resources.

XSUAA is not a user store — it delegates authentication to SAP IAS. XSUAA's role is exclusively authorization: deciding what an authenticated user is permitted to do based on their assigned scopes and role collections.

XSUAA Architecture Concepts

XSUAA InstanceCreated as a BTP service instance in CF (plan: application) or Kyma (ServiceInstance CRD). One XSUAA instance per application — shared across all runtime environments.
xs-security.jsonThe application security descriptor. Defines scopes, role templates, and (optionally) pre-built role collections. Supplied at service instance creation time.
ScopesFine-grained permission strings (e.g., $XSAPPNAME.billing.read). Checked by CAP @restrict annotations or @sap/xssec manually. Defined in xs-security.json.
Role TemplatesNamed aggregations of scopes (e.g., BillingAdministrator = billing.read + billing.admin). Role templates become the assignable units in Role Collections.
Role CollectionsBTP's RBAC grouping mechanism. Aggregate role templates from one or more applications. Assigned to users or AD groups (via IPS). Managed in BTP Cockpit.
JWT StructureXSUAA JWTs contain: xsappname, granted_scopes, user_name, email, subdomain (tenant), exp (expiry). Inspect with jwt.io for debugging.
Authorization Code GrantUsed for user-facing applications (browser → App Router → XSUAA → IAS). The App Router manages the full OAuth flow and session.
Client Credentials GrantUsed for service-to-service communication (no user context). CAP uses this when calling SAP AI Core, Event Mesh, or other BTP services.
Principal PropagationPasses the authenticated user identity from a BTP app through Cloud Connector to an on-premise system (S/4HANA). Enables audit trail at the backend.
Multi-tenant ModeWhen tenant-mode: 'shared' in xs-security.json, the XSUAA instance serves multiple tenants. Each tenant's JWT contains a unique subdomain claim.

xs-security.json — Complete Application Security Descriptor

Design scopes around actions, not roles
Define scopes at the action level first (customer.read, billing.read, billing.admin), then aggregate into role templates. This separation allows fine-grained Role Collections without modifying application code. The $XSAPPNAME placeholder is replaced with the actual xsappname at runtime.
xs-security.json
1{
2  "xsappname": "dewa-utilities-portal",
3  "tenant-mode": "dedicated",
4  "description": "DEWA Utilities Customer Portal",
5  "scopes": [
6    {
7      "name": "$XSAPPNAME.customer.read",
8      "description": "Read customer utility data"
9    },
10    {
11      "name": "$XSAPPNAME.billing.read",
12      "description": "View billing statements"
13    },
14    {
15      "name": "$XSAPPNAME.billing.admin",
16      "description": "Manage billing corrections"
17    },
18    {
19      "name": "uaa.user",
20      "description": "UAA user scope (required)"
21    }
22  ],
23  "role-templates": [
24    {
25      "name": "CustomerViewer",
26      "description": "Read-only customer access",
27      "scope-references": [
28        "$XSAPPNAME.customer.read",
29        "$XSAPPNAME.billing.read"
30      ]
31    },
32    {
33      "name": "BillingAdministrator",
34      "description": "Full billing administration",
35      "scope-references": [
36        "$XSAPPNAME.customer.read",
37        "$XSAPPNAME.billing.read",
38        "$XSAPPNAME.billing.admin"
39      ]
40    }
41  ],
42  "role-collections": [
43    {
44      "name": "DEWA-Customer-Viewer",
45      "description": "Standard customer service agent",
46      "role-template-references": [
47        "$XSAPPNAME.CustomerViewer"
48      ]
49    }
50  ],
51  "oauth2-configuration": {
52    "token-validity": 3600,
53    "refresh-token-validity": 86400,
54    "redirect-uris": [
55      "https://dewa-utilities.cfapps.ae1.hana.ondemand.com/login/callback"
56    ]
57  }
58}

CAP Service Authorization — Declarative Pattern

Prefer @restrict over manual xssec calls
The CDS @restrict annotation is the recommended pattern for CAP applications. It is enforced at the OData protocol layer — before any application code runs — and is visible in the service definition for auditors.
srv/billing-service.cds
1// CAP service — scope-based authorization
2// srv/billing-service.cds
3service BillingService @(requires: 'authenticated-user') {
4  @(restrict: [
5    { grant: 'READ', to: 'CustomerViewer' },
6    { grant: ['READ', 'WRITE', 'DELETE'], to: 'BillingAdministrator' }
7  ])
8  entity Bills as projection on db.Bills;
9
10  @(requires: 'BillingAdministrator')
11  action applyCorrection(billId: UUID, amount: Decimal) returns Boolean;
12}

Manual Scope Check — Node.js (@sap/xssec)

srv/middleware/auth.js
1// Node.js manual scope check (for non-CAP services)
2const xssec = require('@sap/xssec');
3const xsuaaCredentials = JSON.parse(process.env.VCAP_SERVICES).xsuaa[0].credentials;
4
5app.get('/api/admin', (req, res) => {
6  xssec.createSecurityContext(
7    req.headers.authorization?.split(' ')[1],
8    xsuaaCredentials,
9    (err, ctx) => {
10      if (err || !ctx.checkScope('$XSAPPNAME.billing.admin')) {
11        return res.status(403).json({ error: 'Insufficient scope' });
12      }
13      // Proceed with admin logic
14    }
15  );
16});

JWT Token Claims Reference

JWT ClaimDescriptionExample
user_nameUser login name (email)ahmed.ali@dewa.gov.ae
given_nameFirst name from IAS/IdPAhmed
xsappnameXSUAA application namedewa-utilities-portal!t123
scopeArray of granted scope strings["dewa...!t123.billing.read"]
zidZone ID (XSUAA tenant ID)a1b2c3d4-...
ext_attr.subaccountidBTP subaccount IDsa-12345-...
expToken expiry (Unix timestamp)1748980800 (3600s from iat)

Enterprise Example: DEWA Utilities Portal

DEWA XSUAA Configuration
DEWA Utilities Portal uses XSUAA with 3 role templates: CustomerViewer, BillingAdmin, SystemAdmin. Azure AD groups are mapped to BTP Role Collections via IPS. CAP service uses CDS @restrict annotations for declarative scope checks on all OData entities and actions. Service-to-service calls from CAP to SAP AI Core use Client Credentials grant type. Principal propagation configured for audit trail — logged user identity flows through Cloud Connector to S/4HANA for all data access operations.

Best Practices

Define fine-grained scopes

Avoid a single admin scope for all privileged actions. Break permissions down by domain and action (customer.read, billing.read, billing.admin) to enable least-privilege RBAC.

Use CDS @restrict annotations in CAP

Declarative scope checks via @restrict are safer and more auditable than imperative xssec calls. CAP enforces them automatically at the OData layer.

Set token-validity to 3600s maximum

One hour is the maximum acceptable token validity for user tokens. Shorter is better — implement token refresh rather than extending validity.

Use Client Credentials for service-to-service

Service-to-service calls must use Client Credentials grant type (no user token). Never impersonate user tokens for backend communication.

Validate JWT on every request

Token validation must happen on every HTTP request — never cache scope decisions across requests. CAP does this automatically when XSUAA is bound.

Common Pitfalls

Granting uaa.admin scope to application users
uaa.admin gives full XSUAA administrative access — the ability to create and modify scopes for any application. Never include in application role templates.
Missing redirect-uris in xs-security.json
Without explicit redirect-uris, OAuth authorization code flow is vulnerable to redirect attacks. All callback URLs must be explicitly listed.
Using a monolithic admin scope
A single 'admin' scope makes RBAC impossible. You cannot grant a user billing access without also granting user management access if they share one scope.
Forgetting to bind XSUAA service to the app
Without the XSUAA service binding, CAP disables authentication. The VCAP_SERVICES environment variable must contain XSUAA credentials for token validation to activate.
Setting token-validity to 86400s
A 24-hour token validity means a compromised token grants access for an entire day. Always use 3600s (1 hour) maximum for user-facing applications.

JWT Security Controls

JWT tokens are bearer tokens — anyone with the token can use it. Apply these controls to limit blast radius:

Validate JWT on every HTTP request — never cache scope decisions across requests
Validate the aud (audience) claim matches your xsappname to prevent token replay across apps
Never log JWT token values — they are equivalent to passwords
Use short token validity (3600s / 1 hour) and implement refresh token rotation
Never pass JWT tokens between users or services that are not the intended audience
Monitor XSUAA audit events for unexpected scope escalation attempts or unusual grant patterns