Shared attributes

According to the SWITCH edu-ID architecture, there are three sources for attributes of a user:

  1. The user, by self-declaring personal information in My Account,
  2. The participating organisations - universities who define attributes of affiliated users,
  3. Complementary attribute sources.

The shared attribute service described here is a complementary attribute source. It allows basically arbitrary services or applications (a client) to set specific attribute values for users. These attributes can then be made available to selected services.

  • For each user, the client can set or reset a predefined yes/no property. It is represented in the API as group membership: the user is either member of a group or not.
  • The yes/no property is translated by the SWITCH edu-ID IdP into an attribute value. The attribute is either present or not.
  • The attribute value will only be seen by a set of selected SPs

Typical applications are:

  • An organization gives access to their resources by setting an organizational membership flag for their members.
  • The National Licenses registration platform entitles users to access to research publications at various publishers.
  • A university needs to collaborate with people who are not official university member. A registration platform of for temporary members taggs selected user as "affiliates", and gives them access to collaboration platforms.

Prerequisites:

  • Consuming SPs need to support (=understand) the specific attribute value
  • To use the API and to define groups an agreement has to be made between the client and SWITCH. Please contact the edu-ID team:

Current limitations:

API to set and share selected attributes

The shared attribute API uses a subset of the SCIM specification to set and reset group memberships.

Roles:

  • SWITCH edu-ID is SCIM service provider
  • an external service is SCIM client

Authentication and permissions:

Basic Authentication. An API-user is set up by the SWITCH edu-ID team on request.

The permissions of an API-user can be adjusted finely. Depending on the requirements, the following permissions can be granted to an API-user: GET-Users, POST-Users, PATCH-Groups, GET-Groups, POST-Groups.

Attributes supported in the profile:

  • Users:
    • id : issued by the SCIM service
    • externalID: corresponds to the SWITCH edu-ID unique ID
  • Groups:
    • id: issued by the SCIM service

Basic steps to set and reset group memberships for a user:

  1. Create a user (users-POST request) with the Swiss edu-ID unique-ID as externalID
    1. This returns a record with an internal ID of that user
    2. The POST request can be repeated without any harm
  2. To retrieve the user’s group membership make a users-GET request and read the groups object
  3. To add a user to a group make a groups-PATCH request
  4. To remove a user from a group make a groups-PATCH request with a path expression
  5. To retrieve the members of a group make a groups-GET request

The required group(s) will be created for the client by the SWITCH edu-ID team.

SCIM API Reqeuests

API endpoints:

In the examples below, the REST service endpoint base url is https://eduid.ch/sg/index.php/.

Create a new user

Before a user can be associated to groups, an internal user record has to be created. The record contains the internal identifier "id", which is used to add or remove a user in a group.

POST /sg/index.php/Users

The body must contain information about the new user in JSON format as shown in the following example:

{
  "externalID":"1234567@eduid.ch" 
}

Results:

HTTP/1.1 200 OK
Content-Type: application/scim+json
{
  "id":"2819c223-7f76-453a-919d-413861904646",
  "externalID":"1234567@eduid.ch",
  "meta":  {
    "created":"2016-07-24T11:29:51Z",
    "modified":"2016-07-24T11:51:09Z" 
  },
  "schemas":  ["urn:ietf:params:scim:schemas:core:2.0:User"]
}

Notes:

  • If the user with externalID already exists, 200 OK is returned including the result body, and no data is modified in the directory.
  • externalID can be any identifier that is shared by SPs who share group information. In most cases it is recommended to use swissEduPersonUniqueID as externalID. SPs that are part of the organizational identity management processes may also use the identifier swissEduId.

Add a user to a group

To add an existing user (with the internal "id" 2819c22...) to an existing group (acbf3ae...):

PATCH /Groups/acbf3ae7-8463-425b-bded-9b4da3f908ce
Content-Type: application/scim+json

