Authentication Error

https://bessapay.net/errors/authentication-error

Overview

An Authentication Error occurs when there's a problem specifically with the authentication process. Unlike the more general Unauthorized error, authentication errors usually indicate a specific issue with the credentials format, authentication method, or authentication service.

Details

  • Error Code: AUTHENTICATION_ERROR
  • HTTP Status: 401
  • Error Type: Client Error

Common scenarios

  • • Malformed authentication token
  • • Invalid authentication scheme
  • • Authentication service unavailable
  • • Token validation error
  • • Signature verification failed

Example

Authentication Error Response
1{
2  "type": "https://bessapay.net/errors/authentication-error",
3  "title": "Authentication Error",
4  "status": 401,
5  "detail": "JWT token signature validation failed",
6  "instance": "/api/v1/accounts",
7  "errorCode": "AUTHENTICATION_ERROR",
8  "timestamp": "2023-06-15T18:15:33Z"
9}

How to Fix

Check token format

Ensure your authentication token is properly formatted. For JWT tokens, verify that all three parts (header, payload, signature) are present and properly encoded.

Verify token freshness

Check that your token is not expired. JWT tokens contain an expiration timestamp. If your token has expired, request a new one.

Checking JWT Expiration
1// Function to check if a JWT token is expired
2function isTokenExpired(token) {
3  try {
4    // Get the payload part (second part of the JWT)
5    const base64Url = token.split('.')[1];
6    const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
7    const payload = JSON.parse(window.atob(base64));
8    
9    // Check the expiration time
10    const currentTime = Math.floor(Date.now() / 1000);
11    return payload.exp < currentTime;
12  } catch (e) {
13    console.error('Error parsing token:', e);
14    return true; // Assume expired if any error
15  }
16}

Use the correct authentication scheme

BessaPay API supports different authentication schemes:

  • API Key: Authorization: Bearer YOUR_API_KEY
  • JWT Token: Authorization: Bearer YOUR_JWT_TOKEN
  • OAuth2: Authorization: Bearer YOUR_OAUTH_TOKEN

Make sure you're using the right scheme for the endpoint you're accessing.

Refresh your authentication

If you're using OAuth or JWT tokens, implement token refresh logic to obtain a new token when the current one expires or becomes invalid.

Code Example: Handling Authentication Errors

JavaScript Authentication Error Handling
1// Example of handling Authentication errors with token refresh
2class AuthClient {
3  constructor(clientId, clientSecret, apiBaseUrl = 'https://api.semuni.com/v1') {
4    this.clientId = clientId;
5    this.clientSecret = clientSecret;
6    this.apiBaseUrl = apiBaseUrl;
7    this.token = null;
8    this.refreshToken = null;
9    this.tokenExpiry = null;
10  }
11  
12  // Get a valid token, refreshing if necessary
13  async getValidToken() {
14    // Check if token is expired or about to expire (within 60 seconds)
15    const now = Math.floor(Date.now() / 1000);
16    if (!this.token || !this.tokenExpiry || this.tokenExpiry - 60 < now) {
17      // Need to get a new token
18      if (this.refreshToken) {
19        await this.refreshAccessToken();
20      } else {
21        await this.authenticate();
22      }
23    }
24    
25    return this.token;
26  }
27  
28  // Initial authentication
29  async authenticate() {
30    try {
31      const response = await fetch(`${this.apiBaseUrl}/auth/token`, {
32        method: 'POST',
33        headers: {
34          'Content-Type': 'application/json'
35        },
36        body: JSON.stringify({
37          client_id: this.clientId,
38          client_secret: this.clientSecret,
39          grant_type: 'client_credentials'
40        })
41      });
42      
43      if (!response.ok) {
44        const error = await response.json();
45        throw new Error(`Authentication failed: ${error.detail || 'Unknown error'}`);
46      }
47      
48      const authData = await response.json();
49      this.token = authData.access_token;
50      this.refreshToken = authData.refresh_token;
51      this.tokenExpiry = now + authData.expires_in;
52      
53      return this.token;
54    } catch (error) {
55      console.error('Authentication error:', error);
56      throw error;
57    }
58  }
59  
60  // Refresh an existing token
61  async refreshAccessToken() {
62    if (!this.refreshToken) {
63      return this.authenticate();
64    }
65    
66    try {
67      const response = await fetch(`${this.apiBaseUrl}/auth/token`, {
68        method: 'POST',
69        headers: {
70          'Content-Type': 'application/json'
71        },
72        body: JSON.stringify({
73          client_id: this.clientId,
74          refresh_token: this.refreshToken,
75          grant_type: 'refresh_token'
76        })
77      });
78      
79      if (!response.ok) {
80        // If refresh fails, try full authentication
81        if (response.status === 401) {
82          return this.authenticate();
83        }
84        
85        const error = await response.json();
86        throw new Error(`Token refresh failed: ${error.detail || 'Unknown error'}`);
87      }
88      
89      const authData = await response.json();
90      const now = Math.floor(Date.now() / 1000);
91      this.token = authData.access_token;
92      this.refreshToken = authData.refresh_token || this.refreshToken;
93      this.tokenExpiry = now + authData.expires_in;
94      
95      return this.token;
96    } catch (error) {
97      console.error('Token refresh error:', error);
98      // Fall back to full authentication
99      return this.authenticate();
100    }
101  }
102  
103  // Make an authenticated API call
104  async request(endpoint, options = {}) {
105    try {
106      const token = await this.getValidToken();
107      
108      const response = await fetch(`${this.apiBaseUrl}${endpoint}`, {
109        ...options,
110        headers: {
111          'Authorization': `Bearer ${token}`,
112          'Content-Type': 'application/json',
113          ...options.headers
114        }
115      });
116      
117      if (response.status === 401) {
118        const errorData = await response.json();
119        
120        // Check if it's an authentication error
121        if (errorData.type === 'https://bessapay.net/errors/authentication-error') {
122          console.warn('Authentication error, retrying with fresh token');
123          
124          // Force new token and retry once
125          await this.authenticate();
126          return this.request(endpoint, options);
127        }
128      }
129      
130      return response;
131    } catch (error) {
132      console.error('API request error:', error);
133      throw error;
134    }
135  }
136}
137
138// Usage example
139const authClient = new AuthClient('your-client-id', 'your-client-secret');
140authClient.request('/accounts')
141  .then(response => response.json())
142  .then(data => console.log(data))
143  .catch(error => console.error('Error:', error));