Authenticating API Requests

There is only one way to authenticate GroupDocs Cloud REST APIs: by using OAuth 2.0 protocol with JWT Bearer Token.
The JWT token is extracted and validated by our APIs from the Authorization request header.

OAuth 2.0

OAuth 2.0 is an authorization framework that enables your applications to obtain access to data to different APIs.
OAuth provides authorization flows for web and desktop applications, and mobile devices.

What is a JSON Web Token (JWT)?

A JSON Web Token is used to send information that can be verified and trusted by means of a digital signature. It comprises a compact and URL-safe JSON object, which is cryptographically signed to verify its authenticity, and which can also be encrypted if the payload contains sensitive information. Because of its compact structure, JWT is usually used in HTTP Authorization headers or URL query parameters.

Structure of a JSON Web Token

A JWT is represented as a sequence of base64url encoded values that are separated by period characters.

header.payload.signature

The header contains the metadata for the token and it minimally contains the type of signature and the encryption algorithm.

Payload (Claims)

In the context of JWT, a claim can be defined as a statement about an entity (typically, the user), as well as additional metadata about the token itself. The claim contains the information we want to transmit, and that the server can use to properly handle JSON Web Token authentication. There are multiple claims we can provide; these include registered claim names, public claim names and private claim names.

Signature

The JWT standard follows the JSON Web Signature (JWS) specification to generate the final signed token. It is generated by combining the encoded JWT Header and the encoded JWT Payload and signing it using a strong encryption algorithm, such as HMAC SHA-256. The signature’s secret key is held by the server so it will be able to verify existing tokens and sign new ones.

How JSON Web Tokens Work

A browser or mobile client makes a request to the authentication server containing user Client Id and Client Secret. The authentication server generates a new JWT access token and returns it to the client. On every request to a restricted resource, the client sends the access token in the Authorization header. The server then validates the token and, if it’s valid, returns the secure resource to the client.

Authorization Flow

The GroupDocs Cloud REST API supports several parts of the OAuth 2.0 protocol and the way to authorize REST API calls is by using client_credentials workflow.

The client_credentials workflow we use is based on a set of keys (client_id and client_secret) which are further used to obtain a token (JWT Token).

The basic concept and how it works is described in the next image:

Applications

To access the REST API using JWT Token, you need to create an application. To register new applications, login into the Dashboard Developer site using your GroupDocs Account, and go to the Applicaitons view. Once you create a new application, we will issue a client_id and client_secret that you can use to obtain an JWT Token in order to authenticate your REST API calls. (You can generate new secrets for your Applications, but make sure you update it when issuing new access tokens using those credentials.)

Get JWT Access Token

After you have created a new application you can obtain an access token by sending a POST request to /connect/token endpoint:

POST request to: https://api.groupdocs.cloud/connect/token
Headers:
  Accept: application/json
  Content-Type: application/x-www-form-urlencoded
  Body:
    grant_type: client_credentials
    client_id: CLIENT_ID
    client_secret: CLIENT_SECRET

The endpoint acts as an authorization server and it verifies your credentials, if they are correct it returns a JSON ticket containing several items, through each, you can find the access_token, expire time of the token and the token type (Bearer). The provided access_token is a Bearer Token that you can further use in the Authorization header of your request.

cURL Example

