OAuth 2.0 Authentication
TaxBandits API incorporates OAuth 2.0, the standard authorization mechanism that enables your software to access the resources hosted by TaxBandits.
This authentication scheme involves JSON Web Tokens (JWT), which are access tokens generated by the server in response to a request.
- To start the OAuth 2.0 Authentication, you must retrieve the API keys (User Token, Client ID, Client Secret) in the sandbox console.
- Once done, you must request the access token. To request an access token, you need to create a JWS (JSON Web Signature) for Authentication. The JWS consists of 3 parts, as given below:
Header:
{
"alg": "HS256", /*Algorithm = HS256*/
"typ": "JWT" /*Type = JSON Web Token (JWT)*/
}
Payload:
{
"iss": "968a9c78dae29a29", /*Issuer: Client ID retrieved from the console site*/
"sub": "968a9c78dae29a29", /*Subject: Client ID retrieved from the console site*/
"aud": "a574b75f18b24fc09f9039ffb5cb08f3", /*Audience: User Token retrieved from the console site*/
"iat": 1516239022 /*Issued at: Number of seconds from Jan 1 1970 00:00:00 (Unix epoch format)*/
}
Signature:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
siqHfLy59g3UHxrb5gjxg /*Client Secret retrieved from the console site*/
)
- Combine the Header, payload, and signature to generate the JWS.
Sample JWS
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOi
I5NjhhOWM3OGRhZTI5YTI5Iiwic3ViIjoiOTY4YTljNzhkYWUyOWEyOSIsImF1
ZCI6ImE1NzRiNzVmMThiMjRmYzA5ZjkwMzlmZmI1Y2IwOGYzIiwiaWF0IjoxN
TE2MjM5MDIyfQ.HNQznxlPyVt62kyUeVwtk1-uzm1uDWH4NBDLShA6Ac0
- Once the JWS is generated, send a request to the Authentication Server URL for an Access token. Refer below to learn how to get the JWT from TaxBandits API.
Authentication Server URL:
Sandbox: https://testoauth.expressauth.net/v2/tbsauth
Live: https://oauth.expressauth.net/v2/tbsauth
GETv2/tbsauth
In order to send a GET request to the TaxBandits Authentication Server URL, you must pass the JWS in the “Authentication: {JWS Value}” HTTP Header.
- Once we receive a JWS from you, TaxBandits will provide the JWT (Access token) as a response.
Following are the parts of the JWT response you receive
Header:
{
"alg": "HS256", /*Algorithm = HS256*/
"typ": "JWT" /*Type = JSON Web Token (JWT)*/
}
Payload:
{
"iss": "https://testoauth.expressauth.net/v2/",
"sub": "9f3e403de1d9a3d2",
"aud": "ca64d73230a44d2682937b6844fbc528",
"iat": 1694585458,
"exp": 1694589058
}
Signature:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
siqHfLy59g3UHxrb5gjxg /*Master Secret Key*/
)
Here is the sample JWT response you will receive:
{
"StatusCode": 200,
"StatusName": "Ok",
"StatusMessage": "Successful API call",
"AccessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3Rlc3RvYXV0aC5leHByZXNzYXV0aC5uZXQvdjIvIiwic3ViIjoiOWYzZTQwM2RlMWQ5YTNkMiIsImF1ZCI6ImNhNjRkNzMyMzBhNDRkMjY4MjkzN2I2ODQ0ZmJjNTI4IiwiaWF0IjoxNjk0NTg1NDU4LCJleHAiOjE2OTQ1ODkwNTh9.WPOCs-lxo3GXz7_zGGmQovWZy4WD0smW7n-U-InuoXE",
"TokenType": "Bearer",
"ExpiresIn": 3600,
"Errors": null
}
Sample Code:
- NodeJs
- C#
- Ruby
- Java
- Python
- PHP
- Go
Send the above-listed parameters using a code to decrypt the PDF URL for download. Here is a sample code for NodeJs.
const axios = require("axios");
const jwt = require("jsonwebtoken");
const generateJWT = async (clientId, clientSecret, userToken) => {
try {
// Generate JWS value
const signature = generateJWS(clientId, clientSecret, userToken);
// Getting JWT by requesting OAUTH Server
const oauthResponse = await axios.get('https://testoauth.expressauth.net/V2/tbsauth', {
headers: {
Authentication: signature // Pass JWS as Authentication in headers
}
});
console.log('TaxBandits JWT:', oauthResponse?.data?.AccessToken)
} catch (e) {
console.log("Error in JWT:", e?.response?.data)
}
}
const generateJWS = (clientId, clientSecret, userToken) => {
try {
const payload = {
"iss": clientId,
"sub": clientId,
"aud": userToken,
"iat": Math.floor(new Date().getTime() / 1000)
}
const jwsToken = jwt.sign(payload, clientSecret);
return jwsToken;
} catch (e) {
console.log("Error in JWS: ", e)
}
}
const clientId = "<<TaxBandits Client Id>>" // Client ID retrieved from the console site
const clientSecret = "<<TaxBandits Client Secret>>" // Client Secret retrieved from the console site
const userToken = "<<TaxBandits User Token>>" // User Token retrieved from the console site
generateJWT(clientId, clientSecret, userToken)
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Newtonsoft.Json.Linq;
namespace TaxBandits.WebHook
{
class Program
{
static async Task Main(string[] args)
{
string clientId = "<<TaxBandits Client Id>>"; // Client ID retrieved from the console site
string clientSecret = "<<TaxBandits Client Secret>>"; // Client Secret retrieved from the console site
string userToken = "<<TaxBandits User Token>>"; // User Token retrieved from the console site
await GenerateJWT(clientId, clientSecret, userToken);
}
static async Task GenerateJWT(string clientId, string clientSecret, string userToken)
{
try
{
string signature = GenerateJWS(clientId, clientSecret, userToken);
Console.WriteLine("Error in JWS: " + signature);
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Authentication", signature);
HttpResponseMessage response = await httpClient.GetAsync("https://testoauth.expressauth.net/V2/tbsauth");
if (response.IsSuccessStatusCode)
{
string jsonResponse = await response.Content.ReadAsStringAsync();
JObject jsonObject = JObject.Parse(jsonResponse);
Console.WriteLine("TaxBandits JWT: " + jsonObject["AccessToken"]);
}
else
{
string errorResponse = await response.Content.ReadAsStringAsync();
Console.WriteLine("Error in JWT: " + errorResponse);
}
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.Message);
}
}
static string GenerateJWS(string clientId, string clientSecret, string userToken)
{
try
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(clientSecret));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var payload = new JwtPayload
{
{ "iss", clientId },
{ "sub", clientId },
{ "aud", userToken },
{ "iat", Math.Floor((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds) }
};
var jwtToken = new JwtSecurityToken(
claims: payload.Claims,
signingCredentials: credentials
);
var jwtHandler = new JwtSecurityTokenHandler();
return jwtHandler.WriteToken(jwtToken);
}
catch (Exception e)
{
Console.WriteLine("Error in JWS: " + e.Message);
return null;
}
}
}
}
require 'httparty'
require 'jwt'
def generate_jws(client_id, client_secret, user_token)
payload = {
iss: client_id,
sub: client_id,
aud: user_token,
iat: Time.now.to_i
}
JWT.encode(payload, client_secret, 'HS256')
end
def generate_jwt(client_id, client_secret, user_token)
begin
signature = generate_jws(client_id, client_secret, user_token)
oauth_response = HTTParty.get("https://testoauth.expressauth.net/V2/tbsauth", headers: { 'Authentication' => signature })
puts "TaxBandits JWT: #{oauth_response['AccessToken']}"
rescue => e
puts "Error in JWT: #{e.response&.body}"
end
end
client_id = '<<TaxBandits Client Id>>' # Client ID retrieved from the console site
client_secret = '<<TaxBandits Client Secret>>' # Client Secret retrieved from the console site
user_token = '<<TaxBandits User Token>>' # User Token retrieved from the console site
generate_jwt(client_id, client_secret, user_token)
package org.example;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
public class GenerateJWT {
public static void main(String[] args) {
String clientId = "<<TaxBandits Client Id>>"; // Client ID retrieved from the console site
String clientSecret = "<<TaxBandits Client Secret>>"; // Client Secret retrieved from the console site
String userToken = "<<TaxBandits User Token>>"; // User Token retrieved from the console site
generateJWT(clientId, clientSecret, userToken);
}
public static void generateJWT(String clientId, String clientSecret, String userToken) {
try {
String jwsToken = generateJWS(clientId, clientSecret, userToken);
URL url = new URL("https://testoauth.expressauth.net/V2/tbsauth");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Authentication", jwsToken);
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
String response = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
System.out.println("TaxBandits JWT: " + response);
} else {
String errorResponse = new String(connection.getErrorStream().readAllBytes(), StandardCharsets.UTF_8);
System.out.println("Error in JWT: " + errorResponse);
}
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
public static String generateJWS(String clientId, String clientSecret, String userToken) {
try {
Algorithm algorithm = Algorithm.HMAC256(clientSecret);
Map<String, Object> payload = new HashMap<>();
payload.put("iss", clientId);
payload.put("sub", clientId);
payload.put("aud", userToken);
payload.put("iat", new Date().getTime() / 1000);
return JWT.create()
.withPayload(payload)
.sign(algorithm);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
import requests
import jwt
import time
def generate_jwt(client_id, client_secret, user_token):
try:
# Generate JWS value
signature = generate_jws(client_id, client_secret, user_token)
# Getting JWT by requesting OAUTH Server
headers = {
'Authentication': signature # Pass JWS as Authentication in headers
}
response = requests.get('https://testoauth.expressauth.net/V2/tbsauth', headers=headers)
if response.status_code == 200:
print('TaxBandits JWT:', response.json().get('AccessToken'))
else:
print('Error in JWT:', response.json())
except Exception as e:
print("Error:", e)
def generate_jws(client_id, client_secret, user_token):
try:
payload = {
"iss": client_id,
"sub": client_id,
"aud": user_token,
"iat": int(time.time())
}
jws_token = jwt.encode(payload, client_secret, algorithm='HS256')
return jws_token
except Exception as e:
print("Error in JWS:", e)
if __name__ == "__main__":
client_id = "<<TaxBandits Client Id>>" # Client ID retrieved from the console site
client_secret = "<<TaxBandits Client Secret>>" # Client Secret retrieved from the console site
user_token = "<<TaxBandits User Token>>" # User Token retrieved from the console site
generate_jwt(client_id, client_secret, user_token)
<?php
require 'vendor/autoload.php'; // Include Composer's autoloader
use FirebaseJWTJWT; // Import the JWT class
function generateJWT($clientId, $clientSecret, $userToken) {
try {
// Generate JWS value
$signature = generateJWS($clientId, $clientSecret, $userToken);
// Set cURL options
$url = 'https://testoauth.expressauth.net/V2/tbsauth';
$headers = [
'Authentication: ' . $signature
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// Execute cURL session and get the response
$response = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpcode == 200) {
$data = json_decode($response, true);
echo 'TaxBandits JWT: ' . $data['AccessToken'] . "
";
} else {
echo 'Error in JWT: ' . $response . "
";
}
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "
";
}
}
function generateJWS($clientId, $clientSecret, $userToken) {
try {
$payload = [
"iss" => $clientId,
"sub" => $clientId,
"aud" => $userToken,
"iat" => time() // Current timestamp in seconds
];
$jwsToken = JWT::encode($payload, $clientSecret, "HS256"); // Generate JWT using Firebase JWT library
return $jwsToken;
} catch (Exception $e) {
echo "Error in JWS: " . $e->getMessage() . "
";
}
}
$clientId = "<<TaxBandits Client Id>>"; # Client ID retrieved from the console site
$clientSecret = "<<TaxBandits Client Secret>>"; # Client Secret retrieved from the console site
$userToken = "<<TaxBandits User Token>>"; # User Token retrieved from the console site
generateJWT($clientId, $clientSecret, $userToken);
?>
package main
import (
"fmt"
"io/ioutil"
"net/http"
"time"
"github.com/dgrijalva/jwt-go"
)
func main() {
clientID := "<<TaxBandits Client Id>>" // Client ID retrieved from the console site
clientSecret := "<<TaxBandits Client Secret>>" // Client Secret retrieved from the console site
userToken := "<<TaxBandits User Token>>" // User Token retrieved from the console site
generateJWT(clientID, clientSecret, userToken)
}
func generateJWT(clientID string, clientSecret string, userToken string) {
signature := generateJWS(clientID, clientSecret, userToken)
url := "https://testoauth.expressauth.net/V2/tbsauth"
req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Println("Error creating request:", err)
return
}
req.Header.Set("Authentication", signature)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error making request:", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response:", err)
return
}
if resp.StatusCode == http.StatusOK {
fmt.Println("TaxBandits JWT:", string(body))
} else {
fmt.Println("Error in JWT:", string(body))
}
}
func generateJWS(clientID string, clientSecret string, userToken string) string {
token := jwt.New(jwt.SigningMethodHS256)
// Set claims
claims := token.Claims.(jwt.MapClaims)
claims["iss"] = clientID
claims["sub"] = clientID
claims["aud"] = userToken
claims["iat"] = time.Now().Unix()
// Generate token string
tokenString, err := token.SignedString([]byte(clientSecret))
if err != nil {
fmt.Println("Error generating JWT:", err)
return ""
}
return tokenString
}
Once the JWT is obtained, you can use that token to access the Authorization Server URL. This JWT will expire after an hour.
Server Time
To request an access token, you need to create a JWS (JSON Web Signature) for Authentication. The Payload of the JWS will contain the following parameters:
- Issuer "iss"
- Subject "sub"
- Audience "aud"
- Issued at "iat"
The JWT will be returned in the Response only when the iat value matches our server time. If the iat value does not match, then you will get the error "401 - Invalid 'iat' value in request".
You can use the GetServerTime endpoint to get the timezone, current date, and time of our server. This helps you make sure that the server time of your application is aligned with our API’s server time.
One of the reasons why the server times may mismatch is that your Windows time might not have synced. In that case, you can try synchronizing your time with the Windows time zone server and check if the times match.
GETv2/getservertime
Response Body
Field | Type | Description |
---|---|---|
StatusCode | Number | Returns the status codes like 200,300 etc |
StatusName | string | Name of the status code |
StatusMessage | string | Detailed status message |
ServerDate | string | TaxBandits API server current date |
ServerTime | string | TaxBandits API server current time |
TimeZone | string | TaxBandits API server time zone |
UnixTs | string | Unix time stamp of TaxBandits API server time |
Errors | object[] | Shows error information |
Id | string | Returns the validation error Id |
Name | string | Name of the validation error |
Message | string | Description of the validation error |
Response JSON
{
"StatusCode": 200,
"StatusName": "Ok",
"StatusMessage": "Successful API call",
"ServerDate": "10/10/2023",
"ServerTime": "06:05:48",
"TimeZone": "UTC",
"UnixTs": "1696917948",
"Errors": null
}