Identity Applications (and OSP) REST API via curl and jq

6 Likes

Identity Applications REST API via curl and jq

In this article I'll demontrate how to use the curl and jq utilities in a bash command line to interact with Identity Applications via its REST API. The Identity Applications use the OAuth2 protocol for authentication and authorization. So before we can work with the Identity Apps, we first get an access token from OSP.

Prerequisites

Packages

While curl is installed even if you select a minimal Linux distribution, jq packages are an add-on and available from extra modules:

OAuth client

In the OAuth terminology curl (and bash) are a client. We assume you are running on a secure server or workstation with restricted access to the client credentials. Thus we have a confidential client.

The easiest way to register  a new OAuth client with OSP (our Authorization Server) is to edit the ism-configuration.properties file by hand and add the following three properties:

com.netiq.playgound.clientID = playgound
com.netiq.playgound.clientPass = secret
com.netiq.playgound.redirect.url = https://webapp.example.com/oauth.html

Choose a clientID (playgound) of your liking and adjust the property names accordingly. redirect.url is not relevant for scripts using the resource owner password credentials grant.

Instead of using a plain text client secret, you should generate an obfuscated clientPass value with:

java -jar /opt/netiq/idm/apps/tomcat/lib/obscurity-*jar "secret"

Restart OSP.

User

In addition to an OAuth client, you also need a user in the identity vault. We will be using the Resource Owner Password Credentials Grant, so you need the user's username and its password. Some methods require the user to have administrative privileges.

Endpoints

You need to know your OAuth2 issuer URL. For OSP installed with NetIQ Identity Manager this defaults to https://idmapps.example.com:8543/osp/a/idm/auth/oauth2. From this you can retrieve the OAuth2/OpenID endpoints with:

export BASE_URL="https://idmapps.example.com:8543"
export OAUTH2_ISSUER="${BASE_URL}/osp/a/idm/auth/oauth2"

curl -fsS "$OAUTH2_ISSUER/.well-known/openid-configuration" \
  | jq . \
  | tee openid-configuration.json

export AUTHORIZATION_ENDPOINT="$(jq -r .authorization_endpoint openid-configuration.json)"
export TOKEN_ENDPOINT="$(jq -r .token_endpoint openid-configuration.json)"
export USERINFO_ENDPOINT="$(jq -r .userinfo_endpoint openid-configuration.json)"
export REVOCATION_ENDPOINT="$(jq -r .revocation_endpoint openid-configuration.json)"
export INTROSPECTION_ENDPOINT="$(jq -r .introspection_endpoint openid-configuration.json)"

Authentication

Setup environment

export CLIENT_ID="playground"
read -sp "password for client $CLIENT_ID: " CLIENT_PASSWORD && echo && export CLIENT_PASSWORD

export USERNAME="uaadmin"
read -sp "password for user $USERNAME: " PASSWORD && echo && export PASSWORD

Login

Get tokens and store them in token.json.

curl -fsS \
  --request POST \
  --url $TOKEN_ENDPOINT \
  --user "$CLIENT_ID:$CLIENT_PASSWORD" \
  --data "grant_type=password" \
  --data "username=$USERNAME" \
  --data "password=$PASSWORD" \
  -o token.json # login

Refresh access token

By deafult, OSP access tokens expire after 60 seconds. To get a new access token and store it in access_token.json (to avoid overwriting your refresh token) use:

curl -fsS \
  --request POST \
  --url $TOKEN_ENDPOINT \
  --user "$CLIENT_ID:$CLIENT_PASSWORD" \
  --data "grant_type=refresh_token" \
  --data "refresh_token=$(jq -r .refresh_token token.json)" \
  | jq '.exp = (now   .expires_in | floor) | .exp_date = (.exp | todate)' \
  > access_token.json # refresh access token

The 2nd jq command adds two expiration timestamp properties: exp and exp_date:

{
  "access_token": "eH8AIIWvy8yaZFDx6PJqpgJIkrNxoq_M3gVQfcpzAwnOM9rBpm-EyvsZmVh0i-AOMaM3rf8CF-g9rpEv7rXQx1Ev1kRLVqor6kY8zMDywtM3EiSwxFi-t50YAvYKxSoBuBg2ZUBp2wEb4k48MqLowJF93ko8i-hNVIXOZIh1wvFmEL4DR1VEZWIAKj6krq8v8WlHUETxnMUrhAMBxsPHHoCit_TXwehRM5vPaUxhpK-L_SpAd89tCAJjd0MN_PGmd0qbK_TepJkc7LL3G8S8lO_ENeV8lejz9PK3tEtgIlWGg-PI",
  "token_type": "Bearer",
  "expires_in": 60,
  "exp": 1598006322,
  "exp_date": "2020-08-21T10:38:42Z"
}