curl --location --request POST 'https://api.groupdocs.cloud/connect/token' \
     --header 'Content-Type: application/x-www-form-urlencoded' \
     --data-urlencode 'grant_type=client_credentials' \
     --data-urlencode 'client_id=XXYYXXYY' \
     --data-urlencode 'client_secret=XXYYXXYY'
{
    "access_token": "eyJhbGciOiJSUzI1UiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE2MDUxMTA3MTMsImV4cCI6MUYwNTE5NzExMywiaXNzIjoiaHR0cHM6Ly9hcGkuZ3JvdXBkb2NzLmNsb3VkIiwiYXVkIjpbImh0dHBzOi8vYXBpLmdyb3VwZG9jcy5jbG91ZC9yZXNvdXJjZXMiLCJhcGkuYmlsbGluZyIsImFwaS5pZGVudGl0eSIsImFwaS5wcm9kdWN0cyIsImFwaS5zdG9yYWdlIl0sImNsaWVudF9pZCI6IjNlZmYwMGFlLWIxNzctNDRiZC04NTVlLTkxNzlkZmNiN2M4OSIsImNsaWVudR9kZWZhdWx0X3N0b3JhZ2UiOiJkY2Y0MjkyMC1hNjc1LTRjNTEtOTdlMi1kZWJhNGFkZjg4ZWYiLCJjbGllbnRfaWRlbnRpdHlfdXNlcl9pZCI6Ijc5MjMyMSIsInNjb3BlIjpbImFwaS5iaWxsaW5nIiwiYXBpLmlkZW50aXR5IiwiYXBpLnByb2R1Y3RzIiwiYXBpLnN0b3JhZ2UiXX0.DuDw85-xsxMfiddMhqK0RCcHTWkviDDKqsNVH1Rcnab1LsYaW_76d7IXPLvHMO6LMzGJ2WOsvqiO5Tk4bezd04p0OvTXJLF4TQ4GP6lPcw4p5GWayyLljOxZiDPgmfpH3J8F3H0Qr-9PJyMreeZ-x8h8jzO65HLhdw0NOFfABaJ0NJkuMqhI0bGfZd2BalfxKoCfUFajzXvq5oFuCtC8t7G-81QSTC0L2waSjH9ET6MY1F-7HSV3fxFBswcIdx383N30VjCh3HFml8xScHFtVHGsyc7XFBWWzhTcMxQKrRVcgdLGg6DvS3W47cbIpXjfQ-p0nFj1briayLOK-GaZ8Q",
    "expires_in": 86400,
    "token_type": "Bearer"
}

Call REST API

Now that you have the Bearer Token (access_token) generated using the application credentials, you can make API calls and authorize by adding the access token in the ‘Authorization’ header, as it’s defined in the OAuth 2.0 protocol.

Headers: Authorization: Bearer ACCESS_TOKEN

You authorize with one application, but you can access files from all storages in your account, by specifying query parameters (e.g. storage, storageName etc.).

cURL Example

