.NET OAuth 2.0 client credentials authentication for the Shape API

Published: 2023-06-29
Author: Alex Bartlett

Shape Payroll is an API first payroll platform, everything our UI does can be replicated programmatically via an integration or script.

In order to exercise the API endpoints, you will first need to authenticate your integration client so we know who you are. For machine to machine (M2M) auth, Shape manages this using the OAuth 2.0 client credentials flow.

Our full API documentation is here.

Step 1 Acquire Credentials

Log into the Shape UI, then navigate to My Account -> Developers -> Credentials, then click the New Credentials button at the top of the screen.

Give you client a name and click Create. The system will generate a Client ID and Client Secret for you. Make a note of the secret as once you close the dialog it is impossible to recover.

Store the secret somewhere safe and don’t share it with anyone.

Step 2 Access Token

In order to access the server, you will need to exchange your credentials for a short lived token. We do this using the OAuth 2.0 Client Credentials flow.

The flow itself is well known, if you are using C# you could use code similar to:

using System.Text.Json;

// Development server
const string serverUrl = "https://dev-api.shapepayroll.com";

// Live server
// const string serverUrl = "https://api.shapepayroll.com";

const string clientId = "your client id";
const string clientSecret = "your client secret";

var client = new HttpClient
{
    BaseAddress = new Uri(serverUrl),
    DefaultRequestHeaders = {
        { "User-Agent", "Add a unique name for your app here" } 
    }
};

var content = new FormUrlEncodedContent(new Dictionary<string, string>
    {
        {"grant_type", "client_credentials"} ,
        {"client_id", clientId} ,
        {"client_secret", clientSecret} ,
    }
);
var response = await client.PostAsync("/oauth/token", content);
var responseBody = await response.Content.ReadAsStreamAsync();
var tokens = await JsonSerializer.DeserializeAsync<TokenResponse>(responseBody, JsonSerializerOptions.Default);

Console.WriteLine($"Your token: {tokens.access_token}");
Console.WriteLine($"Expires in: {tokens.expires_in} seconds");

class TokenResponse
{
    public string access_token { get; set; }
    public int expires_in { get; set; }
}

You can use the token until the expiry time, after which you will need to repeat the process to get another.

Step 3 API Access

Now that you have an access_token you can call the API, passing the token in the Authorization header of subsequent requests, in the format 'Bearer <your access_token>'.

Security Best Practices

  • Do not share the secret with anyone.

  • Use a different set of credentials for each environment you manage.

  • Keep production secrets in a secure store, in your production environment.

  • Don’t commit the secret into your repo.

  • Rotate the secrets from time to time.