integreat
Version:
Node.js integration layer
116 lines • 5.07 kB
JavaScript
import { isObject } from '../utils/is.js';
import { createErrorResponse } from '../utils/response.js';
const MAX_RETRIES = 1;
const shouldRetry = (authentication, retryCount) => authentication?.status === 'timeout' && retryCount < MAX_RETRIES;
const getAuthKey = (authenticator, options, action) => typeof authenticator.extractAuthKey === 'function'
? authenticator.extractAuthKey(options, action) || ''
: '';
export default class Auth {
id;
#authenticator;
#options;
#overrideAuthAsMethod;
#authentications = new Map();
constructor(id, authenticator, options, overrideAuthAsMethod) {
this.id = id;
this.#authenticator = authenticator;
this.#options = options || {};
this.#overrideAuthAsMethod = overrideAuthAsMethod;
}
async authenticate(action, dispatch) {
const authKey = getAuthKey(this.#authenticator, this.#options, action);
let authentication = this.#authentications.get(authKey);
if (authentication?.status === 'granted' &&
this.#authenticator.isAuthenticated(authentication, this.#options, action)) {
return true;
}
let attempt = 0;
do {
authentication = await this.#authenticator.authenticate(this.#options, action, dispatch, authentication || null);
} while (shouldRetry(authentication, attempt++));
this.#authentications.set(authKey, authentication);
return authentication?.status === 'granted';
}
async validate(authentication, action, dispatch) {
if (typeof this.#authenticator.validate !== 'function') {
return createErrorResponse(`Could not authenticate. Authenticator '${this.#authenticator.id}' doesn't support validation`, this.id, 'autherror');
}
if (authentication.status !== 'granted') {
return createErrorResponse('Authentication was refused', this.id, 'noaccess');
}
const response = await this.#authenticator.validate(authentication, this.#options, action, dispatch);
if (response.status === 'ok' && response.access?.ident) {
return response;
}
else {
return createErrorResponse(`Authentication was refused. ${response.error}`, this.id, response.status || 'autherror', response.reason);
}
}
async authenticateAndGetAuthObject(action, authAsMethod, dispatch) {
const fn = this.#authenticator.authentication[authAsMethod];
if (typeof fn === 'function') {
const auth = await this.#authenticator.authenticate(this.#options, action, dispatch, null);
if (auth.status === 'granted') {
return fn(auth);
}
else {
throw new Error(auth.error || 'Authentication failed');
}
}
return null;
}
getAuthObject(transporter, action, providedAuthKey) {
const authKey = providedAuthKey ?? getAuthKey(this.#authenticator, this.#options, action);
const auth = this.#authentications.get(authKey);
if (!auth || auth.status !== 'granted') {
return null;
}
const authenticator = this.#authenticator;
const authAsMethod = this.#overrideAuthAsMethod ||
transporter.defaultAuthAsMethod ||
transporter.authentication;
const authObjectFn = isObject(authenticator?.authentication) &&
typeof authAsMethod === 'string' &&
authenticator.authentication[authAsMethod];
return typeof authObjectFn === 'function' ? authObjectFn(auth) : null;
}
getResponseFromAuth(authKey = '') {
const auth = this.#authentications.get(authKey);
if (!auth) {
return {
status: 'noaccess',
error: `Trying to use auth '${this.id}' before authentication has been run`,
};
}
if (auth.status === 'granted') {
return { status: 'ok' };
}
const status = auth.status === 'refused' ? 'noaccess' : 'autherror';
const error = auth.status === 'refused'
? `Authentication attempt for auth '${this.id}' was refused.`
: `Could not authenticate auth '${this.id}'. [${auth.status}]`;
return { status, error: [error, auth.error].filter(Boolean).join(' ') };
}
applyToAction(action, transporter) {
const authKey = getAuthKey(this.#authenticator, this.#options, action);
const auth = this.#authentications.get(authKey);
if (auth?.status === 'granted') {
return {
...action,
meta: {
...action.meta,
auth: this.getAuthObject(transporter, action, authKey),
},
};
}
return {
...action,
response: {
...action.response,
...this.getResponseFromAuth(authKey),
},
meta: { ...action.meta, auth: null },
};
}
}
//# sourceMappingURL=Auth.js.map