Skip to Content
Technical Articles

Mapping of SAML attributes with XSUAA JWT in Cloud Foundry

Introduction

As working with Cloud foundry & Custom Identity Authentication, I come across one scenario where I wanted to get logged in user’s information with some add on attributes [eg. City, Country etc.] from IdP in my application.

Back to Neo environment, we just need to add assertion attributes in IAS which we wanted, then once user authenticated with IdP, we can directly get all attributes in SAML session itself.

But now in CF, The Application router is the entry point for the application The application router triggers the authentication process in UAA. At the time of user authentication process, the container security APIs receive an Authorization: Bearer HTTP header that contains an OAuth access token in the JWT format from the application router.

JSON Web Tokens (JWT) contains header and information (like issuer, expiration time, etc.) and is signed with a private key of the UAA service. JWT transmits information as JSON object. When trying to access the application, the user must get the JWT token from the security API after which the application opens a session for the access.

 

While digging into it more, I come to know that not all SAML attributes are directly mapped with JWT token, JWT  token only contains basic user identification information like name, email, userId etc.

 

In this blog post I will going to explain step by step on  how to get all SAML attributes from custom IdP, which are not available directly in user’s JWT.

Let’s Do it!

Prerequisites

  • SAP IAS Tenant Admin
  • SCP Cockpit with Security Admin Role

Steps

1) Setup trust between custom IAS & CF Cockpit

Follow steps mentioned in descriptive blog by Murali Shanmugham [Thank you 👍]

Building Portal Sites on SAP Cloud Platform Cloud Foundry – Configuring Identity Provider and Authentication setup

for configure Trust for your Identity Authentication Service & SCP CF Cockpit.

 

 

2) Expose SAML Assertion Attributes in IAS

Go to IAS Tenant admin, Navigate to Applications and choose your desired application and Select Assertion Attributes from Trust Tab.

 

 

Add SAML assertion attributes, you wanted in your application to be exposed,

In this example I wanted  Groups, Country, City & Employee Number of logged in user from IdP.

 

 

 

3) Set default value for SAML Group Attribute

Set any default value for Group attribute, this group attribute will be assigned to all existing and new registering user in your IdP.

This Group attribute value we need in next Step No. 6 for setting up Role Collection Mapping in SCP Cockpit.

Select Default Attributes from Trust Tab

 

 

I set value for Group attribute is “SAML_XSUAA_Group

 

 

4) Create a Simple NodeJS app

This app, we will use to demonstrate the user’s authenticated session response using XSUAA JWT

1. Create app.js file & paste below code

var express = require('express');
var app = express();
const request = require('request');
const bodyParser = require('body-parser');
var approuter = require('@sap/approuter');
const jwtDecode = require('jwt-decode');
var ar = new approuter();

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static(__dirname +'/'));

ar.beforeRequestHandler.use('/jwtdecode', function (req, res, next) {
	if (!req.user) {
	  res.statusCode = 403;
	  res.end(`Missing JWT Token`);
	} else {
	  res.statusCode = 200;
	  res.end(`${JSON.stringify(jwtDecode(req.user.token.accessToken))}`);
	} 
});
ar.start();

// serve app
app.get('/', function(req, res){
	res.sendFile('index.html');
	console.log('[server] index served');
});

 

2. Create package.json file & paste below code

{
  "name": "userinfo",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node app.js"
  },
  "author": "Prashant Patil",
  "license": "ISC",
  "dependencies": {
    "@sap/approuter": "6.5.0",
    "express": "*",
    "jwt-decode": "2.2.0",
    "request": "latest"
    
  }
}

 

3. Create xs-app.json file & paste below code

{
  "welcomeFile": "index.html",
  "authenticationMethod": "route",
  "routes": [
    {
      "source": "/*",
      "localDir": "./",
      "authenticationType": "xsuaa"
    }
  ]
}

 

4. Create xs-security.json file & paste below code

{
  "xsappname": "userInfo",
  "tenant-mode": "dedicated",
  "description": "Security profile of getuserinfo",
  "scopes": [
    {
      "name": "uaa.user",
      "description": "UAA"
    },
    {
      "name": "$XSAPPNAME.Display",
      "description": "display"
    }
  ],
  "attributes": [
    {
      "name": "Country",
      "description": "Country",
      "valueType": "s"
    },
    {
      "name": "City",
      "description": "City",
      "valueType": "string"
    },
    {
      "name": "EmployeeNum",
      "description": "EmployeeNum",
      "valueType": "int"
    },
    {
      "name": "Groups",
      "description": "Groups",
      "valueType": "s"
    }
  ],
  "role-templates": [
    {
      "name": "Token_Exchange",
      "description": "UAA",
      "scope-references": ["uaa.user"]
    },
    {
      "name": "Viewer",
      "description": "View all",
      "scope-references": ["$XSAPPNAME.Display"],
      "attribute-references": ["Country", "City", "EmployeeNum", "Groups"]
    }
  ]
}