{ "schemas":  ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations":[
   {
    "op":"add",
    "path":"members",
    "value":[
     {
       "$ref": "https://eduid.ch/sg/index.php/Users/2819c223...413861904646",
       "value": "2819c223-7f76-453a-919d-413861904646" 
     }
    ]
   }
 ]
}

Response: (if successful)

HTTP/1.1 204 No Content
Location: "https://eduid.ch/sg/index.php/Groups/acbf3ae7-8463-...-9b4da3f908ce" 

Remove a user from a group

To remove the member (with the internal "id" 2819c22...) from the group (acbf3ae...) use a PATCH operation with a path expression:

PATCH /sg/index.php/Groups/acbf3ae7-8463-425b-bded-9b4da3f908ce
Accept: application/scim+json
Content-Type: application/scim+json

{
 "Schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
 "Operations":[{
   "op":"remove",
   "path":"members[value eq \"2819c223-7f76-...413861904646\"]" 
 }]
}

Response:

Retrieve all members of a group

Find all users in an existing group (acbf3ae...):

GET /Groups/acbf3ae7-8463-425b-bded-9b4da3f908ce

Example response: (if successful)

HTTP/1.1 200 OK 
Content-Type: application/scim+json

{
"id":"acbf3ae7-8463-425b-bded-9b4da3f908ce",
"displayName":"Test Group",
"schemas":["urn:ietf:params:scim:schemas:core:2.0:Group"],
"members":[
{"value":"2819c223-7f76-453a-919d-413861904646", "display":" "},
{"value":"c626d45b-2bbd-483d-8d34-9c1c6dc5fdc3", "display":" "}
]
}

Note: To use this function, the API user needs to have the permission "GET-groups".

Retrieve an internal User-ID by the Swiss edu-ID unique ID

Request:

GET /sg/index.php/Users?filter=externalID eq “1234567@eduid.ch”
Host: eduid.ch
Accept: application/scim+json


Example response:

HTTP/1.1 200 OK
Content-Type: application/scim+json

{
 "schemas":["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
 "totalResults":1,
 "Resources":[
   {
     "id":"e64a2bef-02f2-4a67-8f29-6121a8f4aff3",
   }
 ]
}

Retrieve a user by the internal User-ID

and check his/her group membership:

GET /sg/index.php/Users/e64a2bef-02f2-4a67-8f29-6121a8f4aff3

Example response:

HTTP/1.1 200 OK
Content-Type: application/scim+json

{
  "id":"e64a2bef-02f2-4a67-8f29-6121a8f4aff3",
  "externalID":"1234567@eduid.ch",
  "groups":  [
        {
      "value":"acbf3ae7-8463-425b-bded-9b4da3f908ce",
      "display":"Test Group" 
    }
  ],
  "schemas":  ["urn:ietf:params:scim:schemas:core:2.0:User"]
}

This user is a member of the group “National Library License Compliant”

Error responses

Error responses that can be issued for all of the above GET, POST and PATCH requests:

The authentication failed

Response:

HTTP/1.1 401 Unauthorized
Content-Type: application/scim+json
Not authorized

The authentication was ok, but the client is not authorized to do this operation.
Response:

HTTP/1.1 403 Forbidden
Content-Type: application/scim+json
Not found

If the referenced user or group does not exist.
Response:

HTTP/1.1 404 Not Found
Content-Type: application/scim+json

Test Sequence Example

  • Endpoint base URL: https://test.eduid.ch/sg/index.php/
  • User external ID: 1234567@eduid.ch
  • Group internal ID: f4d40595-6d7d-41bc-9fa2-7139d2fcf892

1) Create a user (can also be safely used to determine the internal 'id' of an existing user)

curl --user apiuser:passwd -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data '{ "externalID":"1234567@eduid.ch" }' https://test.eduid.ch/sg/index.php/Users

Response:

{"externalID":"1234567@eduid.ch","schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"id":"6943fc0d-61a5-4dc8-a7fa-234243323a49"}

2) Get the user, and his/her group membership information using the internal id

