Saturday, November 3, 2012

WSO2 Identity Server as a SCIM Service Provider

As I have blogged in my previous posts, we have developped WSO2 Charon as an open source implementation of SCIM protocol which is an open standard for Identity Provisioning.

It can be used by any one who wants to add SCIM based provisioning support for their applications.

We have integrated WSO2 Charon with WSO2 Identity Server 4.0.0which is available to be downloaded at http://wso2.com/products/identity-server/

In this post, I am going to demonstrate how to utilize its SCIM endpoints which expose User and Group resources in Restful way.

Following is a high level overview of SCIM Service Provider architecture of IS.

For simplicity, I will use curl commands to send CRUD requests to the rest endpoints of Identity Server.

Download Identity Server from above link, unzip it and start...

URL of the SCIM User Endpoint is: https://localhost:9443/wso2/scim/Users
URL of the SCIM Group Endpoint is: https://localhost:9443/wso2/scim/Groups

These endpoints are exposed over https since sensitive information is exchanged and also protected with Basic Auth Authentication.

Create User:
curl -v -k --user admin:admin --data "{"schemas":[],"name":{"familyName":"gunasinghe","givenName":"hasinitg"},"userName":"hasinitg","password":"hasinitg","emails":[{"primary":true,"value":"hasini_home.com","type":"home"},{"value":"hasini_work.com","type":"work"}]}" --header "Content-Type:application/json" https://localhost:9443/wso2/scim/Users

Here we authenticate with Basic Auth and send the payload in JSON format adhering to the SCIM 1.1 specification.

You will get a response with 201 CREATED status and pay load as below:
{"id":"48f7cfe5-f0e3-4a67-af7e-d762aa9ab215","schemas":["urn:scim:schemas:core:1.0"],"name":{"familyName":"gunasinghe","givenName":"hasinitg"},"userName":"hasinitg","emails":[{"value":"hasini_home.com","type":"home"},{"value":"hasini_work.com","type":"work"}],"meta":{"lastModified":"2012-11-03T18:36:53","location":"https://localhost:9443/wso2/scim/Users/48f7cfe5-f0e3-4a67-af7e-d762aa9ab215","created":"2012-11-03T18:36:53"}}

There, you will notice that it contains some additional attributes such as unique id, created, last modified and location which are READ ONLY attributes and set by the service provider.

Now access the management console of Identity Server in a browse with URL:
https://localhost:9443/carbon/admin/login.jsp and login as admin with credential admin.

You will notice that the above created user is shown under:

You can access user profile of the user and see first name and last name are set properly but not other fields. That is because default claims of Carbon uses a different set of attributes in LDAP than the SCIM specific dialect (will discuss about it in detail later).

But those attributes are stored in the underlying user store. You can verify that by going a GET request on the User.

GET User:
You can retrieve a particular user resource using its unique id:

curl -v -k --user admin:admin https://localhost:9443/wso2/scim/Users/48f7cfe5-f0e3-4a67-af7e-d762aa9ab215

You will notice that all the attributes that were sent are there in the response as well.

List Users:
Now create some users through the web management console of Identity Server and fill in their profile details. I created two users called Umesha and Shyama and filled in their profile details.

curl -v -k --user admin:admin https://localhost:9443/wso2/scim/Users

Response:

{"schemas":["urn:scim:schemas:core:1.0"],
"totalResults":3,
"Resources":
[
 {"id":"48f7cfe5-f0e3-4a67-af7e-d762aa9ab215","name": {"familyName":"gunasinghe","givenName":"hasinitg"},"userName":"hasinitg","emails":[{"value":"hasini_work.com","type":"work"},{"value":"hasini_home.com","type":"home"}],"meta":{"lastModified":"2012-11-03T18:36:53","created":"2012-11-03T18:36:53","location":"https://localhost:9443/wso2/scim/Users/48f7cfe5-f0e3-4a67-af7e-d762aa9ab215"}},

{"id":"8dd71de9-e2f9-47b7-a5d4-a5f3862950ff","profileUrl":"shyama@blogspot.com","ims":["gmail"],"roles":["everyone"],"name":{"familyName":"shyama","givenName":"Shyama"},"userName":"shyama","emails":["shyama@example.com"],"phoneNumbers":[{"value":"7890","type":"mobile"}],"addresses":[{"value":"Panadura","type":"streetAddress"},{"value":"Sri Lanka","type":"country"}],"meta":{"lastModified":"2012-11-03T18:53:46","created":"2012-11-03T18:52:41"}},

{"id":"6b14c23d-4811-4bbd-b653-04fcda2df266","profileUrl":"umesha@blogspot.com","ims":["gmail"],"roles":["everyone"],"name":{"familyName":"umesha","givenName":"Umesha"},"userName":"umesha","emails":["umesha@gmail.com"],"phoneNumbers":[{"value":"857657","type":"mobile"}],"addresses":[{"value":"Pannipitiya","type":"streetAddress"},{"value":"Sri Lanka","type":"country"}],"meta":{"lastModified":"2012-11-03T18:51:52","created":"2012-11-03T18:50:26"}}
 ]
}

