Authentication
All Assist Insurances APIs use OAuth 2.0 with the client credentials flow for authentication. This guide covers everything you need to implement secure authentication in your application.
OAuth 2.0 Client Credentials Flow
The client credentials flow is designed for server-to-server authentication where your application authenticates using its client ID and secret.
Flow Diagram
┌─────────────┐ ┌──────────────┐
│ │ │ │
│ Your │ 1. POST /auth/token │ Assist │
│ Server │ ──────────────────────────────> │ API │
│ │ (client_id + client_secret) │ │
│ │ │ │
│ │ 2. access_token │ │
│ │ <────────────────────────────── │ │
│ │ │ │
│ │ 3. API Request │ │
│ │ ──────────────────────────────> │ │
│ │ (Authorization: Bearer token)│ │
│ │ │ │
│ │ 4. API Response │ │
│ │ <────────────────────────────── │ │
│ │ │ │
└─────────────┘ └──────────────┘
Getting Your Credentials
Contact our technical support team to obtain your API credentials:
- Email: neil.reilly@assistinsurances.ie
- What you'll receive:
- Client ID (UUID format)
- Client Secret (secure string)
- OAuth scope
- API base URL
Never commit credentials to version control or expose them in client-side code. Use environment variables or a secure secret management system.
Token Endpoint
Production API
POST https://api.assistinsurances.ie/auth/token
Test API
POST https://apim-assist-test-ne.azure-api.net/auth/token
Request Format
The token endpoint accepts requests in two formats for convenience:
Option 1: Form-Encoded (Standard OAuth)
POST /auth/token HTTP/1.1
Host: api.assistinsurances.ie
Content-Type: application/x-www-form-urlencoded
client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=api://1c15f5fa-f434-401b-b4ec-ab3ea75d48bb/assist-api-gateway/.default&grant_type=client_credentials
Option 2: JSON (Convenience Format)
POST /auth/token HTTP/1.1
Host: api.assistinsurances.ie
Content-Type: application/json
{
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"scope": "api://1c15f5fa-f434-401b-b4ec-ab3ea75d48bb/assist-api-gateway/.default",
"grant_type": "client_credentials"
}
Response Format
Success Response (200 OK)
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ik1HTHFqOThWTkxvWGFGZnBKQ0JwZ0I0SmFLcyJ9...",
"token_type": "Bearer",
"expires_in": 3599
}
Fields:
access_token- JWT token to use for API authenticationtoken_type- Always "Bearer"expires_in- Token validity in seconds (typically 3599 = 1 hour)
Error Response (401 Unauthorized)
{
"error": "invalid_client",
"error_description": "Client authentication failed",
"statusCode": 401
}
Implementation Examples
Basic Token Request
- JavaScript/Node.js
- Python
- C#
- Go
async function getAccessToken() {
const response = await fetch('https://api.assistinsurances.ie/auth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
client_id: process.env.ASSIST_CLIENT_ID,
client_secret: process.env.ASSIST_CLIENT_SECRET,
scope: 'api://1c15f5fa-f434-401b-b4ec-ab3ea75d48bb/assist-api-gateway/.default',
grant_type: 'client_credentials',
}),
});
if (!response.ok) {
throw new Error(`Token request failed: ${response.statusText}`);
}
const data = await response.json();
return data.access_token;
}
import os
import requests
from typing import Dict
def get_access_token() -> str:
"""Obtain an access token from the Assist API."""
response = requests.post(
'https://api.assistinsurances.ie/auth/token',
data={
'client_id': os.environ['ASSIST_CLIENT_ID'],
'client_secret': os.environ['ASSIST_CLIENT_SECRET'],
'scope': 'api://1c15f5fa-f434-401b-b4ec-ab3ea75d48bb/assist-api-gateway/.default',
'grant_type': 'client_credentials',
},
timeout=30
)
response.raise_for_status()
return response.json()['access_token']
using System;
using System.Net.Http;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
public class AssistAuthClient
{
private readonly HttpClient _httpClient;
private readonly string _clientId;
private readonly string _clientSecret;
private readonly string _baseUrl;
public AssistAuthClient(string baseUrl)
{
_httpClient = new HttpClient();
_clientId = Environment.GetEnvironmentVariable("ASSIST_CLIENT_ID");
_clientSecret = Environment.GetEnvironmentVariable("ASSIST_CLIENT_SECRET");
_baseUrl = baseUrl;
}
public async Task<string> GetAccessTokenAsync()
{
var content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "client_id", _clientId },
{ "client_secret", _clientSecret },
{ "scope", "api://1c15f5fa-f434-401b-b4ec-ab3ea75d48bb/assist-api-gateway/.default" },
{ "grant_type", "client_credentials" }
});
var response = await _httpClient.PostAsync(
$"{_baseUrl}/auth/token",
content
);
response.EnsureSuccessStatusCode();
var jsonDoc = JsonDocument.Parse(
await response.Content.ReadAsStringAsync()
);
return jsonDoc.RootElement
.GetProperty("access_token")
.GetString();
}
}
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"strings"
)
type TokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in"`
}
func GetAccessToken(baseURL string) (string, error) {
data := url.Values{}
data.Set("client_id", os.Getenv("ASSIST_CLIENT_ID"))
data.Set("client_secret", os.Getenv("ASSIST_CLIENT_SECRET"))
data.Set("scope", "api://1c15f5fa-f434-401b-b4ec-ab3ea75d48bb/assist-api-gateway/.default")
data.Set("grant_type", "client_credentials")
resp, err := http.Post(
fmt.Sprintf("%s/auth/token", baseURL),
"application/x-www-form-urlencoded",
strings.NewReader(data.Encode()),
)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return "", fmt.Errorf("token request failed: %s", body)
}
var tokenResp TokenResponse
if err := json.NewDecoder(resp.Body).Decode(&tokenResp); err != nil {
return "", err
}
return tokenResp.AccessToken, nil
}
Token Caching and Refresh
Always cache tokens and reuse them until they expire. Making a new token request for every API call is inefficient and may trigger rate limits.
- JavaScript/Node.js
- Python
- C#
class AssistAuthClient {
constructor(clientId, clientSecret, baseUrl) {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.baseUrl = baseUrl;
this.token = null;
this.tokenExpiresAt = null;
}
async getAccessToken() {
// Return cached token if still valid (with 5-minute buffer)
if (this.token && this.tokenExpiresAt > Date.now() + 300000) {
return this.token;
}
// Request new token
const response = await fetch(`${this.baseUrl}/auth/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
client_id: this.clientId,
client_secret: this.clientSecret,
scope: 'api://1c15f5fa-f434-401b-b4ec-ab3ea75d48bb/assist-api-gateway/.default',
grant_type: 'client_credentials',
}),
});
if (!response.ok) {
throw new Error(`Token request failed: ${response.statusText}`);
}
const data = await response.json();
// Cache token with expiry
this.token = data.access_token;
this.tokenExpiresAt = Date.now() + (data.expires_in * 1000);
return this.token;
}
async makeAuthenticatedRequest(endpoint, options = {}) {
const token = await this.getAccessToken();
return fetch(`${this.baseUrl}${endpoint}`, {
...options,
headers: {
...options.headers,
'Authorization': `Bearer ${token}`,
},
});
}
}
// Usage
const client = new AssistAuthClient(
process.env.ASSIST_CLIENT_ID,
process.env.ASSIST_CLIENT_SECRET,
'https://api.assistinsurances.ie'
);
// Token is automatically cached and refreshed
const response = await client.makeAuthenticatedRequest('/priceQuote', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ data: { /* quote data */ } }),
});
import os
import time
import requests
from typing import Optional
from datetime import datetime, timedelta
class AssistAuthClient:
def __init__(self, base_url: str):
self.client_id = os.environ['ASSIST_CLIENT_ID']
self.client_secret = os.environ['ASSIST_CLIENT_SECRET']
self.base_url = base_url
self.token: Optional[str] = None
self.token_expires_at: Optional[datetime] = None
self.session = requests.Session()
def get_access_token(self) -> str:
"""Get cached token or request new one if expired."""
# Return cached token if still valid (with 5-minute buffer)
if self.token and self.token_expires_at:
buffer = timedelta(minutes=5)
if datetime.now() < (self.token_expires_at - buffer):
return self.token
# Request new token
response = self.session.post(
f'{self.base_url}/auth/token',
data={
'client_id': self.client_id,
'client_secret': self.client_secret,
'scope': 'api://1c15f5fa-f434-401b-b4ec-ab3ea75d48bb/assist-api-gateway/.default',
'grant_type': 'client_credentials',
},
timeout=30
)
response.raise_for_status()
data = response.json()
# Cache token with expiry
self.token = data['access_token']
self.token_expires_at = datetime.now() + timedelta(
seconds=data['expires_in']
)
return self.token
def make_authenticated_request(self, endpoint: str, **kwargs) -> requests.Response:
"""Make an authenticated API request."""
token = self.get_access_token()
headers = kwargs.get('headers', {})
headers['Authorization'] = f'Bearer {token}'
kwargs['headers'] = headers
return self.session.request(url=f'{self.base_url}{endpoint}', **kwargs)
# Usage
client = AssistAuthClient('https://api.assistinsurances.ie')
# Token is automatically cached and refreshed
response = client.make_authenticated_request(
'/priceQuote',
method='POST',
json={'data': { # quote data }}
)
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
public class AssistAuthClient
{
private readonly HttpClient _httpClient;
private readonly string _clientId;
private readonly string _clientSecret;
private readonly string _baseUrl;
private string _token;
private DateTime _tokenExpiresAt;
public AssistAuthClient(string baseUrl)
{
_httpClient = new HttpClient();
_clientId = Environment.GetEnvironmentVariable("ASSIST_CLIENT_ID");
_clientSecret = Environment.GetEnvironmentVariable("ASSIST_CLIENT_SECRET");
_baseUrl = baseUrl;
}
public async Task<string> GetAccessTokenAsync()
{
// Return cached token if still valid (with 5-minute buffer)
if (!string.IsNullOrEmpty(_token) &&
_tokenExpiresAt > DateTime.UtcNow.AddMinutes(5))
{
return _token;
}
// Request new token
var content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "client_id", _clientId },
{ "client_secret", _clientSecret },
{ "scope", "api://1c15f5fa-f434-401b-b4ec-ab3ea75d48bb/assist-api-gateway/.default" },
{ "grant_type", "client_credentials" }
});
var response = await _httpClient.PostAsync(
$"{_baseUrl}/auth/token",
content
);
response.EnsureSuccessStatusCode();
var jsonDoc = JsonDocument.Parse(
await response.Content.ReadAsStringAsync()
);
// Cache token with expiry
_token = jsonDoc.RootElement.GetProperty("access_token").GetString();
var expiresIn = jsonDoc.RootElement.GetProperty("expires_in").GetInt32();
_tokenExpiresAt = DateTime.UtcNow.AddSeconds(expiresIn);
return _token;
}
public async Task<HttpResponseMessage> MakeAuthenticatedRequestAsync(
string endpoint,
HttpMethod method,
HttpContent content = null)
{
var token = await GetAccessTokenAsync();
var request = new HttpRequestMessage(method, $"{_baseUrl}{endpoint}")
{
Content = content
};
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
return await _httpClient.SendAsync(request);
}
}
// Usage
var client = new AssistAuthClient("https://api.assistinsurances.ie");
// Token is automatically cached and refreshed
var response = await client.MakeAuthenticatedRequestAsync(
"/priceQuote",
HttpMethod.Post,
new StringContent(jsonData, Encoding.UTF8, "application/json")
);
Using the Access Token
Once you have an access token, include it in the Authorization header of all API requests:
GET /vehicle-lookup/12-D-12345 HTTP/1.1
Host: api.assistinsurances.ie
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
Security Best Practices
1. Secure Storage
Do:
- Store credentials in environment variables
- Use secret management systems (AWS Secrets Manager, Azure Key Vault, HashiCorp Vault)
- Encrypt credentials at rest
Don't:
- Hard-code credentials in source code
- Commit credentials to version control
- Expose credentials in logs or error messages
- Store credentials in client-side code
2. Token Handling
Do:
- Cache tokens and reuse until expiry
- Implement automatic refresh with a buffer (e.g., refresh 5 minutes before expiry)
- Clear tokens on application shutdown
Don't:
- Request a new token for every API call
- Share tokens between different applications
- Log full token values
3. Network Security
Do:
- Always use HTTPS
- Implement request timeouts (recommended: 30 seconds)
- Use connection pooling for efficiency
Don't:
- Make requests over HTTP
- Disable SSL certificate validation
- Allow indefinite request timeouts
4. Error Handling
Do:
- Implement retry logic with exponential backoff
- Handle token expiry gracefully
- Log authentication failures for monitoring
Don't:
- Retry authentication failures indefinitely
- Expose error details to end users
- Ignore authentication errors
Troubleshooting
Invalid Client Error
{
"error": "invalid_client",
"error_description": "Client authentication failed"
}
Causes:
- Incorrect client ID or secret
- Credentials for wrong environment
- Trailing whitespace in credentials
Solution: Verify your credentials and ensure you're using the correct API base URL.
Invalid Scope Error
{
"error": "invalid_scope",
"error_description": "The requested scope is invalid"
}
Solution: Ensure you're using the correct scope: api://1c15f5fa-f434-401b-b4ec-ab3ea75d48bb/assist-api-gateway/.default
Token Expired Error
{
"statusCode": 401,
"message": "The token has expired"
}
Solution: Implement token caching with automatic refresh before expiry.
Rate Limit Exceeded
{
"statusCode": 429,
"message": "Rate limit exceeded"
}
Solution: Implement exponential backoff and ensure you're caching tokens properly.
Testing
Using cURL
# 1. Get token and save to variable
TOKEN=$(curl -s -X POST "https://api.assistinsurances.ie/auth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=api://1c15f5fa-f434-401b-b4ec-ab3ea75d48bb/assist-api-gateway/.default" \
-d "grant_type=client_credentials" \
| jq -r '.access_token')
# 2. Verify token
echo "Token: ${TOKEN:0:50}..."
# 3. Use token in API call
curl -X POST "https://api.assistinsurances.ie/priceQuote" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"data": {"in_dts.raterCover": "Comprehensive"}}'
Using Postman
- Create a new request collection
- Add authorization at collection level:
- Type: OAuth 2.0
- Grant Type: Client Credentials
- Access Token URL:
https://api.assistinsurances.ie/auth/token - Client ID: Your client ID
- Client Secret: Your client secret
- Scope:
api://1c15f5fa-f434-401b-b4ec-ab3ea75d48bb/assist-api-gateway/.default
- Click "Get New Access Token"
- All requests in the collection will automatically use the token
Next Steps
- Insly Integration Guide - Implement Insly quote integration
- Applied Systems Guide - Full quote lifecycle
- Error Handling - Handle errors and rate limits
- API Reference - Explore all available endpoints