Files
fuse-angular/src/app/core/auth/auth.utils.ts
2021-05-14 17:17:06 +03:00

205 lines
5.3 KiB
TypeScript

// -----------------------------------------------------------------------------------------------------
// @ AUTH UTILITIES
//
// Methods are derivations of the Auth0 Angular-JWT helper service methods
// https://github.com/auth0/angular2-jwt
// -----------------------------------------------------------------------------------------------------
export class AuthUtils
{
/**
* Constructor
*/
constructor()
{
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Is token expired?
*
* @param token
* @param offsetSeconds
*/
static isTokenExpired(token: string, offsetSeconds?: number): boolean
{
// Return if there is no token
if ( !token || token === '' )
{
return true;
}
// Get the expiration date
const date = this._getTokenExpirationDate(token);
offsetSeconds = offsetSeconds || 0;
if ( date === null )
{
return true;
}
// Check if the token is expired
return !(date.valueOf() > new Date().valueOf() + offsetSeconds * 1000);
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Base64 decoder
* Credits: https://github.com/atk
*
* @param str
* @private
*/
private static _b64decode(str: string): string
{
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
let output = '';
str = String(str).replace(/=+$/, '');
if ( str.length % 4 === 1 )
{
throw new Error(
'\'atob\' failed: The string to be decoded is not correctly encoded.'
);
}
/* eslint-disable */
for (
// initialize result and counters
let bc = 0, bs: any, buffer: any, idx = 0;
// get next character
(buffer = str.charAt(idx++));
// character found in table? initialize bit storage and add its ascii value;
~buffer &&
(
(bs = bc % 4 ? bs * 64 + buffer : buffer),
// and if not first of each 4 characters,
// convert the first 8 bits to one ascii character
bc++ % 4
)
? (output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6))))
: 0
)
{
// try to find character in table (0-63, not found => -1)
buffer = chars.indexOf(buffer);
}
/* eslint-enable */
return output;
}
/**
* Base64 unicode decoder
*
* @param str
* @private
*/
private static _b64DecodeUnicode(str: any): string
{
return decodeURIComponent(
Array.prototype.map
.call(this._b64decode(str), (c: any) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
.join('')
);
}
/**
* URL Base 64 decoder
*
* @param str
* @private
*/
private static _urlBase64Decode(str: string): string
{
let output = str.replace(/-/g, '+').replace(/_/g, '/');
switch ( output.length % 4 )
{
case 0:
{
break;
}
case 2:
{
output += '==';
break;
}
case 3:
{
output += '=';
break;
}
default:
{
throw Error('Illegal base64url string!');
}
}
return this._b64DecodeUnicode(output);
}
/**
* Decode token
*
* @param token
* @private
*/
private static _decodeToken(token: string): any
{
// Return if there is no token
if ( !token )
{
return null;
}
// Split the token
const parts = token.split('.');
if ( parts.length !== 3 )
{
throw new Error('The inspected token doesn\'t appear to be a JWT. Check to make sure it has three parts and see https://jwt.io for more.');
}
// Decode the token using the Base64 decoder
const decoded = this._urlBase64Decode(parts[1]);
if ( !decoded )
{
throw new Error('Cannot decode the token.');
}
return JSON.parse(decoded);
}
/**
* Get token expiration date
*
* @param token
* @private
*/
private static _getTokenExpirationDate(token: string): Date | null
{
// Get the decoded token
const decodedToken = this._decodeToken(token);
// Return if the decodedToken doesn't have an 'exp' field
if ( !decodedToken.hasOwnProperty('exp') )
{
return null;
}
// Convert the expiration date
const date = new Date(0);
date.setUTCSeconds(decodedToken.exp);
return date;
}
}