Here I have created attributes which I wanted to be mapped with SAML attributes & created role template as “Viewer” & provided attribute references for this role template.

More details about Application Security Descriptor Config can be found  here .

 

5. Create XSUAA Service Instance

XSUAA service instance can be created using SCP Cokpit directly and select xs-security file in Specify Parameter steps

OR

Create using CF command line

cf create-service xsuaa application userinfo-uaa -c xs-security.json

 

6. Create manifest.yml file & paste below code

---
applications:
- name: user-info
  memory: 128M
  instances: 1
  services:
    - userinfo-uaa

Mention xsuaa service instance name which you just created in previous step.

 

7. Push application to the SCP

cf push user-info

 

Now if you run application directly,

App URL : https://<Application Route>/jwtdecode.

{
  "jti": "******",
  "ext_attr": {
    "enhancer": "XSUAA",
    "zdn": "********"
  },
  "xs.system.attributes": {
    "xs.saml.groups": [],
    "xs.rolecollections": []
  },
  "given_name": "Prashant",
  "xs.user.attributes": {},
  "family_name": "Patil",
  "sub": "********",
  "scope": [
    "openid",
    "uaa.user"
  ],
  "client_id": "********",
  "cid": "********",
  "azp": "********",
  "grant_type": "authorization_code",
  "user_id": "*******",
  "origin": "********",
  "user_name": "P000004",
  "email": "******@********.com",
  "auth_time": ****,
  "rev_sig": "****",
  "iat": ****,
  "exp": *****,
  "iss": "https://********/oauth/token",
  "zid": "*****",
  "aud": [
    "uaa",
    "openid"
    
  ]
}

 

You can observe this response only returns some of attributes related to logged in user like given_name, family_name, user_name, email.

Which is not solve our problem & that’s not the only information we wanted, So proceed for Next Step.

 

5) Map attributes exposed by your IdP to the attributes defined in your xs-security.json

Go to SCP Cockpit and navigate to your deployed application and click on Roles,

 

Click on “+” to add new Role, Here by default you can Token_Exchange role.

 

Choose “Role Template” which you created in xs-security file with attributes & Provide Role Name,

 

 

In next step, you can see all attributes listed which you mentioned in xs-security.json file, Select source as “Identity Provider” and in values provide same value which is exposed by IdP  as Assertion Attributes

 

 

In Next step, you can select Role Collection if you created already or just skip and later we can can assign this role to desired role collection. Review and click Finish.

 

6) Role Collection Mapping for custom IdP in Cockpit

Navigate to subacccount and click on Role Collections under Security menu, and click on ‘+’ to create new Role collection.

 

Click on your role collection and click Edit to add Role which we created in previous step &  Click on Save.

 

 

Now Navigate to Trust Configuration & Select your custom IdP,

 

Select Role Collection Mappings ,and Click on New Role Collection Mappings,

Select your Role Collection & assign default group value which we created in Step 3 and click on Save.

This mapping is for once user logged in using your custom IdP and access you application then this Role collection is assigned to the user id so that user’s JWT  token has all SAML attributes which we mapped.

 

Result

Now access your deployed application,

 

App URL : https://<Application Route>/jwtdecode.

 

Response : 

{
  "jti": "******",
  "ext_attr": {
    "enhancer": "XSUAA",
    "zdn": "********"
  },
  "xs.system.attributes": {
    "xs.saml.groups": [
      "SAML_XSUAA_Group"
    ],
    "xs.rolecollections": [
      "userinfo"
    ]
  },
  "given_name": "Prashant",
  "xs.user.attributes": {
    "City": [
      "Pune"
    ],
    "Country": [
      "IN"
    ],
    "EmployeeNum": [
      "760"
    ],
    "Groups": [
      "SAML_XSUAA_Group"
    ]
  },
  "family_name": "Patil",
  "sub": "********",
  "scope": [
    "userInfo!t159.Display",
    "openid",
    "uaa.user"
  ],
  "client_id": "********",
  "cid": "********",
  "azp": "********",
  "grant_type": "authorization_code",
  "user_id": "*******",
  "origin": "********",
  "user_name": "P000004",
  "email": "******@********.com",
  "auth_time": ****,
  "rev_sig": "****",
  "iat": ****,
  "exp": *****,
  "iss": "https://********/oauth/token",
  "zid": "*****",
  "aud": [
    "uaa",
    "userInfo!t159",
    "openid",
    "sb-userInfo!t159"
  ]
}

 

Now finally in this response you can observe all our mapped attributes which we wanted are now getting under key “xs.user.attributes”

 

 

Conclusion

With this blog post you learned,

  • How to configure Assertion & Default Attributes in IdP
  • How to Create & Deploy simple NodeJS app in CF
  • How to do Mapping of CF application attributes with attributes exposed by custom IdP

 

Hope this helps.

**********

 

 

Your feedback matters 😊!

 

 

Prashant Patil

 

 

 

 

 

7 Comments
You must be Logged on to comment or reply to a post.