How to use the GMS API
What are the endpoints?
GMS endpoints are a subset of the Authorization Service API. You can use standard REST API GET, POST PUT, DELETE and PATCH requests to manage your groups.
How can you call it?
The API is protected by OpenID Connect (OIDC). To call it you must provide a token, such as in the example below. Tokens are encoded JSON objects. The sub
(subject JSON attribute) of the token is interpreted as the request caller. The aud
(audience JSON attribute) of the token must be set to authorization-service-api
.
### Call the Authorization Service API using your the exchanged token
API_RESPONSE=$(curl \
-X GET "https://authorization-service-api.web.cern.ch/api/v1.0/Group/my-group" \
-H "Accept: */*" \
-H "Authorization: Bearer $API_ACCESS_TOKEN" )
echo $API_RESPONSE
How can I get a token?
Typically you would want to call the API programatically using an authenticated client, rather than as a user or as yourself. A client is technically an Open ID Connect client registered in the Authentication service with its own client ID and client secret.
CERN's Authentication service (auth.cern.ch) has a dedicated endpoint that clients can
call to get a token that is valid for a particular audience. Please read the API Access Guide for full instructions on how to create your client and generate an API Access Token. For GMS the audience for the API Access Token request must be authorization-service-api
.
How can I manage a group using a client?
To manage a group, a client must be a member of the administrator group of the group that you wish to manage. You can set this up through the GMS Portal.
Best practices and tips
- E-groups cannot be managed by the GMS API. Migrate your E-groups to GMS first.
- For full compatibility with downstream systems ensure that your groups and their administrator groups all have their Synchronisation Type =
Primary
- If your client needs to read all groups, add it to the
authorization-service-groups-readers
group. The API managers will need to give their approval - Memberships are returned as a paginated object
Example
The following is an example in Python. It is provided to help you get started as easily as possible but may not be actively updated.
import requests
import json
import sys
import os
# === Configuration ===
client_id = "group-manager-hannah" # Replace with your client ID
client_secret = "X" # Replace with your client secret
group_id = "group-to-be-managed" # Replace with the group ID you're managing
file_path = 'upns.txt' # Path to the file with UPNs (one per line)
keycloak_api_token_endpoint = "https://auth.cern.ch/auth/realms/cern/api-access/token"
authzsvc_endpoint = "https://authorization-service-api.web.cern.ch/api/v1.0/"
# === Get API Token ===
print("Getting API token...")
try:
token_resp = requests.post(
keycloak_api_token_endpoint,
data={
"grant_type": "client_credentials",
"client_id": client_id,
"client_secret": client_secret,
"audience": "authorization-service-api"
},
headers={"Content-Type": "application/x-www-form-urlencoded"}
)
token_resp.raise_for_status()
api_token = token_resp.json()['access_token']
print("Token received.\n")
except Exception as e:
print("Failed to get API token:", e)
sys.exit(1)
# === Get Group Info ===
def get_group_info():
print("Fetching group details...")
group_resp = requests.get(
f"{authzsvc_endpoint}Group/{group_id}",
headers={"Authorization": f"Bearer {api_token}"}
)
group_resp.raise_for_status()
print("Group info retrieved.\n")
return group_resp.json()
# === Get Current Identity Members ===
def get_group_identity_members():
print("Getting current group identity members...")
members_resp = requests.get(
f"{authzsvc_endpoint}Group/{group_id}/members/identities",
headers={"Authorization": f"Bearer {api_token}"}
)
members_resp.raise_for_status()
return members_resp.json()
# === Get Current Group Members ===
def get_group_group_members():
print("Getting current group group members...")
members_resp = requests.get(
f"{authzsvc_endpoint}Group/{group_id}/members/groups",
headers={"Authorization": f"Bearer {api_token}"}
)
members_resp.raise_for_status()
return members_resp.json()
# === Read UPNs From File ===
def read_upns():
print(f"Reading UPNs from '{file_path}'...")
if not os.path.exists(file_path):
print(f"File not found: {file_path}")
sys.exit(1)
with open(file_path, 'r') as f:
upn_list = [{"id": line.strip()} for line in f if line.strip()]
if not upn_list:
print("No valid UPNs found in the file.")
sys.exit(1)
print(f"{len(upn_list)} UPNs read.\n")
return upn_list
# === Add UPNs to Group ===
def add_upns_to_group(upns):
print("Adding new UPNs to group...")
post_resp = requests.post(
f"{authzsvc_endpoint}Group/{group_id}/members/identities/",
headers={
"Authorization": f"Bearer {api_token}",
"Content-Type": "application/json"
},
json=upns
)
if post_resp.ok:
print("Members added successfully.")
print(post_resp.json()['data'])
else:
print("Failed to add members.")
print("Status:", post_resp.status_code)
print("Response:", post_resp.text)
# === Run All Steps ===
try:
group_info = get_group_info()
print(json.dumps(group_info, indent=2))
current_identity_members = get_group_identity_members()
print(f"Current Member Identities: {current_identity_members['pagination']['total']}")
current_group_members = get_group_group_members()
print(f"Current Member Groups: {current_group_members['pagination']['total']}")
upns_to_add = read_upns()
add_upns_to_group(upns_to_add)
except Exception as e:
print("An error occurred:", e)
sys.exit(1)