curl --user apiuser:passwd https://test.eduid.ch/sg/index.php/Users/6943fc0d-61a5-4dc8-a7fa-234243323a49

Response:

{"id":"6943fc0d-61a5-4dc8-a7fa-234243323a49","externalID":"1234567@eduid.ch","schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"groups":[]}

(here, the user belongs to no group)

3) Add a user

add the user 6943fc0d-61a5-4dc8-a7fa-234243323a49 to the group f4d40595-6d7d-41bc-9fa2-7139d2fcf892 :

Precondition: the user and the group must already exist

curl --user apiuser:passwd -X PATCH \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data '{ "schemas":  ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations":[
   {
    "op":"add",
    "path":"members",
    "value":[
     {
      "$ref": "https://test.eduid.ch/sg/index.php/Users/6943fc0d-61a5-4dc8-a7fa-234243323a49",
"value": "6943fc0d-61a5-4dc8-a7fa-234243323a49" 
     }
     ]
   }
  ]
}' https://test.eduid.ch/sg/index.php/Groups/f4d40595-6d7d-41bc-9fa2-7139d2fcf892

Response:

HTTP/1.1 200 OK

4) Get the user, and his/her group membership information using the internal id

curl --user apiuser:passwd https://test.eduid.ch/sg/index.php/Users/6943fc0d-61a5-4dc8-a7fa-234243323a49

Response:

{"id":"6943fc0d-61a5-4dc8-a7fa-234243323a49","externalID":"1234567@eduid.ch","schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"groups":[{"value":"f4d40595-6d7d-41bc-9fa2-7139d2fcf892","display":"National Licenses Programme"}]}

The groups object is not empty now.

5) Remove a user

Remove the user 6943fc0d-61a5-4dc8-a7fa-234243323a49 from the group f4d40595-6d7d-41bc-9fa2-7139d2fcf892 :

curl --user apiuser:passwd -X PATCH \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data '{ "schemas":  ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations":[
   {
    "op":"remove",
    "path":"members[value eq \"6943fc0d-61a5-4dc8-a7fa-234243323a49\"]" 
   }
  ]
}' https://test.eduid.ch/sg/index.php/Groups/f4d40595-6d7d-41bc-9fa2-7139d2fcf892

Response:

HTTP/1.1 200 OK

Web GUI

The above requests can also be made using the human-friendly web GUI that is available here:

GUI endpoints:

To access the GUI, client credentials are required.

Example case: National licenses (shared yes/no property)

In the national licenses case a registration service decides for each user if he/she is entitled to have access to contents of publishers who participate in the programme. For each user who has access, the shared property “national-license-compliant” is written to a shared database. The Swiss edu-ID IdP reads the shared database and sets the attribute “common-lib-terms” for the users who are entitled to have access to the contents.

SCIM-Privisioning-diagram

In this use case, SWITCH edu-ID acts as a SCIM service and the national license registration platform as SCIM client.

Available SCIM API endpoints:

  • POST /Users
  • GET /Users/{id}
  • GET /Users?filter
  • PATCH /Groups
  • POST /Groups (not for public use)
  • PUT /Groups (not for public use)
  • DELETE /Groups (not for public use)

Example case: Grant access to digital content for private cantonal library members

Cantonal libraries are legally mandated to provide access to digital publications to their patrons. These are typically private persons who meet particular conditions like

  • They are mostly cantonal residents
  • They showed up in person at a library’s service desk for registration

Case-Cantonal-Libraries

Example case: Manage loosely coupled affiliates at FHNW

Requirements:

  • The organization needs to manage accounts for affiliates
  • The affiliates are not enrolled at the organization and they do not get an organizational account

Solution concept:

  • The affiliates get a SWITCH edu-ID...
  • ... and registered at a registration service of the organization
  • the organization sets the shared property "org-affiliate" for selected users
  • the edu-ID IdP translates the property to an entitlement attribute

Save

Save