curl -v "https://api.groupdocs.cloud/v1/viewer/Test.msg/html/attachments/Freescale%20OSC.pdf/pages/1/resources/styles.css" \
     -X GET \
     -H "Content-Type: application/json" \
     -H "authorization: Bearer _J7gynLXEsUVn8fCYlsHqP-Su6G3-TjRUQH328UFoMQ2j7wrh8_n5CcqqDU8Bpx7Pvkoc3I9K1AeDOINokG4a1pmXwfMdExQRt6vQ-356u-OQvZQjoYkDwNyEUObAlDbAw7LFcA1utZKnerf2JV6Q8Gjn00BH-N4IJaUY02jXzppPP7fOdx0RNTiUfAnAuemsDbItsyd-BTT8oIk2AwcTwIZM5ub5eFNYzgIrtrTDxVUMd6oG3-xAuGVM5h2Bc9D-G17pspaLXIEkeqyjSMaOzKHxi-vOUse3i8mRTNhu0gCHXt2q08MR_qMtfgGhT8ZQh-kk8bRTX9QVv-LzcSx7I0PTZkYM8Rha8QVr1aStXehlW2yIGo7YGQobeBnsn2zmIuR1CzczdxfePSQ4evPuoaSuFN9I9swLDFcZYfVdcq3Tk5i"
  sup {
    top: -0.4em;
    vertical-align: baseline;
    position: relative;
  }
  sub {
    top: 0.4em;
    vertical-align: baseline;
    position: relative;
  }
  a:link { text-decoration:none; }
  a:visited { text-decoration:none; }

  @media screen and (min-device-pixel-ratio:0), (-webkit-min-device-pixel-ratio:0), (min--moz-device-pixel-ratio: 0) {
    .p1-EqxtBMuQ-view{ font-size:10em; transform:scale(0.1); -moz-transform:scale(0.1); -webkit-transform:scale(0.1); -moz-transform-origin:top left; -webkit-transform-origin:top left; } }
  .layer { }.ie { font-size: 1pt; }
  .ie body { font-size: 12em; }
  .p1-EqxtBMuQ-01 {
  position: absolute;
  white-space: nowrap;
  }
  .p1-EqxtBMuQ-02 {
    height: 66em;
    font-size: 1em;
    margin: 0em;
    line-height: 0.0em;
    display: block;
    border-style: none;
    width: 49.58333em;
  }
  @supports(-ms-ime-align:auto) { .p1-EqxtBMuQ-02 {width: auto; overflow: hidden;}}
    .p1-EqxtBMuQ-03 {
    position: relative;
  }
    .p1-EqxtBMuQ-04 {
    width: 100%;
    clip: rect(-0.041667em,49.625em,66.04166em,-0.041667em);
    position: absolute;
    pointer-events: none;
  }
  .p1-EqxtBMuQ-05 {
    position: relative;
    width: 49.58333em;
}
curl -v "https://api.groupdocs.cloud/v1/viewer/Test.msg/html/attachments/Freescale%20OSC.pdf/pages/1/resources/styles.css" \
     -X GET \
     -H "Content-Type: application/json" \
     -H "authorization: Bearer _J7gynLXEsUVn8fCYlsHqP-Su6G3-TjRUQH328UFoMQ2j7wrh8_n5CcqqDU8Bpx7Pvkoc3I9K1AeDOINokG4a1pmXwfMdExQRt6vQ-356u-OQvZQjoYkDwNyEUObAlDbAw7LFcA1utZKnerf2JV6Q8Gjn00BH-N4IJaUY02jXzppPP7fOdx0RNTiUfAnAuemsDbItsyd-BTT8oIk2AwcTwIZM5ub5eFNYzgIrtrTDxVUMd6oG3-xAuGVM5h2Bc9D-G17pspaLXIEkeqyjSMaOzKHxi-vOUse3i8mRTNhu0gCHXt2q08MR_qMtfgGhT8ZQh-kk8bRTX9QVv-LzcSx7I0PTZkYM8Rha8QVr1aStXehlW2yIGo7YGQobeBnsn2zmIuR1CzczdxfePSQ4evPuoaSuFN9I9swLDFcZYfVdcq3Tk5i"
sup {
  top: -0.4em;
  vertical-align: baseline;
  position: relative;
}
sub {
  top: 0.4em;
  vertical-align: baseline;
  position: relative;
}
a:link {text-decoration:none;}
a:visited {text-decoration:none;}
@media screen and (min-device-pixel-ratio:0), (-webkit-min-device-pixel-ratio:0), (min--moz-device-pixel-ratio: 0) {.p1-EqxtBMuQ-view{ font-size:10em; transform:scale(0.1); -moz-transform:scale(0.1); -webkit-transform:scale(0.1); -moz-transform-origin:top left; -webkit-transform-origin:top left; } }
.layer { }.ie { font-size: 1pt; }
.ie body { font-size: 12em; }
.p1-EqxtBMuQ-01 {
  position: absolute;
  white-space: nowrap;
}
.p1-EqxtBMuQ-02 {
  height: 66em;
  font-size: 1em;
  margin: 0em;
  line-height: 0.0em;
  display: block;
  border-style: none;
  width: 49.58333em;
}
@supports(-ms-ime-align:auto) { .p1-EqxtBMuQ-02 {width: auto; overflow: hidden;}}
  .p1-EqxtBMuQ-03 {
  position: relative;
}
.p1-EqxtBMuQ-04 {
  width: 100%;
  clip: rect(-0.041667em,49.625em,66.04166em,-0.041667em);
  position: absolute;
  pointer-events: none;
}
.p1-EqxtBMuQ-05 {
  position: relative;
  width: 49.58333em;
}

Token Lifetime

The time of the tokens is finite. By default, the access_token lifetime is 1 day. Before you create a new access_token, use it and renew it only before it expires. To detect when an access token expires, you must write specific code that will check for any of these:

  • expires_in value in the ticket generated by the /connect/token endpoint.
  • will handle the 401 Unauthorized error responses from the API endpoint and issue a request for a new token.