@titanium/authentication-mock
Version:
⭐ Axway Amplify module for mocking OAuth Authentication with Appcelerator Titanium SDK Framework
168 lines (143 loc) • 4.73 kB
JavaScript
const _ = require('lodash');
const jwt = require('@titanium/jwt');
const moment = require('moment');
const path = require('path');
const fs = require('fs');
// TIBUG: __dirname will randomly be undefined
// console.debug(`🦠 __dirname: ${JSON.stringify(__dirname, null, 2)}`);
const kids = [ 'a5f23fbc289dac0e9eada1aa0ac2e27f' ];
let mock_users_path = './mock-users.json';
// TIBUG: Titanium can't handle relative paths when loading files so must convert to absolute path
if (typeof Ti !== 'undefined') {
mock_users_path = path.join(Ti.Filesystem.resourcesDirectory, `./${__dirname}`, mock_users_path);
}
export class MockAuthentication {
constructor({
users,
audience = 'audience',
client_id = 'client_id',
device,
issuer = 'issuer',
subject = 'subject',
access_token_expires_in = 300, // 5 minutes
refresh_token_expires_in = 5259492, // 2 months
scopes = [ 'scope1' ],
kid = kids[0],
} = {}) {
this.users = users;
this.audience = audience;
this.client_id = client_id;
this.device = device;
this.issuer = issuer;
this.scopes = scopes;
this.subject = subject;
this.access_token_expires_in = access_token_expires_in;
this.refresh_token_expires_in = refresh_token_expires_in;
this.kid = kid;
if (!this.users) {
try {
this.users = JSON.parse(fs.readFileSync(mock_users_path, 'utf8'));
} catch (error) {
console.error(error);
this.users = [];
}
}
}
async getPublicKey({ kid } = {}) {
console.debug(`📌 you are here → MockAuthentication.getPublicKey({kid:${kid}})`);
if (!kid) {
return this.getPublicKey({ kid: this.kid });
}
let public_key_path = `./keys/public/${kid}.pub`;
// TIBUG: Titanium can't handle relative paths when loading files so must convert to absolute path
if (typeof Ti !== 'undefined') {
public_key_path = path.join(Ti.Filesystem.resourcesDirectory, `./${__dirname}`, public_key_path);
}
const public_key = fs.readFileSync(public_key_path, 'utf8');
if (! this.public_key && (kid === this.kid)) {
this.public_key = public_key;
}
return public_key;
}
async authenticate({
username,
password,
options: {
audience = this.audience,
client_id = this.client_id,
device = this.device || require('crypto').createHash('md5').update(username).digest('hex'),
issuer = this.issuer,
scopes = this.scopes,
subject = this.subject,
access_token_expires_in = this.access_token_expires_in,
refresh_token_expires_in = this.refresh_token_expires_in,
kid = this.kid,
} = {},
} = {}) {
const response = {
authenticated: false,
claims: [],
};
if (!username || !password || username !== password) {
response.error = 'authentication failed';
return response;
}
const user = _.find(this.users, { username });
if (!user) {
response.error = 'user not found';
return response;
}
const getPrivateKey = async ({ kid } = {}) => {
let private_key_path = `./keys/private/${kid}.key`;
// TIBUG: Titanium can't handle relative paths when loading files so must convert to absolute path
if (typeof Ti !== 'undefined') {
private_key_path = path.join(Ti.Filesystem.resourcesDirectory, `./${__dirname}`, private_key_path);
}
const private_key = fs.readFileSync(private_key_path, 'utf8');
return private_key;
};
const private_key = await getPrivateKey({ kid });
response.access_token = jwt.sign(
{
token: user.token,
name: user.formatted_name,
given_name: user.first_name,
family_name: user.last_name,
picture: user.picture,
updated_at: user.entity_updated_at,
client_id: client_id,
username: username,
userid: user.id,
email: user.email,
email_verified: user.email_verified,
job_title: user.job_title,
zoneinfo: user.timezone,
phone_number: user.phone,
phone_number_verified: user.phone_verified,
auth_time: moment(),
scope: scopes.join(' '),
azp: device,
kid,
},
private_key,
{
algorithm: 'RS256',
issuer: issuer,
subject: subject,
audience: audience,
expiresIn: access_token_expires_in,
},
);
response.user = {
username: username,
first_name: user.first_name,
last_name: user.last_name,
formatted_name: user.formatted_name,
email: user.email,
};
response.authenticated = true;
console.debug(`🦠 MockAuthentication response: ${JSON.stringify(response, null, 2)}`);
return response;
}
}
module.exports = MockAuthentication;