sapui5tutors SAPUI5 • Fiori • SAP BTP Step-by-step tutorials Real project examples Interview Q&A
Practical SAPUI5 • Fiori • SAP BTP tutorials and interview prep

CAPM Authentication: XSUAA Setup Step by Step

From anonymous to authenticated

Local development runs without security — convenient, until you deploy. Production CAP apps on BTP authenticate users through XSUAA (Authorization and Trust Management). Here's the full setup, end to end.

Authentication answers "who are you?" Authorization answers "what may you do?" This post covers the first; the next covers the second.


Step 1: The security descriptor

Create xs-security.json in your project root:

{
  "xsappname": "bookshop",
  "scopes": [
    { "name": "$XSAPPNAME.admin", "description": "Admin access" },
    { "name": "$XSAPPNAME.viewer", "description": "Read access" }
  ],
  "role-templates": [
    { "name": "admin", "scope-references": ["$XSAPPNAME.admin"] },
    { "name": "viewer", "scope-references": ["$XSAPPNAME.viewer"] }
  ]
}

Scopes are the permissions your app defines; role templates bundle them into assignable roles.


Step 2: Wire it into the MTA

In mta.yaml, add the XSUAA resource and bind your backend to it:

resources:
  - name: bookshop-auth
    type: org.cloudfoundry.managed-service
    parameters:
      service: xsuaa
      service-plan: application
      path: ./xs-security.json

On deploy, BTP creates the XSUAA service instance from this descriptor and injects the credentials into your app.


Step 3: Add the approuter

Users never call your backend directly — the approuter handles login and forwards the JWT:

{
  "welcomeFile": "index.html",
  "authenticationMethod": "route",
  "routes": [
    { "source": "^/odata/(.*)$", "target": "$1",
      "destination": "srv-api", "authenticationType": "xsuaa" },
    { "source": "^(.*)$", "target": "$1",
      "localDir": "resources" }
  ]
}

Unauthenticated users hitting /odata/… get redirected to the identity provider login. After login, the JWT flows to your service on every request.


Step 4: Assign roles and test

  • Create role collections in the BTP cockpit from your role templates.
  • Assign users to the collections.
  • Test — hit the app URL in an incognito window; you should land on the login page.
  • Check req.user in a handler to see the authenticated identity and scopes.

Local testing with auth: cds bind or mock users via [development] users config — don't deploy just to test login.


How the JWT flows

Understanding the token flow demystifies most XSUAA issues. The user logs in through the identity provider; the approuter receives the ID token, exchanges it for a JWT scoped to your xsappname, and forwards it to your backend.

Your CAP service validates the JWT signature against XSUAA's public keys and populates req.user: the user ID, scopes, and any custom attributes. Handlers and @restrict rules read from this — never from client-supplied headers.

When authentication breaks, check the chain in order: approuter routes, XSUAA binding, then the JWT contents (decode it at jwt.io — expiry and audience issues are visible immediately).


Security is infrastructure, not code

Notice how little application code this took: a JSON descriptor, MTA wiring, approuter routes. CAP keeps authentication declarative — your handlers just read req.user.

XSUAA errors cryptic? Paste them in the comments.