# Custom External Widget
This feature provides clients and partners the ability to acquire a user contextualized access token, while the user is logged into the Cornerstone LMS application. This enables them to build custom pages, inside an IFRAME, that invoke Cornerstone APIs through server-side code they host on their servers.
Hosting server-side code on the client or partner's servers is required for acquiring the access token and invoking Cornerstone APIs
# Flow Diagram
# Setup
# Oauth2 Application Registration
This process will remain unchanged from the client credentials flow, with exception of a visual indicator on the scopes lists, to indicate that certain scopes will be unavailable for the authorization code flow. Admin should capture the client and client secret presented at completion of the registration process.
For additional security, an optional field to specify sanctioned domain(s) is presented to the admin. The domain(s) will be used to validate the domain of the IFrame URL in the new widget.
During the setup of the Client Credentials application registration, the admin is required to select a user account which the tokens are issued for. When the same Client Id is used in an authorization code flow, the token will be issued for the logged in user and not the one assigned to the application.
For the initial implementation, applications registered with the new Assertion flow will not be available for custom page integration
# Custom Page Configuration
On the custom page setup, a new Custom External widget will be available.
Once this widget is selected the admin is prompted for the following information:
The admin selects an Oauth2 application from a list presented (only eligible ones are listed, see note above)
The number of scopes associated with the selected OAuth2 application is displayed
Best practice for security is to carefully select scopes when registering an Oauth2 application, if the intention is to use it for a custom page
- The admin then enters the URL to the location where it is hosted, this will be the source of the Custom Page delivered into the IFRAME
The URL specified must be HTTPS, it will need to be validated as such
# Authorization Code Acquisition
When the custom page is accessed by a user, the application will call the edge-sts-service internally to acquire a code. This code will be passed as a query string parameter to the external widget.
# Delivering the code to source of the IFRAME
Once the code is received by the CSX application, the custom page IFRAME is rendered with the source URL configured and code attached to it on the URL:
<iframe src="https://acme.com/iframeurl.jsp?code={code retrieved}&state={state}" title="Acme custom page"></iframe>
# Access Token Acquisition
The receiving server of authorization code will exchange it for a token by making a call to the OAuth2 token endpoint
The following parameters are required to acquire the access token
clientId : From the OAuth2 application
clientSecret : From the OAuth2 application
code : Received from IFrame src
grant_type : must be "authorization_code"
state : Received from IFrame src
scope : Scopes requested for the currently logged in user
- If all scopes are selected, only scopes assigned to the application will be selected
# Request to Oauth2 Token endpoint
JSON payload Post
curl -X POST \
https://[corpname].csod.com/services/api/oauth2/token \
-H 'Content-Type: application/json' \
-H 'cache-control: no-cache' \
-d '{
"grantType": "authorization_code",
"code": [code],
"clientId": [clientId],
"clientSecret": [clientSecret],
"state": [state],
"scope": [scope]
}'
Validation
grantType must be "authorization_code"
clientId and clientSecret must be validated as valid
code must be associated with the clientId
The CSX session associated with the code must still be active
State must be a valid state given to the iframe for the current authorization code
Scope must be a valid, space delimited list of scopes, or the all scope.
Response
Successful
# Access token success
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: private
{
"access_token": "ZWRnZQ:...",
"expires_in": 86400,
"scope": "...",
"token_type": "Bearer"
}
Access Token Requirements
Access token will be issued with an expiration of 86400 seconds (24 hours)
Access token will be associated with the active session of the code
When the user's session expires or the user logs out, the access token must be invalidated
We may need to produce hooks through River to expose session events for expiration and log out
Subscribe to the session events for expiration and log out
Get UserInfo
In order to get the user information that corresponds to the above Token make the following call:
curl -X GET \
https://[corpname]/services/api/oauth2/userinfo \
-H 'Authorization: Bearer ZWRnZQ:...'
Note: above bearer token can then be used to make API call to return data for the contextual user.