Skip to content
Developer home

Authentication for Single Page Web Applications

  Less than to read

In order to obtain a Bearer Token from a SPA application, you need to implement the Authorization Code OAuth 2.0 grant flow using Proof Key for Code Exchange (PKCE). The Proof Key for Code Exchange (PKCE) (defined in RFC 7636) is a technique used to mitigate attacks to the Authorization Code OAuth 2.0 grant flow.

With PKCE, the application creates, for every authorization request, a cryptographically random key called code_verifier and its transformed value called code_challenge, which is sent to Sage ID to get the authorization_code. When the application receives the authorization_code, it will send the code and the code_verifier to Sage ID token endpoint to exchange them for the requested tokens.

This OAuth 2.0 flow follows these steps:

  1. Your SPA application initiates the flow and redirects the user to Sage ID (specifically to the /authorize endpoint), sending the code_challenge and code_challenge_method parameters.
  2. Sage ID redirects the user to your SPA application with an authorization_code in the querystring.
  3. Your SPA application sends the authorization_code and code_verifier together with the redirect_uri and the client_id to Sage ID. This is done using the /oauth/token endpoint.
  4. Sage ID validates this information and returns an Access Token (and optionally a Refresh Token) to your SPA application.
  5. Then, your SPA application can use the Access Token to call the Sage 200 API on behalf of the user.

How to Implement it

In the next points, we will work through the steps needed in order to implement it: create a code verifier and a code challenge, get the user’s authorization, get a token and access the Sage 200 API using the token.

1. Create a Code Verifier

First, you need to generate and store a code_verifier.

function base64URLEncode(str) {
    return str.toString('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
}
var verifier = base64URLEncode(crypto.randomBytes(32));

2. Create a Code Challenge

Using the code_verifier, generate a code_challenge that will be sent in the authorization request.

You must hash this value and not send a plain-text string.

function sha256(buffer) {
    return crypto.createHash('sha256').update(buffer).digest();
}
var challenge = base64URLEncode(sha256(verifier));

3. Get the User’s Authorization

To begin an Authorization Code flow, your ASP application should first send the user to the authorization URL, including the code_challenge and the method used to generate it:

<a href="https://id.sage.com/authorize?audience=861692d/sage200nc.sage.com/api&scope=openid email profile Sales:ReadWrite offline_access&response_type=code&client_id=YOUR_CLIENT_ID&code_challenge=CODE_CHALLENGE&code_challenge_method=S256&redirect_uri=https://id.sage.com/mobile">
  Sign In
</a>

4. Exchange the Authorization Code for an Access Token

Now that you have an Authorization Code, you must exchange it for an Access Token that can be used to call the Sage 200 API. Using the Authorization Code from the previous step, you will need to POST to the Token URL sending also the code_verifier:

var client = new RestClient("https://id.sage.com/oauth/token");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddParameter("application/json", "{\"grant_type\":\"authorization_code\",\"client_id\": \"YOUR_CLIENT_ID\",\"code_verifier\": \"YOUR_GENERATED_CODE_VERIFIER\",\"code\": \"YOUR_AUTHORIZATION_CODE\",\"redirect_uri\": \"https://id.sage.com/mobile\"}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

The response contains access_token, refresh_token, id_token, and token_type values, for example:

{
  "access_token": "eyJz93a...k4laUWw",
  "refresh_token": "GEbRxBN...edjnXbL",
  "id_token": "eyJ0XAi...4faeEoQ",
  "token_type": "Bearer"
}

Note that refresh_token will only be present in the response if you included the offline_access scope.

5. Call the Sage 200 API

Once you have the access_token you can use it to make calls to the Sage 200 API, by passing it as a Bearer Token in the Authorization header of the HTTP request:

// Use the Access Token to make Sage 200 API calls
$('#get-appointments').click(function(e) {
  e.preventDefault();

  $.ajax({
    cache: false,
    url: "https://sage200.sage.es/api/sales/products",
    headers: { "Authorization": "Bearer " + access_token }
  });
});

6. Get a new Access Token

If you have a refresh_token, you can call the /oauth/token endpoint using the refresh_token grant type, and the refresh token string, to obtain a new Access Token.

var client = new RestClient("https://id.sage.com/oauth/token");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "x-www-form-urlencoded");
request.AddParameter("application/json", "grant_type=refresh_token&refresh_token=REFRESH_TOKEN&client_id=YOUR_CLIENT_ID", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

The response contains access_token, expires_in, id_token, and token_type values.