You can see the three users representation with attributes in JSON format adhering to SCIM Schema.

Update User:
I am going to update the work and home email of user: hasinitg through following curl command:

Note: you have to use the correct SCIM ID by taking it either from create user response or from list user response.

curl -v -k --user admin:admin -X PUT -d "{"schemas":[],"name":{"familyName":"gunasinghe","givenName":"hasinitg"},"userName":"hasinitg","emails":[{"value":"hasini@wso2.com","type":"work"},{"value":"hasi7786@gmail.com","type":"home"}]}" --header "Content-Type:application/json" https://localhost:9443/wso2/scim/Users/48f7cfe5-f0e3-4a67-af7e-d762aa9ab215

You will get a response with 200 OK response and a payload containing the updated user representation.

Delete User:
Now I will delete the user with userName 'shyama' which was created through management console of IS:

curl -v -k --user admin:admin -X DELETE https://localhost:9443/wso2/scim/Users/8dd71de9-e2f9-47b7-a5d4-a5f3862950ff -H "Accept: application/json"

You will get a response with status 200 OK and the user will be deleted from the user store.

In the same way, we can manage groups by performing CRUD operations on the Group resource endpoint.

Filter User:
Since CRUD operations have to be performed using SCIM ID which is unique to Service Provider, User REST endpoint also supports filter operation. You can filter users with userName which is considered as the unique user attribute in Carbon servers.

curl -v -k --user admin:admin https://localhost:9443/wso2/scim/Users?filter=userNameEqumesha

You will get a response like below from which you can extract the SCIM ID to perform rest of the operations.

{"schemas":["urn:scim:schemas:core:1.0"],"totalResults":1,"Resources":[{"id":"6b14c23d-4811-4bbd-b653-04fcda2df266","profileUrl":"umesha@blogspot.com","ims":["gmail"],"roles":["everyone"],"name":{"familyName":"umesha","givenName":"Umesha"},"userName":"umesha","emails":["umesha@gmail.com"],"phoneNumbers":[{"value":"857657","type":"mobile"}],"addresses":[{"value":"Pannipitiya","type":"streetAddress"},{"value":"Sri Lanka","type":"country"}],"meta":{"lastModified":"2012-11-03T18:51:52","created":"2012-11-03T18:50:26"}}]}

Create Group: 
You can create groups either with or without members.
Following command creates a group with a user.

Note: when creating a group with users, you need to have that user already existing in the user store and provide its unique id. So lets create a new group named: 'engineer'  with user 'umesha' as a member.

curl -v -k --user admin:admin --data "{"displayName": "engineer","members": [{"value":"6b14c23d-4811-4bbd-b653-04fcda2df266","display": "umesha"}]}" --header "Content-Type:application/json" https://localhost:9443/wso2/scim/Groups 

You will get a response with payload like below and a response status 201 CREATED:

{"id":"e8868723-30b2-4979-ae23-6d1de2e7d841","schemas":["urn:scim:schemas:core:1.0"],"displayName":"engineer","members":[{"value":"6b14c23d-4811-4bbd-b653-04fcda2df266","display":"umesha"}],"meta":{"lastModified":"2012-11-03T20:33:16","created":"2012-11-03T20:33:16","location":"https://localhost:9443/wso2/scim/Groups/e8868723-30b2-4979-ae23-6d1de2e7d841"}} 

You can observe in the management console of IS, that the new group is listed under roles  and user Umesha is listed under users of that group.

List Groups: 
Now lets create another role through IS management console and list all the groups. Create a group named: 'manager' without any users added to it.

Now list the groups: You can see both groups are listed.
{"schemas":["urn:scim:schemas:core:1.0"],
 "totalResults":2,"Resources":[
{"id":"e8868723-30b2-4979-ae23-6d1de2e7d841","displayName":"engineer","members":[{"value":"6b14c23d-4811-4bbd-b653-04fcda2df266","display":"umesha"}],"meta":{"lastModified":"2012-11-03T20:33:16","created":"2012-11-03T20:33:16","location":"https://localhost:9443/wso2/scim/Groups/e8868723-30b2-4979-ae23-6d1de2e7d841"}},

{"id":"3f26902e-c22b-48bc-ba0a-c197a5710b70","displayName":"manager","meta":{"lastModified":"2012-11-03T20:39:25","created":"2012-11-03T20:39:25","location":"https://localhost:9443/wso2/scim/Groups3f26902e-c22b-48bc-ba0a-c197a5710b70"}}
]}

Update Group: 
Now lets rename the group 'manager' to executive:

curl -v -k --user admin:admin -X PUT -d "{"displayName": "executive"}" --header "Content-Type:application/json" https://localhost:9443/wso2/scim/Groups/3f26902e-c22b-48bc-ba0a-c197a5710b70 

