Introduction
The API supports JWT token authentication from version 11.15.0 onwards.
The standard workflow is
sign in by providing credential to obtain tokens
use access token in Authorization header while invoking API end points
use refresh token to get a new access token when previous is expired
sign out when refresh token is no longer needed
Previously, only Basic Authentication was supported by the API. It is possible to keep this type of authentication, concurrently with token authentication or not.
Tokens
The API uses JWT tokens of limited life time to manage access to end points. There are two types of tokens: the long-lasting refreshment token and the short-lived access token.
refreshment token
The refreshment token is mainly used to obtain access tokens. It can also be stored by the client to implement a "Remember me" feature.
The sign in end point creates a refreshment token and the sign out end point destroy it. Alternatively, a token may expire after its maximum lifetime has been reached, whether it is revoked by an administration operation or has reached a maximum age if this option is enabled.
access token
An access token is used as authorization to invoke an end point. It cannot be revoked and becomes invalid when it expires or reaches its maximum age if this option is activated. An access token can also become invalid on demand by the server.
token invalidity
When a token is invalid, the authentication and authorizations associated with it are refused by the API services. A token may be invalid because it has expired, because it has been revoked (or invalidated) or because it is not recognized by the server as valid.
JWT tokens
The REST API uses JWT tokens (JSON Web Tokens). A JWT token is a three Base64-URL (UTF-8) strings separated by dots. The three parts are:
header
Header consists of two parts: the type of the token, which is always JWT, and the hashing algorithm begin used to build the signature part of the token. These two informations are stored in a JSon object which is encoded to form the first part of the token.
The hash algorithms supported by the REST API are:
HS256 (HMAC SHA256)
HS384 (HMAC SHA384)
HS512 (HMAC SHA512)
Default is HS256, but you can changed it in plug-in configuration.
Payload
The second part of the token is the payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional data. The claims are also stored in a JSon object which is encoded.
Registered claim names
iat
iss
sub
exp
nbf (optional)
jti (only for refreshment tokens)
Public claim names (OpenID)
name (optional)
email (optional)
Signature
The signature is used to verify the message wasn’t changed along the way. The secret used to sign the token is not public and can change at any time. It is possible to configure the generation of this secret in the plug-in configuration. Signature is also encoded.
Message Authentication Code (MAC)
The tokens created by the API are not intended to be used for any purpose other than API access authentication (or token refreshment with this API). If the customer wants to use the token to exploit his information, outside the authentication system, he can use a specific end point to validate the token, then use a standard JWT API to extract the data from the payload. The MAC is private (only known by the server), so it is not possible for the client to modify the user data.. The server can reset the MAC, making the token invalid.
Invokation of services
Authorization Bearer
To invoke an API service with token authentication, simply pass the token through the Authorization header, specifying the Bearer type.
Example:
GET https://application/api/rest/dam/data/asset/55 Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Mzc0NTY3NjMsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6OTA4MC9lbmdpbmVwa2ciLCJ3dHlwIjoiVSIsInN1YiI6ImpvZWwuZHJpZ28iLCJuYW1lIjoiSm_Dq2wgRHJpZ28iLCJlbWFpbCI6ImpvZWwuZHJpZ29Ad2VkaWEuZnIiLCJ1c2lkIjoiMTIiLCJleHAiOjE1Mzc0OTk5NjN9.sy-ZmujVMU4P1xeQ6_qBf-fjUSHdH1MDbe-S0LpoSMI
Example js/jquery/ajax
var assetId = $("#assetid-field").val(); // get assetId input field if ( assetId=="" || assetId==null || assetId===undefined ) { return; } var opts = { url: 'https://<app>/api/rest/dam/data/asset/' + assetId, beforeSend: function(request) { // pass access token as Bearer request.setRequestHeader("Authorization", "Bearer " + accessToken); }, method: 'GET', // since jQuery 1.9 type: 'GET', // prior jQuery 1.9 done: function(data){ // replace success with done prior jQuery 3.0 if ( data["status"]== 200 ) { // success // show asset id $("#assetid-display").text(assetId); // show asset data $("#assetdata").html( jsonToHtml(data.response.data) ); // replace img src with signature in for thumbnail $("#assetimage").prop("src", 'https://<app>/api/rest/dam/data/asset/' + assetId + '/binary?variation=thumbnailSmall&atk=' + signToken ); } else { // failure // $("#errorMessage").text("GET ASSET KO / " + data["status"] + " / " + data["message"] ); } }, fail: function(xhr, status, error) { // replace fail with error prior jQuery 3.0 // failure // $("#errorMessage").text("GET ASSET KO / " + error ); } }; $.ajax(opts);
Query parameter / Signature token
To allow the invocation of the token binary recovery service by placing a URL in the src attribute of an img HTML tag, it is possible to use a request parameter for this end point. To do this, use the signature token as the value of the atk parameter.
Example:
GET https://application/api/rest/dam/data/asset/55/binary?variation=thumbnailSmall&atk=ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBZWFFpT2pFMU16YzBOVFkzTmpNc0ltbHpjeUk2SW1oMGRIQTZMeTlzYjJOaGJHaHZjM1E2T1RBNE1DOWxibWRwYm1Wd2EyY2lMQ0ozZEhsd0lqb2lWU0lzSW5OMVlpSTZJbXB2Wld3dVpISnBaMjhpTENKdVlXMWxJam9pU21fRHEyd2dSSEpwWjI4aUxDSmxiV0ZwYkNJNkltcHZaV3d1WkhKcFoyOUFkMlZrYVdFdVpuSWlMQ0oxYzJsa0lqb2lNVElpTENKbGVIQWlPakUxTXpjME9UazVOak45LnN5LVptdWpWTVU0UDF4ZVE2X3FCZi1malVTSGRIMU1EYmUtUzBMcG9TTUk
Authenticate end point (Create tokens)
Method: POST
Parameters
The parameters can be passed through the content type application/x-www-form-urlencoded or multipart/form-data.
login: the user login
password: the password
application: application name (optional)
userid: application user (optional, taken into account only for the connection by application)
exp: desired expiration time pour the refreshment token (optional)
a date, as UTC Unix epoch time
an ISO datetime (yyyy-MM-dd’T’HH:mm:ss or yyyyMMdd’T’HHmmss)
unlimited, for an unlimited time token (The expiration date can never exceed the limits set elsewhere).
other value or parameter omitted means default value depending on the context
Response
The response is application/json, status 201 (created), containing mainly :
refreshToken: refreshment JWT Token
accessToken: access JWT Token
signature: query authentication parameter for binary end point
Example:
{ tokenType: "Bearer", refreshToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Mzc0NjM2NDQsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6OTA4MC9lbmdpbmVwa2ciLCJ3dHlwIjoiUiIsInN1YiI6ImpvZWwuZHJpZ28iLCJuYW1lIjoiSm_Dq2wgRHJpZ28iLCJlbWFpbCI6ImpvZWwuZHJpZ29Ad2VkaWEuZnIiLCJ1c2lkIjoiMTIiLCJleHAiOjE1Mzc1NTAwNDQsImp0aSI6Ijg2MSJ9.Fvc1UJu0kjfFaydIA0-t3cKjZ7rMY6s5htUxi-0lcmk", accessToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Mzc0NjM2NDQsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6OTA4MC9lbmdpbmVwa2ciLCJ3dHlwIjoiVSIsInN1YiI6ImpvZWwuZHJpZ28iLCJuYW1lIjoiSm_Dq2wgRHJpZ28iLCJlbWFpbCI6ImpvZWwuZHJpZ29Ad2VkaWEuZnIiLCJ1c2lkIjoiMTIiLCJleHAiOjE1Mzc1MDY4NDR9.GqDb_CR8zVja2xW6LNk3QA6bff78BGGUjz_ArHwTXVE", signature: "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBZWFFpT2pFMU16YzBOak0yTkRRc0ltbHpjeUk2SW1oMGRIQTZMeTlzYjJOaGJHaHZjM1E2T1RBNE1DOWxibWRwYm1Wd2EyY2lMQ0ozZEhsd0lqb2lWU0lzSW5OMVlpSTZJbXB2Wld3dVpISnBaMjhpTENKdVlXMWxJam9pU21fRHEyd2dSSEpwWjI4aUxDSmxiV0ZwYkNJNkltcHZaV3d1WkhKcFoyOUFkMlZrYVdFdVpuSWlMQ0oxYzJsa0lqb2lNVElpTENKbGVIQWlPakUxTXpjMU1EWTRORFI5LkdxRGJfQ1I4elZqYTJ4VzZMTmszUUE2YmZmNzhCR0dVanpfQXJId1RYVkU", links: { href: "https://application/api/rest/signin", refreshTokenHref: "https://application/api/rest/token?token=ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBZWFFpT2pFMU16YzBOak0yTkRRc0ltbHpjeUk2SW1oMGRIQTZMeTlzYjJOaGJHaHZjM1E2T1RBNE1DOWxibWRwYm1Wd2EyY2lMQ0ozZEhsd0lqb2lVaUlzSW5OMVlpSTZJbXB2Wld3dVpISnBaMjhpTENKdVlXMWxJam9pU21fRHEyd2dSSEpwWjI4aUxDSmxiV0ZwYkNJNkltcHZaV3d1WkhKcFoyOUFkMlZrYVdFdVpuSWlMQ0oxYzJsa0lqb2lNVElpTENKbGVIQWlPakUxTXpjMU5UQXdORFFzSW1wMGFTSTZJamcyTVNKOS5GdmMxVUp1MGtqZkZheWRJQTAtdDNjS2paN3JNWTZzNWh0VXhpLTBsY21r", signoutHref: "https://application/api/rest/signout?token=ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBZWFFpT2pFMU16YzBOak0yTkRRc0ltbHpjeUk2SW1oMGRIQTZMeTlzYjJOaGJHaHZjM1E2T1RBNE1DOWxibWRwYm1Wd2EyY2lMQ0ozZEhsd0lqb2lVaUlzSW5OMVlpSTZJbXB2Wld3dVpISnBaMjhpTENKdVlXMWxJam9pU21fRHEyd2dSSEpwWjI4aUxDSmxiV0ZwYkNJNkltcHZaV3d1WkhKcFoyOUFkMlZrYVdFdVpuSWlMQ0oxYzJsa0lqb2lNVElpTENKbGVIQWlPakUxTXpjMU5UQXdORFFzSW1wMGFTSTZJamcyTVNKOS5GdmMxVUp1MGtqZkZheWRJQTAtdDNjS2paN3JNWTZzNWh0VXhpLTBsY21r" }, version: "1.0", status: 201, time: 617 }
additional informations for OAuth2 sign in
Depending of the OAuth2 server configuration, you can get additional informations about the user account:
state: the OAuth2 state returned while the OAuth2 processus
loginHints: An object with the id of the OAuth2 authentication server and the login hint you can send in parameter loginHint of the OAuth2 login end point
idToken: the openid token
Example:
{ tokenType: "Bearer", refreshToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Mzc0NjM2NDQsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6OTA4MC9lbmdpbmVwa2ciLCJ3dHlwIjoiUiIsInN1YiI6ImpvZWwuZHJpZ28iLCJuYW1lIjoiSm_Dq2wgRHJpZ28iLCJlbWFpbCI6ImpvZWwuZHJpZ29Ad2VkaWEuZnIiLCJ1c2lkIjoiMTIiLCJleHAiOjE1Mzc1NTAwNDQsImp0aSI6Ijg2MSJ9.Fvc1UJu0kjfFaydIA0-t3cKjZ7rMY6s5htUxi-0lcmk", accessToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1Mzc0NjM2NDQsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6OTA4MC9lbmdpbmVwa2ciLCJ3dHlwIjoiVSIsInN1YiI6ImpvZWwuZHJpZ28iLCJuYW1lIjoiSm_Dq2wgRHJpZ28iLCJlbWFpbCI6ImpvZWwuZHJpZ29Ad2VkaWEuZnIiLCJ1c2lkIjoiMTIiLCJleHAiOjE1Mzc1MDY4NDR9.GqDb_CR8zVja2xW6LNk3QA6bff78BGGUjz_ArHwTXVE", signature: "ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBZWFFpT2pFMU16YzBOak0yTkRRc0ltbHpjeUk2SW1oMGRIQTZMeTlzYjJOaGJHaHZjM1E2T1RBNE1DOWxibWRwYm1Wd2EyY2lMQ0ozZEhsd0lqb2lWU0lzSW5OMVlpSTZJbXB2Wld3dVpISnBaMjhpTENKdVlXMWxJam9pU21fRHEyd2dSSEpwWjI4aUxDSmxiV0ZwYkNJNkltcHZaV3d1WkhKcFoyOUFkMlZrYVdFdVpuSWlMQ0oxYzJsa0lqb2lNVElpTENKbGVIQWlPakUxTXpjMU1EWTRORFI5LkdxRGJfQ1I4elZqYTJ4VzZMTmszUUE2YmZmNzhCR0dVanpfQXJId1RYVkU", links: { href: "https://application/api/rest/signin", refreshTokenHref: "https://application/api/rest/token?token=ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBZWFFpT2pFMU16YzBOak0yTkRRc0ltbHpjeUk2SW1oMGRIQTZMeTlzYjJOaGJHaHZjM1E2T1RBNE1DOWxibWRwYm1Wd2EyY2lMQ0ozZEhsd0lqb2lVaUlzSW5OMVlpSTZJbXB2Wld3dVpISnBaMjhpTENKdVlXMWxJam9pU21fRHEyd2dSSEpwWjI4aUxDSmxiV0ZwYkNJNkltcHZaV3d1WkhKcFoyOUFkMlZrYVdFdVpuSWlMQ0oxYzJsa0lqb2lNVElpTENKbGVIQWlPakUxTXpjMU5UQXdORFFzSW1wMGFTSTZJamcyTVNKOS5GdmMxVUp1MGtqZkZheWRJQTAtdDNjS2paN3JNWTZzNWh0VXhpLTBsY21r", signoutHref: "https://application/api/rest/signout?token=ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBZWFFpT2pFMU16YzBOak0yTkRRc0ltbHpjeUk2SW1oMGRIQTZMeTlzYjJOaGJHaHZjM1E2T1RBNE1DOWxibWRwYm1Wd2EyY2lMQ0ozZEhsd0lqb2lVaUlzSW5OMVlpSTZJbXB2Wld3dVpISnBaMjhpTENKdVlXMWxJam9pU21fRHEyd2dSSEpwWjI4aUxDSmxiV0ZwYkNJNkltcHZaV3d1WkhKcFoyOUFkMlZrYVdFdVpuSWlMQ0oxYzJsa0lqb2lNVElpTENKbGVIQWlPakUxTXpjMU5UQXdORFFzSW1wMGFTSTZJamcyTVNKOS5GdmMxVUp1MGtqZkZheWRJQTAtdDNjS2paN3JNWTZzNWh0VXhpLTBsY21r" }, state: "h2o2", loginHints: { id: "google", loginHint: "joel.drigo@wedia.fr" }, idToken: { iss: "https://accounts.google.com", azp: "[...].apps.googleusercontent.com", aud: "[...].apps.googleusercontent.com", sub: "10105[...]4799", hd: "wedia.fr", email: "joel.drigo@wedia.fr", email_verified: true, at_hash: "5D2TEN[...]aTRHb4Q", name: "Joël DRIGO", picture: "https://lh4.googleusercontent.com/-JvH[...]s96-c/photo.jpg", given_name: "Joël", family_name: "DRIGO", locale: "fr", iat: 1543424259, exp: 1543427859 }, version: "1.0", status: 201, time: 617 }
Problem with ajax about multipart/form-data (missing boundary in content type header)
There is a problem with content type multipart/form-data using a HTML form and an ajax request. You can bypass it this way (jquery):
var form = $("#login-form"); // get the form var formdata = new FormData(form[0]); // create a FormData object for the form var opts = { // options for ajax call url: 'https://<app>/api/rest/signin"/>', data: formdata, cache: false, contentType: false, processData: false, method: 'POST', // since jQuery 1.9.0 type: 'POST', // jQuery prior to 1.9.0 done: function(data){ // replace done with success prior jQuery 3.0 if ( data["status"]==201 ) { // "LOGIN OK" // refreshToken = data["refreshToken"]; // accessToken = data["accessToken"]; // signToken = data["signature"]; } else { // "LOGIN KO / " + data["status"] + " / " + data["message"]); } }, fail: function(xhr, status, error) { // replace fail with error prior jQuery 3.0 // "LOGIN KO / " + error); } }; if(formdata.fake) { // multipart/form-data problem workaround // Make sure no text encoding stuff is done by xhr opts.xhr = function() { var xhr = jQuery.ajaxSettings.xhr(); xhr.send = xhr.sendAsBinary; return xhr; } opts.contentType = "multipart/form-data; boundary="+formdata.boundary; opts.data = formdata.toString(); } $.ajax(opts);
With fetch, do not set Content-Type header to multipart/form-data explicitely :
var form = $("#login-form"); // get the form var formdata = new FormData(form[0]); // create a FormData object for the form fetch('https://<app>/api/rest/signin"/>', { method: 'POST', body: formdata } ) delete result.headers['Content-Type'];
Basic Authentication
It is possible to invoke this end point using Basic authentication. The use is exactly the same as for invoking any other end point in Basic authentication.
Refresh token end point (Create new access token)
Method: GET
Parameters
token: the refresh token
Response
The response is exactly the same as for the end point signin.
Authentication
This end point can be invoked without authentication, but you can pass the access or refresh token to Bearer in the Authorization header. In this case, it will be checked and compared to the token passed as a parameter and you may get a 401 Unauthorized error in response if the tokens do not conform. However, the expiration of the access token is never verified in order to be able to obtain a new access token after its expiration.
Sign out end point (Delete/Revoke refresh token)
Method: DELETE
Parameters
token: the refresh token
Authentication
This end point can be invoked without authentication, but you can pass the access or refresh token to Bearer in the Authorization header. In this case, it will be checked and compared to the token passed as a parameter and you may get a 401 Unauthorized error in response if the tokens do not conform. However, the expiration of the access token is never verified in order to be able to revoke a token even after its expiration.
Validate end point (Validate token)
Method: get
Parameters
token: the token to be validated
Responses
HTTP Code | Definition |
---|---|
200 | Token is valid |
401 | Token is invalid |
Authentication
This end point can be invoked without authentication, but you can pass the access or refresh token to Bearer in the Authorization header. In this case, it will be checked and compared to the token passed as a parameter and you may get a 401 Unauthorized error in response if the tokens do not conform. However, the expiration of the access token is never verified in order to be able to obtain a new access token after its expiration.
Configuring the plug-in
sessionAuth: boolean (default is false), enable session cookie authentication, only out of production mode (because of possible exploitation by CSRF attack)
tokenHash: (optional) base for MAC hash key
tokenCleaningPeriod: The trigger period for the process of deleting expired tokens, in seconds (1800 seconds by default, i.e. 30 minutes). Use 0 to disable the process.
tokenLongLifeTime: the duration of a long life token, in seconds (default is 86400 seconds, i.e. 24 hours)
tokenShortLifeTime: the duration of a short life token, in seconds (default is 1200 seconds, i.e. 20 minutes)
tokenMaxAge: (optional) if specified, the maximum lifetime of a token, regardless of long and short life time
jwtAlgorithm: JWT token MAC algorithm
HS256: HMAC-SHA256 algorithm (default)
HS384: HMAC-SHA384 algorithm
HS512: HMAC-SHA512 algorithm