Refresh Access Token when receiving 401 error #1840
-
As per requested in the discussion #1781 I am creating a new thread for my issue: We are consuming an external API which requires authentication, it expires after few hours and we should refresh the AC. When external API throws a 401 error, instead of throwing an error without the data output, we could get the new AC by performing a login via a HTTP request and then with the new AC (refreshed token) retry the request and send the data output. What would you recommend? Is it possible? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 5 replies
-
Use |
Beta Was this translation helpful? Give feedback.
-
Here is an excerpt of the code I use to interact with Sugar CRM Rest API with OAuth token. /**
* Base Got configuration for Sugar CRM API
*/
export const baseOptions: ExtendOptions = {
agent: {
http: new HttpAgent({keepAlive: true}),
https: new HttpsAgent({keepAlive: true}),
},
prefixUrl: getBaseUrl(),
};
let token: string | undefined;
const authURL = 'oauth2/token';
const authOptions: ExtendOptions = {
method: 'POST',
json: {
grant_type: 'password',
client_id: 'sugar',
client_secret: '',
platform: 'base',
...getCredentials(),
},
};
/** @internal Got instance to be use for authentication */
const authenticationInstance = got.extend(baseOptions, authOptions);
/** @internal Helper function to request an authentication token */
export const getNewAuthToken = async (): Promise<string> => {
const responsePromise = authenticationInstance(authURL);
const body = await responsePromise.json();
if (is.plainObject(body) && body.access_token) {
token = body.access_token as string;
return token;
}
throw new Error('getNewAuthToken() bad response');
};
/**
* Returns an authenticated Got instance for Sugar CRM API
*/
export const authenticatedInstance = got.extend(baseOptions, {
allowGetBody: true,
hooks: {
afterResponse: [
async (response: Response, retryWithMergedOptions) => {
// Unauthorized
if (response.statusCode === 401) {
const updatedOptions: ExtendOptions = {headers: {'oauth-token': await getNewAuthToken()}};
// Save for further requests
authenticatedInstance.defaults.options = got.mergeOptions(
authenticatedInstance.defaults.options,
updatedOptions
);
return retryWithMergedOptions(updatedOptions);
}
// No changes otherwise
return response;
},
],
},
mutableDefaults: true,
pagination: {
paginate: (response: Response) => {
const body = JSON.parse((response as Response<string>).body) as CrmListResponse;
if (is.plainObject(body) && is.number(body.next_offset) && body.next_offset >= 0) {
const {json} = response.request.options;
return {json: {...json, offset: body.next_offset}};
}
return false;
},
stackAllItems: false,
transform: (response: Response) => {
const {body} = response;
const parsed = is.string(body) ? (JSON.parse(body) as JsonObject) : body;
if (is.plainObject(parsed)) {
const {records} = parsed;
if (is.array(records)) {
return records;
}
throw new Error(typeof records);
}
throw new Error(typeof parsed);
},
},
}); |
Beta Was this translation helpful? Give feedback.
Here is an excerpt of the code I use to interact with Sugar CRM Rest API with OAuth token.