Axios with Vault

This article describes how to safely call external APIs from TAS calculations via the axios library while using secret keys stored in Vault (service tokens, API keys, passwords). Vault is available from version TAS 5.17.

The vault.* functions and axios.setVaultHeader / setVaultQueryParam / requestWithVaultField are available from TAS 5.17. On older installations (5.7 and below) the vault namespace does not exist — verify the client's installation version before using it.

In TAS calculations, never use async / await / Promise / .then(). TAS performs its own code transpilation and async syntax leads to silent failure of the calculation. All vault.get() and axios calls are synchronous — they return the result directly.

Principle — why Vault instead of a hardcoded key

The vault.get('NAME') function does not return the secret key as readable text, but rather an opaque reference (VaultSecretRef). This reference cannot be logged, serialized, or printed — an attempt at JSON.stringify, .toString(), or writing it to a variable will only return [VaultSecretRef].

Consequence: you pass the reference from vault.get() only to trusted functions that know how to process it — setVaultHeader, setVaultQueryParam, requestWithVaultField, and requestRawWithVaultField. Nowhere else.

Prerequisites

  • TAS version 5.17 or higher,
  • a secret key created in Vault (Administration → Vault) under a specific name.

Basic procedure

Using Vault with axios always involves three steps:

  1. Load the reference to the secret via vault.get('SECRET_NAME').
  2. Create a client via axios.getAxios({ baseURL }).
  3. Insert the reference into the request using one of the vault methods (setVaultHeader / setVaultQueryParam / requestWithVaultField).

Minimal example — Bearer token in the Authorization header:

// 1) reference to the secret from Vault
const tokenRef = vault.get('EXTERNAL_API_TOKEN');

// 2) client with base URL + 3) inserting the token into the header
const client = axios.getAxios({ baseURL: 'https://api.partner.com/v2' })
.setVaultHeader('Authorization', tokenRef, 'Bearer ');

// call — TAS inserts the token internally only now
const response = client.get('/users/42');
return response.data;

Three ways to insert a secret

Choose the appropriate method depending on where the API expects the secret.

The most common case: a Bearer token or API key in a header. The header is added to all subsequent requests of the given client.

// setVaultHeader(headerName, secretRef, prefix?)
const apiKeyRef = vault.get('PARTNER_API_KEY');

const client = axios.getAxios({ baseURL: 'https://api.partner.com' })
.setVaultHeader('x-api-key', apiKeyRef); // without prefix
// or with prefix: .setVaultHeader('Authorization', apiKeyRef, 'Bearer ');

const response = client.get('/protected-resource');
return response.data;
The third parameter is an optional prefix that is inserted before the secret value — typically 'Bearer ' or 'bearer ' (including the trailing space).

2. Into a query parameter — setVaultQueryParam

For APIs that expect the key in the URL (e.g. ?apiKey=...). The parameter is automatically appended to every request of the client.

const apiKeyRef = vault.get('PUBLIC_API_KEY');

const client = axios.getAxios({ baseURL: 'https://api.example.com' })
.setVaultQueryParam('apiKey', apiKeyRef);

// each request automatically contains ?apiKey=<resolved-secret>
const response = client.get('/results');
return response.data;

3. Into the request body — requestWithVaultField

When the API expects the secret directly in the body (typically an OAuth2 client_credentials flow with client_secret). The secret is inserted into the specified field in data without passing through the code.

const clientSecretRef = vault.get('OAUTH_CLIENT_SECRET');

const client = axios.getAxios({ baseURL: 'https://auth.example.com' });

// requestWithVaultField(config, [{ fieldName, ref }])
const tokens = client.requestWithVaultField(
{
method: 'POST',
url: '/oauth/token',
data: {
grant_type: 'client_credentials',
client_id: 'tas-service'
}
},
[{ fieldName: 'client_secret', ref: clientSecretRef }]
);

return tokens.data.access_token;
The field specified in fieldName (here client_secret) is added to the body automatically — do not write it into the data object manually.

Full response — requestRawWithVaultField

If, in addition to the data, you also need the status, statusText, or response headers, use the raw variant. Available from v5.7.37 (raw axios variants), vault fields from 5.17.

const secretRef = vault.get('SERVICE_PASSWORD');

const client = axios.getAxios({ baseURL: 'https://api.example.com' });

const raw = client.requestRawWithVaultField(
{
method: 'POST',
url: '/login',
data: { username: 'tas-service' }
},
[{ fieldName: 'password', ref: secretRef }]
);

if (raw.status !== 200) {
proc.error('Login failed', { status: raw.status });
debug.error('Login to the external service failed.');
}

return raw.data;

Complete example — OAuth2 token and a follow-up call

A typical scenario: obtaining an access token via a client_secret from Vault and using it for an authorized call.

// 1) reference to the client secret
const clientSecretRef = vault.get('OAUTH_CLIENT_SECRET');

const auth = axios.getAxios({ baseURL: 'https://auth.service.com' });

// 2) exchange for an access token (secret in the body)
const tokenResp = auth.requestWithVaultField(
{
method: 'POST',
url: '/token',
data: { grant_type: 'client_credentials', client_id: 'tas-service' }
},
[{ fieldName: 'client_secret', ref: clientSecretRef }]
);

const accessToken = tokenResp.data.access_token;

// 3) authorized call with the token in the header
const api = axios.getAxios({ baseURL: 'https://api.service.com' })
.setVaultHeader('Authorization', accessToken, 'Bearer ');

const me = api.get('/me');
return me.data;

Logging and error handling

In TAS calculations, log exclusively via proc.info / proc.warn / proc.errornever console.log. To block a task with an error message, use debug.error.

const tokenRef = vault.get('EXTERNAL_API_TOKEN');
const client = axios.getAxios({ baseURL: 'https://api.example.com' })
.setVaultHeader('Authorization', tokenRef, 'Bearer ');

try {
const resp = client.post('/users', { email: vars['EMAIL'].getValue() });
return resp.data;
} catch (err) {
proc.error('API call failed', { message: err.message });
debug.error('Failed to create the user in the external system.');
}
The reference from vault.get() is safe to pass into proc.* as well as into an error message — it will always be shown only as [VaultSecretRef], never as a readable value.

What not to do

Anti-pattern

Why it's wrong

const token = 'eyJhb...';

Hardcoded secret in the code — it leaks in the template export as well as in the log. Always use vault.get().

await axios.getAxios()...

async/await conflicts with TAS transpilation → silent failure. Call synchronously.

vars['X'].setValue(tokenRef)

Storing the reference in a variable makes no sense — the value is not saved, [VaultSecretRef] is returned.

Secret in data manually

A secret written directly into the body passes through the code. Use requestWithVaultField.

Troubleshooting

Problem

Solution

vault is not defined

The installation is running on a version lower than 5.15. Verify the TAS version; on older versions handle tokens via StorageApi or an encrypted configuration.

Secret 'NAME' not found

The secret is not created in Vault, or the template/script does not have access enabled. Check Administration → Vault.

401 Unauthorized

Verify that the secret value is correct and has not expired, and that the prefix in setVaultHeader matches (e.g. 'Bearer ' with a space).

The calculation silently "does nothing"

Almost certainly async/await or .then() in the code. Rewrite to synchronous calls.

Frantisek Brych Updated by Frantisek Brych

AXIOS API

Axios with SSL Certificate

Contact

Syca (opens in a new tab)

Powered by HelpDocs (opens in a new tab)