UNPKG

@tryauth/tryauth-client-ts

Version:

TypeScript library for OAuth2 Authentication

708 lines (707 loc) 31.8 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import JwtDecode from 'jwt-decode'; export class TryAuthAuthorizationResponse { constructor() { this.AccessToken = null; this.IdToken = null; this.Email = null; this.ExpiresAt = null; this.Error = null; } } export class TryAuthAuthorizationCodeTokenResponse { constructor() { this.AccessToken = null; this.IdToken = null; this.RefreshToken = null; this.TokenType = null; this.ExpiresIn = null; this.Error = null; } } export class TryAuthAuthorizationCodeResponse { constructor() { this.Code = null; this.Scope = null; this.State = null; } } export class TryAuthPkceCode { constructor() { this.CodeVerifier = null; this.CodeChallenge = null; } } class TryAuthAuthorizationOptions { constructor() { this.ClientId = null; this.ClientSecret = null; this.IssuerEndpoint = null; this.RedirectUri = null; this.ResponseType = null; this.Scopes = null; this.CodeChallenge = null; this.IdToken = null; this.State = null; this.RefreshToken = null; this.ExternalIssuerEndpoint = null; this.ExternalClientId = null; this.RequirePkce = false; } } export class TryAuthError { constructor() { this.error = null; } } export default class TryAuth { constructor(localStorage = new LocalStorage()) { this.localStorage = localStorage; this.NONCE_KEY = 'tryauth_authorization_nonce_key'; this.REPONSE_URL_KEY = 'tryauth_response_url_key'; this.RESPONSE_TYPE_IDTOKEN_TOKEN = 'id_token token'; this.RESPONSE_TYPE_TOKEN_IDTOKEN = 'token id_token'; this.RESPONSE_TYPE_CODE = 'code'; this.GRANT_TYPE = 'grant_type'; this.AUTHORIZATION_CODE = 'authorization_code'; this.CLIENT_ID = 'client_id'; this.CLIENT_SECRET = 'client_secret'; this.REDIRECT_URI = 'redirect_uri'; this.ACCESS_TOKEN = 'access_token'; this.ID_TOKEN = 'id_token'; this.SCOPE = 'scope'; this.STATE = 'session_state'; this.CODE_VERIFIER = 'code_verifier'; this.REFRESH_TOKEN = 'refresh_token'; } Authorize(tryAuthAuthorizationOptions) { return __awaiter(this, void 0, void 0, function* () { if (tryAuthAuthorizationOptions.ResponseType === this.RESPONSE_TYPE_IDTOKEN_TOKEN || tryAuthAuthorizationOptions.ResponseType === this.RESPONSE_TYPE_TOKEN_IDTOKEN) { yield this.AuthorizeIdTokenToken(tryAuthAuthorizationOptions); } }); } GetRedirect(tryAuthAuthorizationOptions) { if (tryAuthAuthorizationOptions.ResponseType === this.RESPONSE_TYPE_IDTOKEN_TOKEN || tryAuthAuthorizationOptions.ResponseType === this.RESPONSE_TYPE_TOKEN_IDTOKEN) { this.GetRedirectAuthorizeIdTokenToken(tryAuthAuthorizationOptions); } } GetAuthorizationCode(tryAuthAuthorizationOptions) { return __awaiter(this, void 0, void 0, function* () { if (tryAuthAuthorizationOptions.ResponseType === this.RESPONSE_TYPE_CODE) { yield this.GetRedirectAuthorizeCode(tryAuthAuthorizationOptions); } }); } LogoutAuthorizationCode(tryAuthAuthorizationOptions) { return __awaiter(this, void 0, void 0, function* () { if (tryAuthAuthorizationOptions.ResponseType === this.RESPONSE_TYPE_CODE) { yield this.GetLogoutAuthorizationCode(tryAuthAuthorizationOptions); } }); } LogoutEndSessionAuthorizationCode(tryAuthAuthorizationOptions) { if (tryAuthAuthorizationOptions.ResponseType === this.RESPONSE_TYPE_CODE) { this.GetLogoutEndSessionAuthorizationCode(tryAuthAuthorizationOptions); } } CheckAuthorize() { return __awaiter(this, void 0, void 0, function* () { const tryAuthAuthorizationResponse = this.GetResponseData(); const jwtPayload = this.GetJwtPayload(tryAuthAuthorizationResponse.IdToken); const isNonceValid = yield this.ValidateNonce(jwtPayload.nonce); if (!isNonceValid) { const tryAuthError = new TryAuthError(); tryAuthError.error = 'invalid nonce'; tryAuthAuthorizationResponse.Error = tryAuthError; return tryAuthAuthorizationResponse; } tryAuthAuthorizationResponse.ExpiresAt = jwtPayload.exp * 1000; tryAuthAuthorizationResponse.Email = jwtPayload.email; yield this.localStorage.removeItem(this.NONCE_KEY); return tryAuthAuthorizationResponse; }); } CheckRedirect() { const tryAuthAuthorizationResponse = this.GetResponseData(); const jwtPayload = this.GetJwtPayload(tryAuthAuthorizationResponse.IdToken); tryAuthAuthorizationResponse.ExpiresAt = jwtPayload.exp * 1000; tryAuthAuthorizationResponse.Email = jwtPayload.email; this.localStorage.removeItemSync(this.NONCE_KEY); return tryAuthAuthorizationResponse; } GetSilentAuthorizationCodeToken(tryAuthAuthorizationOptions) { const tryAuthAuthorizationCodeResponse = this.GetAuthorizationCodeReponseData(); const response = this.PostAuthorizationCodeToken(tryAuthAuthorizationOptions, tryAuthAuthorizationCodeResponse); const tryAuthSerialize = new TryAuthSerialize(); const serialized = tryAuthSerialize.Deserialize(response); const tryAuthAuthorizationCodeTokenResponse = new TryAuthAuthorizationCodeTokenResponse(); if (serialized.access_token != null && serialized.access_token != undefined) { tryAuthAuthorizationCodeTokenResponse.AccessToken = serialized.access_token; tryAuthAuthorizationCodeTokenResponse.IdToken = serialized.id_token; if (serialized.refresh_token != null && serialized.refresh_token != undefined) tryAuthAuthorizationCodeTokenResponse.RefreshToken = serialized.refresh_token; tryAuthAuthorizationCodeTokenResponse.ExpiresIn = serialized.expires_in; tryAuthAuthorizationCodeTokenResponse.TokenType = serialized.token_type; } else { tryAuthAuthorizationCodeTokenResponse.Error = new TryAuthError(); tryAuthAuthorizationCodeTokenResponse.Error.error = serialized.error; } return tryAuthAuthorizationCodeTokenResponse; } GetAuthorizationCodeRefreshToken(tryAuthAuthorizationOptions) { const response = this.PostAuthorizationCodeRefreshToken(tryAuthAuthorizationOptions); const tryAuthSerialize = new TryAuthSerialize(); const serialized = tryAuthSerialize.Deserialize(response); const tryAuthAuthorizationCodeTokenResponse = new TryAuthAuthorizationCodeTokenResponse(); if (serialized.access_token != null && serialized.access_token != undefined) { tryAuthAuthorizationCodeTokenResponse.AccessToken = serialized.access_token; tryAuthAuthorizationCodeTokenResponse.IdToken = serialized.id_token; if (serialized.refresh_token != null && serialized.refresh_token != undefined) tryAuthAuthorizationCodeTokenResponse.RefreshToken = serialized.refresh_token; tryAuthAuthorizationCodeTokenResponse.ExpiresIn = serialized.expires_in; tryAuthAuthorizationCodeTokenResponse.TokenType = serialized.token_type; } else { tryAuthAuthorizationCodeTokenResponse.Error = new TryAuthError(); tryAuthAuthorizationCodeTokenResponse.Error.error = serialized.error; } return tryAuthAuthorizationCodeTokenResponse; } Redirect() { const urlToRedirect = this.GetResponseLocationUrlSync(); if (urlToRedirect != null && urlToRedirect.length > 0) { window.location.href = urlToRedirect; } } GetResponseData() { const map = this.GetAuthorizationKeyValue(); const access_token = map.get(this.ACCESS_TOKEN); const id_token = map.get(this.ID_TOKEN); const tryAuthAuthorizationResponse = new TryAuthAuthorizationResponse(); tryAuthAuthorizationResponse.AccessToken = access_token; tryAuthAuthorizationResponse.IdToken = id_token; return tryAuthAuthorizationResponse; } GetAuthorizationCodeReponseData() { const map = this.GetAuthorizationCodeKeyValue(); const code = map.get(this.RESPONSE_TYPE_CODE); const scope = map.get(decodeURIComponent(this.SCOPE)); const state = map.get(this.STATE); const tryAuthAuthorizationCodeResponse = new TryAuthAuthorizationCodeResponse(); tryAuthAuthorizationCodeResponse.Code = code; tryAuthAuthorizationCodeResponse.Scope = scope; tryAuthAuthorizationCodeResponse.State = state; return tryAuthAuthorizationCodeResponse; } GetJwtPayload(idToken) { return JwtDecode(idToken); } GetExpiresAt(expiresAtTick) { const tick = expiresAtTick * 1000; return new Date(tick); } ValidateNonce(nonce) { return __awaiter(this, void 0, void 0, function* () { const nonceStored = yield this.localStorage.getItem(this.NONCE_KEY); if (nonce === nonceStored) { return true; } return false; }); } GetAuthorizationKeyValue() { let hash = window.location.hash; if (hash.startsWith('#')) { } hash = hash.substring(1); const split = hash.split('&'); const map = new Map(); for (let i = 0; i < split.length; i++) { const keys = split[i]; const keyValue = keys.split('='); map.set(keyValue[0], keyValue[1]); } return map; } GetAuthorizationCodeKeyValue() { let hash = window.location.search; hash = hash.substring(1); const map = new Map(); const split = hash.split('&'); for (let i = 0; i < split.length; i++) { const keys = split[i]; const keyValue = keys.split('='); map.set(keyValue[0], keyValue[1]); } return map; } AuthorizeIdTokenToken(tryAuthAuthorizationOptions) { return __awaiter(this, void 0, void 0, function* () { const headers = this.SetDefaultHeaders(); const authorizeEndpoint = yield this.GetAuthorizeEndpoint(tryAuthAuthorizationOptions); return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.withCredentials = false; xhr.onload = () => __awaiter(this, void 0, void 0, function* () { window.location.href = xhr.responseURL; }); xhr.open('GET', authorizeEndpoint, true); for (let i = 0; i < headers.length; i++) { const header = headers[i]; xhr.setRequestHeader(header[0], this.EnsureASCII(header[1])); } xhr.send(null); }); }); } GetRedirectAuthorizeIdTokenToken(tryAuthAuthorizationOptions) { const headers = this.SetDefaultHeaders(); const authorizeEndpoint = this.GetAuthorizeEndpointSync(tryAuthAuthorizationOptions); const xhr = new XMLHttpRequest(); xhr.withCredentials = false; xhr.onload = () => { window.location.href = xhr.responseURL; }; xhr.open('GET', authorizeEndpoint, true); for (let i = 0; i < headers.length; i++) { const header = headers[i]; xhr.setRequestHeader(header[0], this.EnsureASCII(header[1])); } xhr.send(null); } GetRedirectAuthorizeCode(tryAuthAuthorizationOptions) { return __awaiter(this, void 0, void 0, function* () { const crypto = new Crypto(); const tryAuthPkceCode = yield crypto.GeneratePkceCodes(); if (tryAuthAuthorizationOptions.RequirePkce) { tryAuthAuthorizationOptions.CodeChallenge = tryAuthPkceCode.CodeChallenge; } yield this.SetCodeVerifier(tryAuthPkceCode.CodeVerifier); let authorizeEndpoint = this.GetAuthorizationCodeEndpoint(tryAuthAuthorizationOptions); yield this.SendRequest(authorizeEndpoint); }); } GetLogoutAuthorizationCode(tryAuthAuthorizationOptions) { return __awaiter(this, void 0, void 0, function* () { const crypto = new Crypto(); const tryAuthPkceCode = yield crypto.GeneratePkceCodes(); tryAuthAuthorizationOptions.CodeChallenge = tryAuthPkceCode.CodeChallenge; yield this.SetCodeVerifier(tryAuthPkceCode.CodeVerifier); let authorizeEndpoint = this.GetLogoutEndpoint(tryAuthAuthorizationOptions); const xhr = new XMLHttpRequest(); xhr.withCredentials = false; xhr.onload = () => { window.location.href = xhr.responseURL; }; xhr.open('GET', authorizeEndpoint, true); const headers = this.SetDefaultHeaders(); for (let i = 0; i < headers.length; i++) { const header = headers[i]; xhr.setRequestHeader(header[0], this.EnsureASCII(header[1])); } xhr.send(null); }); } GetLogoutEndSessionAuthorizationCode(tryAuthAuthorizationOptions) { let authorizeEndpoint = this.GetLogoutEndSessionEndpoint(tryAuthAuthorizationOptions); const xhr = new XMLHttpRequest(); xhr.withCredentials = false; xhr.onload = () => { window.location.href = xhr.responseURL; }; xhr.open('GET', authorizeEndpoint, true); const headers = this.SetDefaultHeaders(); for (let i = 0; i < headers.length; i++) { const header = headers[i]; xhr.setRequestHeader(header[0], this.EnsureASCII(header[1])); } xhr.send(null); } PostAuthorizationCodeToken(tryAuthAuthorizationOptions, tryAuthAuthorizationCodeResponse) { const headers = this.SetDefaultHeaders(); const codeVerifier = this.GetCodeVerifier(); const parameters = new URLSearchParams(); parameters.append(this.GRANT_TYPE, this.AUTHORIZATION_CODE); parameters.append(this.CLIENT_ID, tryAuthAuthorizationOptions.ClientId); parameters.append(this.CLIENT_SECRET, tryAuthAuthorizationOptions.ClientSecret); parameters.append(this.RESPONSE_TYPE_CODE, tryAuthAuthorizationCodeResponse.Code); parameters.append(this.CODE_VERIFIER, codeVerifier); if (tryAuthAuthorizationOptions.RedirectUri == null || tryAuthAuthorizationOptions.RedirectUri == undefined || tryAuthAuthorizationOptions.RedirectUri === '') parameters.append(this.REDIRECT_URI, window.location.origin); else parameters.append(this.REDIRECT_URI, tryAuthAuthorizationOptions.RedirectUri); const tokenEndpoint = this.GetConnectTokenEndpoint(tryAuthAuthorizationOptions.IssuerEndpoint); const xhr = new XMLHttpRequest(); xhr.withCredentials = false; xhr.open('POST', tokenEndpoint, false); for (let i = 0; i < headers.length; i++) { const header = headers[i]; xhr.setRequestHeader(header[0], this.EnsureASCII(header[1])); } xhr.send(parameters); return xhr.responseText; } PostAuthorizationCodeRefreshToken(tryAuthAuthorizationOptions) { const headers = this.SetDefaultHeaders(); const parameters = new URLSearchParams(); parameters.append(this.GRANT_TYPE, this.REFRESH_TOKEN); parameters.append(this.CLIENT_ID, tryAuthAuthorizationOptions.ClientId); parameters.append(this.CLIENT_SECRET, tryAuthAuthorizationOptions.ClientSecret); parameters.append(this.REFRESH_TOKEN, tryAuthAuthorizationOptions.RefreshToken); const tokenEndpoint = this.GetConnectTokenEndpoint(tryAuthAuthorizationOptions.IssuerEndpoint); const xhr = new XMLHttpRequest(); xhr.withCredentials = false; xhr.open('POST', tokenEndpoint, false); for (let i = 0; i < headers.length; i++) { const header = headers[i]; xhr.setRequestHeader(header[0], this.EnsureASCII(header[1])); } xhr.send(parameters); return xhr.responseText; } SetDefaultHeaders() { const headers = []; headers.push(['Content-Type', 'application/x-www-form-urlencoded']); return headers; } SetNonceLocalStorage() { return __awaiter(this, void 0, void 0, function* () { const crypto = new Crypto(30); const nonce = crypto.Create(); yield this.localStorage.setItem(this.NONCE_KEY, nonce); return nonce; }); } SetNonceLocalStorageSync() { const crypto = new Crypto(30); const nonce = crypto.Create(); this.localStorage.setItemSync(this.NONCE_KEY, nonce); return nonce; } SetResponseLocationUrl(responseUrl) { return __awaiter(this, void 0, void 0, function* () { yield this.localStorage.setItem(this.REPONSE_URL_KEY, responseUrl); }); } SetCodeVerifier(code) { this.localStorage.setItemSync(this.CODE_VERIFIER, code); } GetCodeVerifier() { return this.localStorage.getItemSync(this.CODE_VERIFIER); } GetResponseLocationUrl() { return __awaiter(this, void 0, void 0, function* () { return yield this.localStorage.getItem(this.REPONSE_URL_KEY); }); } GetResponseLocationUrlSync() { return this.localStorage.getItemSync(this.REPONSE_URL_KEY); } GetHeaderValue(headers, name) { for (let i = 0; i < headers.length; i++) { const header = headers[i]; if (header[0].toLowerCase() === name.toLowerCase()) return (header[1]); } return null; } GetConnectAuthorizeEndpoint(issuerEndpoint) { return issuerEndpoint + '/connect/authorize'; } GetConnectTokenEndpoint(issuerEndpoint) { return issuerEndpoint + '/connect/token'; } LogoutEndpoint(issuerEndpoint) { return issuerEndpoint + '/Identity/Logout'; } EndSessionEndpoint(issuerEndpoint) { return issuerEndpoint + '/connect/endsession'; } GetAuthorizeEndpoint(tryAuthAuthorizationOptions) { return __awaiter(this, void 0, void 0, function* () { const nonce = yield this.SetNonceLocalStorage(); let authorizeEndpoint = this.GetConnectAuthorizeEndpoint(tryAuthAuthorizationOptions.IssuerEndpoint); authorizeEndpoint = authorizeEndpoint + '?client_id=' + tryAuthAuthorizationOptions.ClientId; if (tryAuthAuthorizationOptions.RedirectUri == null) { authorizeEndpoint = authorizeEndpoint + '&redirect_uri=' + encodeURIComponent(window.location.origin); } else { authorizeEndpoint = authorizeEndpoint + '&redirect_uri=' + encodeURIComponent(tryAuthAuthorizationOptions.RedirectUri); } const ensureExternalIssuerEndpoint = this.EnsureExternalIssuerEndpoint(tryAuthAuthorizationOptions.ExternalIssuerEndpoint); if (ensureExternalIssuerEndpoint != null) { authorizeEndpoint = authorizeEndpoint + '&external_uri=' + encodeURIComponent(ensureExternalIssuerEndpoint); } if (tryAuthAuthorizationOptions.ExternalClientId != null) { authorizeEndpoint = authorizeEndpoint + '&external_client_id=' + tryAuthAuthorizationOptions.ExternalClientId; } authorizeEndpoint = authorizeEndpoint + '&response_type=' + tryAuthAuthorizationOptions.ResponseType; authorizeEndpoint = authorizeEndpoint + '&scope=' + tryAuthAuthorizationOptions.Scopes; authorizeEndpoint = authorizeEndpoint + '&nonce=' + nonce; return authorizeEndpoint; }); } GetAuthorizeEndpointSync(tryAuthAuthorizationOptions) { const nonce = this.SetNonceLocalStorageSync(); let authorizeEndpoint = this.GetConnectAuthorizeEndpoint(tryAuthAuthorizationOptions.IssuerEndpoint); authorizeEndpoint = authorizeEndpoint + '?client_id=' + tryAuthAuthorizationOptions.ClientId; if (tryAuthAuthorizationOptions.RedirectUri == null) { authorizeEndpoint = authorizeEndpoint + '&redirect_uri=' + encodeURIComponent(window.location.origin); } else { authorizeEndpoint = authorizeEndpoint + '&redirect_uri=' + encodeURIComponent(tryAuthAuthorizationOptions.RedirectUri); } const ensureExternalIssuerEndpoint = this.EnsureExternalIssuerEndpoint(tryAuthAuthorizationOptions.ExternalIssuerEndpoint); if (ensureExternalIssuerEndpoint != null) { authorizeEndpoint = authorizeEndpoint + '&external_uri=' + encodeURIComponent(ensureExternalIssuerEndpoint); } if (tryAuthAuthorizationOptions.ExternalClientId != null) { authorizeEndpoint = authorizeEndpoint + '&external_client_id=' + tryAuthAuthorizationOptions.ExternalClientId; } authorizeEndpoint = authorizeEndpoint + '&response_type=' + tryAuthAuthorizationOptions.ResponseType; authorizeEndpoint = authorizeEndpoint + '&scope=' + tryAuthAuthorizationOptions.Scopes; authorizeEndpoint = authorizeEndpoint + '&nonce=' + nonce; return authorizeEndpoint; } GetAuthorizationCodeEndpoint(tryAuthAuthorizationOptions) { let authorizeEndpoint = this.GetConnectAuthorizeEndpoint(tryAuthAuthorizationOptions.IssuerEndpoint); authorizeEndpoint = authorizeEndpoint + '?client_id=' + tryAuthAuthorizationOptions.ClientId; if (tryAuthAuthorizationOptions.RedirectUri == null) { authorizeEndpoint = authorizeEndpoint + '&redirect_uri=' + encodeURIComponent(window.location.origin); } else { authorizeEndpoint = authorizeEndpoint + '&redirect_uri=' + encodeURIComponent(tryAuthAuthorizationOptions.RedirectUri); } authorizeEndpoint = authorizeEndpoint + '&response_type=' + tryAuthAuthorizationOptions.ResponseType; authorizeEndpoint = authorizeEndpoint + '&scope=' + tryAuthAuthorizationOptions.Scopes; if (tryAuthAuthorizationOptions.CodeChallenge != null) { authorizeEndpoint = authorizeEndpoint + '&code_challenge=' + tryAuthAuthorizationOptions.CodeChallenge; authorizeEndpoint = authorizeEndpoint + '&code_challenge_method=S256'; } return authorizeEndpoint; } GetLogoutEndpoint(tryAuthAuthorizationOptions) { let authorizeEndpoint = this.LogoutEndpoint(tryAuthAuthorizationOptions.IssuerEndpoint); authorizeEndpoint = authorizeEndpoint + '?returnUrl=' + encodeURIComponent('/connect/authorize'); authorizeEndpoint = authorizeEndpoint + '&client_id=' + tryAuthAuthorizationOptions.ClientId; if (tryAuthAuthorizationOptions.RedirectUri == null) { authorizeEndpoint = authorizeEndpoint + '&redirect_uri=' + encodeURIComponent(window.location.origin); } else { authorizeEndpoint = authorizeEndpoint + '&redirect_uri=' + encodeURIComponent(tryAuthAuthorizationOptions.RedirectUri); } authorizeEndpoint = authorizeEndpoint + '&response_type=' + tryAuthAuthorizationOptions.ResponseType; authorizeEndpoint = authorizeEndpoint + '&scope=' + tryAuthAuthorizationOptions.Scopes; if (tryAuthAuthorizationOptions.CodeChallenge != null) { authorizeEndpoint = authorizeEndpoint + '&code_challenge=' + tryAuthAuthorizationOptions.CodeChallenge; authorizeEndpoint = authorizeEndpoint + '&code_challenge_method=S256'; } return authorizeEndpoint; } GetLogoutEndSessionEndpoint(tryAuthAuthorizationOptions) { let authorizeEndpoint = this.EndSessionEndpoint(tryAuthAuthorizationOptions.IssuerEndpoint); authorizeEndpoint = authorizeEndpoint + '?id_token_hint=' + tryAuthAuthorizationOptions.IdToken; authorizeEndpoint = authorizeEndpoint + '&state=' + tryAuthAuthorizationOptions.State; authorizeEndpoint = authorizeEndpoint + '&post_logout_redirect_uri=' + tryAuthAuthorizationOptions.RedirectUri; return authorizeEndpoint; } SendRequest(url) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.withCredentials = false; xhr.onload = () => { if (xhr.status >= 200 && xhr.status < 300) { window.location.href = xhr.responseURL; resolve(); } else { reject(new Error(`Error on request: ${xhr.status} - ${xhr.statusText}`)); } }; xhr.onerror = () => reject(new Error("An error occurred while trying to process your request.")); xhr.ontimeout = () => reject(new Error("The request timed out. Please try again later.")); xhr.open("GET", url, true); const headers = this.SetDefaultHeaders(); for (let i = 0; i < headers.length; i++) { const header = headers[i]; xhr.setRequestHeader(header[0], this.EnsureASCII(header[1])); } xhr.send(null); }); } EnsureExternalIssuerEndpoint(externalIssuerEndpoint) { if (externalIssuerEndpoint == null) return ''; if (externalIssuerEndpoint.endsWith('/')) externalIssuerEndpoint = externalIssuerEndpoint + 'authorize'; else externalIssuerEndpoint = externalIssuerEndpoint + '/authorize'; return externalIssuerEndpoint; } EnsureASCII(data) { if (this.HasUnicode(data)) return (this.ConvertToASCII(data)); return (data); } HasUnicode(data) { for (let i = 0; i < data.length; i++) { const char = data[i]; const index = char.charCodeAt(0); if (index > 127) return (true); } return (false); } ConvertToASCII(data) { let encoded = ''; for (let i = 0; i < data.length; i++) { const char = data[i]; const index = char.charCodeAt(0); encoded += '\\u' + index.toString(16).toUpperCase(); } return (encoded); } } class Crypto { constructor(size) { this._size = null; this._charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; this._code_verifier_length = 96; this._pkce_charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~'; this.base64urlEncode = (value) => { let base64 = btoa(value); base64 = base64.replace(/\+/g, '-'); base64 = base64.replace(/\//g, '_'); base64 = base64.replace(/=/g, ''); return base64; }; this.Buffer = null; this._size = size; } Create() { const buffer = new Uint8Array(this._size); for (let i = 0; i < this._size; i += 1) { buffer[i] = (Math.random() * this._charset.length) | 0; } return this.BufferToString(buffer); } GeneratePkceCodes() { return __awaiter(this, void 0, void 0, function* () { const uint = new Uint32Array(this._code_verifier_length); crypto.getRandomValues(uint); const codeVerifier = this.base64urlEncode(Array.from(uint).map((num) => this._pkce_charset[num % this._pkce_charset.length]).join('')); const buffer = yield crypto.subtle.digest('SHA-256', (new TextEncoder()).encode(codeVerifier)); const hash = new Uint8Array(buffer); let binary = ''; const hashLength = hash.byteLength; for (let i = 0; i < hashLength; i++) { binary += String.fromCharCode(hash[i]); } const codeChallenge = this.base64urlEncode(binary); const tryAuthPkceCode = new TryAuthPkceCode(); tryAuthPkceCode.CodeVerifier = codeVerifier; tryAuthPkceCode.CodeChallenge = codeChallenge; return tryAuthPkceCode; }); } BufferToString(buffer) { const state = []; for (let i = 0; i < buffer.byteLength; i += 1) { const index = buffer[i] % this._charset.length; state.push(this._charset[index]); } return state.join(''); } } class LocalStorageBackend { } class LocalStorage extends LocalStorageBackend { constructor(storage) { super(); this._storage = storage || window.localStorage; } getItem(name) { return new Promise((resolve, reject) => { const value = this._storage.getItem(name); if (value) { resolve(value); } else { resolve(null); } }); } getItemSync(name) { const value = this._storage.getItem(name); if (value) { return value; } else { return null; } } removeItem(name) { return new Promise((resolve, reject) => { this._storage.removeItem(name); resolve(); }); } removeItemSync(name) { this._storage.removeItem(name); } clear() { return new Promise((resolve, reject) => { this._storage.clear(); resolve(); }); } setItem(name, value) { return new Promise((resolve, reject) => { this._storage.setItem(name, value); resolve(); }); } setItemSync(name, value) { this._storage.setItem(name, value); } } class TryAuthSerialize { constructor() { this.JSON_START = '{'; this.JSON_END = '}'; this.JSON_ARRAY_START = '['; this.JSON_ARRAY_END = ']'; } IsJson(data) { return ((this.IsJsonInstance(data)) || (this.IsJsonArray(data))); } IsJsonInstance(data) { if (data === null) return (false); if (data.length < 2) return (false); return ((data.substr != null) && (data.substr(0, 1) == this.JSON_START) && (data.substr(data.length - 1, 1) == this.JSON_END)); } IsJsonArray(data) { if (data === null) return (false); if (data.length < 2) return (false); return ((data.substr != null) && (data.substr(0, 1) == this.JSON_ARRAY_START) && (data.substr(data.length - 1, 1) == this.JSON_ARRAY_END)); } Deserialize(data) { if (!this.IsJson(data)) return (data); return (JSON.parse(data)); } }