Check token state (introspect)

Introspect access token:

curl -fsS \
  --request POST \
  --url $INTROSPECTION_ENDPOINT \
  --user "$CLIENT_ID:$CLIENT_PASSWORD" \
  --data "token=$(jq -r .access_token access_token.json)" \
  | jq . # check access token

Introspect refresh token and use jq to calculate its remaining life time in a human readable format:

curl -fsS \
  --request POST \
  --url $INTROSPECTION_ENDPOINT \
  --user "$CLIENT_ID:$CLIENT_PASSWORD" \
  --data "token=$(jq -r .refresh_token token.json)" \
  | jq 'if .exp
    then
      .exp_date = (.exp | todate) # expiration date in ISO 8601 format
      | .exp_duration = ((.exp - now ) | floor) # remaining lifetime in seconds
      | .remaining = "\(.exp_duration / 86400 | floor)d \(.exp_duration / 3600 % 24 | floor)h \(.exp_duration / 60 % 60 | floor)m \(.exp_duration % 60 | floor)s"
    else
      .exp_duration = 0
    end' # check refresh token

Get user info

curl -fsS \
  --url "$USERINFO_ENDPOINT" \
  --header "authorization: $(jq -r '.token_type   " "   .access_token' access_token.json)" \
  --header "accept: application/json" \
  | jq .

Interact with Identity Apps REST endpoints

Get version

curl -fsS \
  --url "$BASE_URL/IDMProv/rest/access/info/version" \
  --header "authorization: $(jq -r '.token_type   " "   .access_token' access_token.json)" \
  | jq .

Get User Application driver status

curl -fsS \
  --url "$BASE_URL/IDMProv/rest/admin/driverstatus/info" \
  --header "authorization: $(jq -r '.token_type   " "   .access_token' access_token.json)" \
  | jq .

Get logging configuration

curl -fsS \
  --url "$BASE_URL/IDMProv/rest/admin/logging/list" \
  --header "authorization: $(jq -r '.token_type   " "   .access_token' access_token.json)" \
  | jq .

Get Memory info

curl -fsS \
  --url "$BASE_URL/IDMProv/rest/access/statistics/memoryinfo" \
  --header "authorization: $(jq -r '.token_type   " "   .access_token' access_token.json)" \
  | jq .

Get Thread info

curl -fsS \
  --url "$BASE_URL/IDMProv/rest/access/statistics/threadinfo" \
  --header "authorization: $(jq -r '.token_type   " "   .access_token' access_token.json)" \
  | jq .

Flush cache

curl -fsS \
  --request DELETE \
  --url "$BASE_URL/IDMProv/rest/admin/cache/holder/items?cacheHolderID=All Cache" \
  --header "authorization: $(jq -r '.token_type   " "   .access_token' access_token.json)" \
  | jq . # flush all caches

more

See REST API documentation for all available methods.

Interact with Identity Reporting REST endpoints

curl -fsS \
  --request DELETE \
  --url "$BASE_URL/IDMDCS-CORE/rpt/collectors/data" \
  --header "authorization: $(jq -r '.token_type   " "   .access_token' access_token.json)" \
  | jq . # purge reporting db

logout

Every login generates a new refresh token. These are stored in the oidpInstanceData attribute on the user object. This space is limited. You therefore must revoke your refresh token once you're done. Otherwise the user might fail to login again after some time.

curl -fsS \
  --request POST \
  --url $REVOCATION_ENDPOINT \
  --user "$CLIENT_ID:$CLIENT_PASSWORD" \
  --data "token_type_hint=refresh_token" \
  --data "token=$(jq -r .refresh_token token.json)" # logout

 

Labels:

How To-Best Practice
Comment List
Anonymous
Parents Comment Children
  • Sweetness and light!  Very nice!  I assume you have a config file for USERNAME, PASSWORD and other variables?  Ah yes, the setenv.sh that is one level higher in the GIT repo.  Clever.

    Very very nice.  Clean.  Useful indeed!  Thank you!

Related Discussions
Recommended