Skip to Content
Technical Articles
Author's profile photo Prashant Patil

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

 

 

 

 

 

Assigned Tags

      15 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Devashish Nayak
      Devashish Nayak

      Great work Prashant, keep it up.

      Author's profile photo Prashant Patil
      Prashant Patil
      Blog Post Author

      Thank you Devoo!

      Author's profile photo Nikita Bachal
      Nikita Bachal

      This is a great piece of content and yet helpful. Thank you for sharing this Prashant.

      Author's profile photo Prashant Patil
      Prashant Patil
      Blog Post Author

      Thank you Nikita!

      Author's profile photo Andrew WU
      Andrew WU

      Hi Prashant

      Thank you for sharing this great blog post. I’m wondering if you could help me out with my issue with CF XSUAA services with custom idp and SAP Cloud Integration.

      Our app is a multi-tenant application set up with xsuaa and custom idp, it all works perfectly when accessing from browser. Now we need to receiving data from SCI (SAP Cloud Integration), according to their documentation: https://help.sap.com/viewer/368c481cd6954bdfa5d0435479fd4eaf/Cloud/en-US/92dd2a6fdb6045f98d23c828d1567fef.html. The supported methods are basic authentication and Client Certificate Authentication.

      For the client credential, it seems xsuaa doesn’t support grant_type “password”, see: https://launchpad.support.sap.com/#/notes/2766354

      Could you help to see if there is a solution for this issue?

      Cheer

      Andrew

      Author's profile photo Gregor Wolf
      Gregor Wolf

      Hi Prashant,

      thank you for this great description. I've included your example in my demo application HTML5UserAPIforCF which can be deployed by building & deploying the MTA. Then only the creation of the Role to map the Attributes is needed.

      Best regards
      Gregor

       

      Author's profile photo Prashant Patil
      Prashant Patil
      Blog Post Author

      Gregor Wolf : Wow that's great, Thank you.

      Author's profile photo Mohamed AHARCHI
      Mohamed AHARCHI

      Exactly what I wanted! Very helpful, thanks

      Author's profile photo Kishan Panara
      Kishan Panara

      Hi Prashant Patil,

      Thanks for the wonderful blog.

      I am able to get the SAML attributes. Now I want to use this attributes in another HTML5 applications.

      I tried to create destination to deployed app and try to consume that in HTML5, but its giving error like Unauthorized.

      Do you have any idea how can I resolve this Unauthorized issue?

       

      Thanks in advance.

       

      Best regards,

      Kishan Panara

      Author's profile photo Prashant Patil
      Prashant Patil
      Blog Post Author

      Hi Kishan,

       

      What is Authentication method for the destination?

       

      Regards,

      Prashant

      Author's profile photo Kishan Panara
      Kishan Panara

      Hi Prashant,

      Thank you for the reply.

      I tried

      1. No authentication, then from UI5 its shows authentication error,
      2. OAuth2UserTokenExchange, here for client Id, secrets and toekn URL taken from userInfo-UAA service key. But still no luck.

      Do you have any pointer on this.

       

      Regards,

      Kisahn Panara

      Author's profile photo Prashant Patil
      Prashant Patil
      Blog Post Author

      OAuth2UserTokenExchange should work. Re-verify the credentials & properties of destination.

      Author's profile photo FEDOR SHESTOV
      FEDOR SHESTOV

      Any luck? I created a new desination, added a service to xs-app,json  and added a service with url but it returnes error 500?

      Author's profile photo Manuel Seeger
      Manuel Seeger

      If you are looking to map a custom attribute from IAS to your application, be aware that custom attributes need to be mapped as default attributes per note https://launchpad.support.sap.com/#/notes/3193175

      And not as an assertion attribute as described in this blog.

      Author's profile photo FEDOR SHESTOV
      FEDOR SHESTOV

      include in xs-security.json "foreign-scope-references": ["user_attributes"]