You will get a response with 200 OK status and full JSON representation of the updated group.

Delete Group: 
You can delete the group using the unique SCIM Id of the group. Following command will delete the group: 'executive'

curl -v -k --user admin:admin -X DELETE https://localhost:9443/wso2/scim/Groups/3f26902e-c22b-48bc-ba0a-c197a5710b70 -H "Accept: application/json" 

Filter Group: 
You can filter groups with the group display name. Following command will filter the group with display name: 'engineer'

curl -v -k --user admin:admin https://localhost:9443/wso2/scim/Groups?filter=displayNameEqengineer

Response:
{"schemas":["urn:scim:schemas:core:1.0",null],"totalResults":1,"Resources":[{"id":"e8868723-30b2-4979-ae23-6d1de2e7d841","displayName":"engineer","members":[{"value":"6b14c23d-4811-4bbd-b653-04fcda2df266","display":"umesha"}],"meta":{"lastModified":"2012-11-03T20:33:16","created":"2012-11-03T20:33:16","location":"https://localhost:9443/wso2/scim/Groups/e8868723-30b2-4979-ae23-6d1de2e7d841"}}]} 

 

14 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Is it possible to specify filter based on schema? For ex: Lets say that the ServiceProvider supports base schema (urn:scim:schemas:core:1.0) and extension schema (ex: urn:scim:schemas:extension:enterprise:1.0). The consumer is interested only in the data of one of the schema's. Is it possible to specify the specific schema in the filter request?

    -Karthik

    ReplyDelete
  3. Is there a way to update a role for a user using SCIM user or groups endpoint? I tried the following and neither works to assign a role to a user:
    1. Create a user with a role assigned to him:
    curl -v -k --user admin:admin --data "{"schemas":[],"name":{"familyName":"FN_atest2","givenName":"LN_atest2"},"userName":"atest2","password":"perf","groups":[{"value":"c83dc72c-15c2-40f2-bddd-4acb086b9e17","display":"Employee"}]}" --header "Content-Type:application/json" https://localhost:9443/wso2/scim/Users

    2. Update the user after it is created:
    curl -v -k --user admin:admin -X PUT --data "{"schemas":[],"name":{"familyName":"FN_atest2","givenName":"LN_atest2"},"userName":"atest2","password":"perf","groups":[{"value":"c83dc72c-15c2-40f2-bddd-4acb086b9e17","display":"FleetPlanner"}]}" --header "Content-Type:application/json" https://localhost:9443/wso2/scim/Users/17ebb35d-62af-4cd3-b440-21bcf80714fc

    Can you let me know if there is way I can assign a existing role to a user from commandline using curl?
    Thanks.

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. You can not assign/un-assign role to an user using SCIM User endpoint. But you can do vice-versa i.e. assign/un-assign user to a group via SCIM Group endpoint.

    Curl command -

    curl -v -k --user admin:admin -X PUT -d "{"members": [{"value":"","display": "display_name_of_user_to_be_added"}]"} --header "Content-Type:application/json" https://localhost:9443/wso2/scim/Groups/

    ReplyDelete
    Replies
    1. This appears to break if you're trying to un-assign a user from the group where the only member of that group is the user you're trying to un-assign, ie:

      curl -v -k --user admin:admin -X PUT -d "{"displayName":"Manager","members":[]}" --header "Content-Type:application/json" https://localhost:9443/wso2/scim/Groups/{groupId}

      Results in this stacktrace:

      java.lang.NullPointerException
      org.wso2.charon.core.objects.Group.getMembersWithDisplayName(Group.java:153)
      org.wso2.carbon.identity.scim.provider.impl.SCIMUserManager.updateGroup(SCIMUserManager.java:613)
      org.wso2.charon.core.protocol.endpoints.GroupResourceEndpoint.updateWithPUT(GroupResourceEndpoint.java:469)
      org.wso2.carbon.identity.scim.provider.resources.GroupResource.updateGroup(GroupResource.java:314)

      Delete
    2. Any idea on how to un-assign a user from a group when the user you're trying to un-assign is the only user in that group?

      Delete
  6. For create User : "userName": "ldap/testuser" works fine but for Create group "displayName": "ldap\engineer" says synatatically incorrect. How we can add role to ldap(secondary user storage) usim scim?

    ReplyDelete
  7. Can we add a user to existing group ???

    ReplyDelete
  8. is it possible to add multiple users using curl command??

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete
  10. Is it possible to add multiple groups in a single request using curl command?

    ReplyDelete
  11. How can we filter users according to their role? Is there a filter operation?
    I use filter operation for groups but it only return user IDs. So we need to call again to retrieve each and every user separately. This is bit hassle and not good for performance.

    Do you have a suggestion?

    ReplyDelete
  12. Can you please help me with
    http://stackoverflow.com/questions/25160424/exception-while-creating-user-in-wso2-via-scim-rest-api

    ReplyDelete

Note: Only a member of this blog may post a comment.