Client Credentials Grants are primarily useful for server-to-server integrations where a third-party application is given access to SSP data and operations without requiring explicit, per end-user authorizations. For example, it would allow server-side portlet code to query SSP for any user's current task list or MAP courses without prompting the end user to either log in to SSP or authorize these specific operations. This results in client applications having rather broad access to SSP data, but is consistent with the current design of SSP's APIs, which are typically protected by per-operation permissions rather than per-user permissions (e.g. "read any MAP", not "read only my MAPs").
Client Credentials Flow
The following diagram illustrates the high-level flow of SSP API authentication via OAuth2
Client Credentials Grants. For a third party application, the most relevant components are:
- Client - The third party application itself,
- Access Token API - A SSP-hosted component represented by the
/api/1/oauth2/tokenURI. The Client sends POST requests to that resource to obtain
Tokenswhich authorize subsequent requests to the rest of the API. These POST requests contain the application's credentials encoded via HTTP Basic Auth. The response is a JSON payload containing the
Tokenitself and a minimal amount of metadata.
- Other APIs - The standard SSP APIs. Clients in possession of a
Tokencan include that value as a request header and will be granted permissions associated with that
Token. SSP administrators can configure
Token-permission relationships and revoke tokens via the SSP user interface.
Client Configuration Step 0 - Make Sure
oauth2_client_password_encoding_secret Is Set
OAuth2 Client secrets are hashed using the value of
oauth2_client_password_encoding_secret as set in
ssp-config.properties. Make sure that confg is set to something you plan to use for the long term as changes to it will make existing secrets unusable. Changes to
ssp-config.properties require an application restart.
Client Configuration Step 1 - Navigate to "OAuth2 Clients" Admin Tool
To see data in this tool, the current user must have the
API_KEY_READ permission. To change/add data, they need
API_KEY_WRITE. Be conservative in granting these permissions, especially the latter, because it allows users to create "back doors" to the application. In particular, users can grant any permission to any OAuth2 Client, not just permissions they current hold.
Click the "Add" button to create a new Client:
Client Configuration Step 2 - Complete the OAuth2 Client Creation Form
The "Client ID" field is actually stored as a SSP username, so be sure to pick a value that is unlikely to conflict with a "real" user's username.
Be sure to take a note of the "Secret" value before saving. The plaintext secret is not needed (e.g. for validating signatures, as with a OAuth1 Consumer Secret), so it is treated the same way you'd expect for an end-user's password. Specifically, a one-way hash is applied to the secret before it is written to the database, which means it is impossible for the application to remind you of the plaintext value.
First Name and Last Name are required for OAuth2 Clients because they act just like "real" users when interacting with SSP data and the SSP APIs always include the first and last names of the creating and most-recently-modifying users for any given record.
Click "Save" to create your new Client:
Client Configuration Step 3 - Browse the Updated Client List
If the save was successful, the new Client list should resemble the following:
Client Configuration Step 4 - Edit the Client
If you decide you need to make changes to the Client, double click the corresponding row in the list view.
Note that changes to any of the following fields will immediately invalidate existing tokens for the editied client, forcing clients to re-authenticate:
- Client ID
Use the Active checkbox to disable a Client without losing any of its configuration.
The following example demonstrates usage of SSP's
Client Credentials Grant flow using the Groovy HTTPBuilder library with corresponding
curl commands to accomplish the same thing albeit without response parsing.
The complete file is attached.
Sample Client Step 1 - Groovy Setup
First install a recent version of Groovy and make sure you can invoke it from the command line.
Create a file called
ssp_oauth2_client.groovy and add the following at the top:
Then run the file to make sure dependencies can be properly downloaded. This may take several seconds as the downloads proceed, during which time you will see no output.
Sample Client Step 2 - Create the Client and Request an Access Token
println "Hello World" and add this in its place, substituting values appropriate for your installation into the variables defined at the top:
The command and its output should look like this:
site.request() invocation resulted in a POST request similar to the following:
Groovy parsed the original response JSON into a Groovy Map. The actual response resembled:
access_token value, which we've stored in the
accessToken Groovy variable can then be used to invoke any other API for which this client has permissions.
Requesting an Access Token with curl
The same thing can be accomplished via curl:
Run with the '
--trace-ascii -' option to see exactly what's going on.
Sample Client Step 3 - Invoke a SSP API
Set the value of
accessToken into the
Authorization header of subsequent API requests and those requests will be processed using the permission set associated with that
Token. For simplicity, here we just request the "top 1" result of the Campus API:
The output should resemble the following (note the
Token reuse, even when running the entire script again). Line breaks added for readability:
The actual request resembled this:
The response, which was parsed from JSON to a Groovy Map in the output above is no different than a standard SSP API response
Invoking an Access Token-authorized API with curl
Here is how the same invocation could be performed with curl:
If the client credentials are incorrect, the output from the Groovy script above will resemble the following:
If the credentials were correct, but the client is disabled:
If the credentials were correct, the client is enabled, but lacks the necessary permissions for the API call:
Token has expired (in which case the caller should just request a new
Same thing with