@adonisjs/auth
Version:
Official authentication provider for Adonis framework
124 lines (123 loc) • 4.1 kB
JavaScript
;
/*
* @adonisjs/auth
*
* (c) AdonisJS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.OATClient = void 0;
const luxon_1 = require("luxon");
const crypto_1 = require("crypto");
const utils_1 = require("@poppinss/utils");
const helpers_1 = require("@poppinss/utils/build/helpers");
const ProviderToken_1 = require("../../Tokens/ProviderToken");
/**
* OAT client to login a user during tests using the
* opaque tokens guard
*/
class OATClient {
constructor(name, config, provider, tokenProvider) {
this.name = name;
this.config = config;
this.provider = provider;
this.tokenProvider = tokenProvider;
/**
* Length of the raw token. The hash length will vary
*/
this.tokenLength = 60;
/**
* Token type for the persistance store
*/
this.tokenType = this.config.tokenProvider.type || 'opaque_token';
}
/**
* Returns the provider user instance from the regular user details. Raises
* exception when id is missing
*/
async getUserForLogin(user, identifierKey) {
const providerUser = await this.provider.getUserFor(user);
/**
* Ensure id exists on the user
*/
const id = providerUser.getId();
if (!id) {
throw new utils_1.Exception(`Cannot login user. Value of "${identifierKey}" is not defined`);
}
return providerUser;
}
/**
* Converts value to a sha256 hash
*/
generateHash(token) {
return (0, crypto_1.createHash)('sha256').update(token).digest('hex');
}
/**
* Converts expiry duration to an absolute date/time value
*/
getExpiresAtDate(expiresIn) {
if (!expiresIn) {
return;
}
const milliseconds = typeof expiresIn === 'string' ? helpers_1.string.toMs(expiresIn) : expiresIn;
return luxon_1.DateTime.local().plus({ milliseconds });
}
/**
* Generates a new token + hash for the persistance
*/
generateTokenForPersistance(expiresIn) {
const token = helpers_1.string.generateRandom(this.tokenLength);
return {
token,
hash: this.generateHash(token),
expiresAt: this.getExpiresAtDate(expiresIn),
};
}
/**
* Returns the request data to mark user as logged in
*/
async login(user, options) {
/**
* Normalize options with defaults
*/
const { expiresIn, name, ...meta } = Object.assign({
name: 'Opaque Access Token',
}, options);
/**
* Since the login method is not exposed to the end user, we cannot expect
* them to instantiate and pass an instance of provider user, so we
* create one manually.
*/
const providerUser = await this.getUserForLogin(user, this.config.provider.identifierKey);
/**
* "getUserForLogin" raises exception when id is missing, so we can
* safely assume it is defined
*/
const id = providerUser.getId();
const token = this.generateTokenForPersistance(expiresIn);
/**
* Persist token to the database. Make sure that we are always
* passing the hash to the storage driver
*/
const providerToken = new ProviderToken_1.ProviderToken(name, token.hash, id, this.tokenType);
providerToken.expiresAt = token.expiresAt;
providerToken.meta = meta;
this.tokenId = await this.tokenProvider.write(providerToken);
return {
headers: {
Authorization: `Bearer ${helpers_1.base64.urlEncode(this.tokenId)}.${token.token}`,
},
};
}
/**
* Logout user
*/
async logout() {
if (this.tokenId) {
await this.tokenProvider.destroy(this.tokenId, this.tokenType);
}
}
}
exports.OATClient = OATClient;