From bb16541f847d0e8c6b7ba276519467f61f3649c1 Mon Sep 17 00:00:00 2001 From: nikita_kysil Date: Tue, 14 Mar 2023 15:19:03 -0400 Subject: [PATCH] add fix cookies for oidc --- static/web/styles/web-element.css | 4 ++ web/api/federated_login.go | 2 + web_apps_src/identifo.js/dist/identifo.d.ts | 18 ++++++- web_apps_src/identifo.js/dist/identifo.js | 22 ++++++++ web_apps_src/identifo.js/dist/identifo.js.map | 2 +- web_apps_src/identifo.js/dist/identifo.mjs | 22 ++++++++ .../identifo.js/dist/identifo.mjs.map | 2 +- web_apps_src/identifo.js/package.json | 2 +- web_apps_src/identifo.js/src/api/api.ts | 7 +++ web_apps_src/identifo.js/src/api/model.ts | 2 + web_apps_src/identifo.js/src/cdk/cdk.ts | 23 ++++++++ web_apps_src/identifo.js/src/cdk/model.ts | 10 +++- web_apps_src/web-element/package-lock.json | 2 +- web_apps_src/web-element/src/components.d.ts | 13 +++++ .../src/components/forms/login_oidc.tsx | 54 +++++++++++++++++++ .../identifo-form/identifo-form.tsx | 2 + 16 files changed, 180 insertions(+), 7 deletions(-) create mode 100644 web_apps_src/web-element/src/components/forms/login_oidc.tsx diff --git a/static/web/styles/web-element.css b/static/web/styles/web-element.css index f2783009..3187654d 100644 --- a/static/web/styles/web-element.css +++ b/static/web/styles/web-element.css @@ -583,3 +583,7 @@ margin-bottom: 48px; } } + +.oidc-login__subtitle { + margin-top: 12px; +} diff --git a/web/api/federated_login.go b/web/api/federated_login.go index e0466260..d1e75c4e 100644 --- a/web/api/federated_login.go +++ b/web/api/federated_login.go @@ -440,6 +440,8 @@ func sessionKey(appId, provider string) string { // StoreInSession stores a specified key/value pair in the session. func storeInSession(sessionName, key string, value string, req *http.Request, res http.ResponseWriter) error { session, _ := Store.New(req, sessionName) + session.Options.SameSite = http.SameSiteNoneMode + session.Options.Secure = true if err := updateSessionValue(session, key, value); err != nil { return err diff --git a/web_apps_src/identifo.js/dist/identifo.d.ts b/web_apps_src/identifo.js/dist/identifo.d.ts index 33a08f94..85735f65 100644 --- a/web_apps_src/identifo.js/dist/identifo.d.ts +++ b/web_apps_src/identifo.js/dist/identifo.d.ts @@ -99,6 +99,7 @@ declare enum TFAStatus { interface ServerSettingsLoginTypes { email: boolean; federated: boolean; + federated_oidc: boolean; phone: boolean; username: boolean; } @@ -159,6 +160,7 @@ interface AppSettingsResponse { tfaStatus: TFAStatus; federatedProviders: FederatedLoginProvider[]; loginWith: ServerSettingsLoginTypes; + federatedOIDCInitURL: string; } interface User { id: string; @@ -231,6 +233,11 @@ declare class API { verifyTFA(code: string, scopes: string[]): Promise; resendTFA(): Promise; logout(): Promise; + oidcVerify(data: { + state: string; + code: string; + scopes: string[]; + }): Promise; invite(email: string, role: string, callbackUrl: string): Promise; storeToken(response: T): T; } @@ -302,6 +309,7 @@ declare enum Routes { 'PASSWORD_FORGOT_TFA_SELECT' = "password/forgot/tfa/select", 'CALLBACK' = "callback", 'LOGIN_PHONE' = "login_phone", + 'LOGIN_OIDC' = "login_oidc", 'LOGIN_PHONE_VERIFY' = "login_phone_verify", 'ERROR' = "error", 'PASSWORD_FORGOT_SUCCESS' = "password/forgot/success", @@ -331,6 +339,11 @@ interface StateLogin extends State, StateWithError { socialLogin: (provider: FederatedLoginProvider) => Promise; passwordForgot: () => Promise; } +interface StateLoginOidc extends State, StateWithError { + route: Routes.LOGIN_OIDC; + oidcLink: string; + verify: (state?: string, code?: string) => Promise; +} interface StateLoginPhone extends State, StateWithError { route: Routes.LOGIN_PHONE; registrationForbidden: boolean; @@ -450,7 +463,7 @@ declare const typeToPasswordForgotTFAVerifyRoute: { email: Routes; sms: Routes; }; -declare type States = State | StateTFASetupApp | StateTFASetupEmail | StateTFASetupSMS | StatePasswordReset | StatePasswordForgot | StatePasswordForgotSuccess | StateLoading | StateCallback | StateLogin | StateRegister | StateError; +declare type States = State | StateTFASetupApp | StateTFASetupEmail | StateTFASetupSMS | StatePasswordReset | StatePasswordForgot | StatePasswordForgotSuccess | StateLoading | StateCallback | StateLogin | StateRegister | StateError | StateLoginOidc; declare class CDK { auth: IdentifoAuth; @@ -465,6 +478,7 @@ declare class CDK { login(): void; loginWithPhone(): void; loginWithPhoneVerify(phone: string, remember?: boolean): void; + loginWithOIDC(): void; loginWithPassword(): void; register(): void; forgotPassword(): void; @@ -487,4 +501,4 @@ declare class CDK { private getLoginTypes; } -export { APIErrorCodes, ApiError, ApiRequestError, AppSettingsResponse, CDK, ClientToken, CookieStorage as CookieStorageManager, EnableTFAResponse, FederatedLoginProvider, IdentifoAuth, IdentifoConfig, InviteResponse, JWTPayload, LocalStorage as LocalStorageManager, LoginResponse, LoginTypes, Routes, ServerSettingsLoginTypes, SessionStorage as SessionStorageManager, State, StateCallback, StateError, StateLoading, StateLogin, StateLoginPhone, StateLoginPhoneVerify, StateLogout, StatePasswordForgot, StatePasswordForgotSuccess, StatePasswordForgotTFASelect, StatePasswordForgotTFAVerify, StatePasswordReset, StateRegister, StateTFASetupApp, StateTFASetupEmail, StateTFASetupSMS, StateTFASetupSelect, StateTFAVerifyApp, StateTFAVerifyEmailSms, StateTFAVerifySelect, StateWithError, States, SuccessResponse, TFALoginVerifyRoutes, TFARequiredRespopnse, TFAResetVerifyRoutes, TFASetupRoutes, TFAStatus, TFAType, TokenManager, TokenResponse, TokenType, UpdateUser, UrlBuilderInit, UrlFlows, User, typeToPasswordForgotTFAVerifyRoute, typeToSetupRoute, typeToTFAVerifyRoute }; +export { APIErrorCodes, ApiError, ApiRequestError, AppSettingsResponse, CDK, ClientToken, CookieStorage as CookieStorageManager, EnableTFAResponse, FederatedLoginProvider, IdentifoAuth, IdentifoConfig, InviteResponse, JWTPayload, LocalStorage as LocalStorageManager, LoginResponse, LoginTypes, Routes, ServerSettingsLoginTypes, SessionStorage as SessionStorageManager, State, StateCallback, StateError, StateLoading, StateLogin, StateLoginOidc, StateLoginPhone, StateLoginPhoneVerify, StateLogout, StatePasswordForgot, StatePasswordForgotSuccess, StatePasswordForgotTFASelect, StatePasswordForgotTFAVerify, StatePasswordReset, StateRegister, StateTFASetupApp, StateTFASetupEmail, StateTFASetupSMS, StateTFASetupSelect, StateTFAVerifyApp, StateTFAVerifyEmailSms, StateTFAVerifySelect, StateWithError, States, SuccessResponse, TFALoginVerifyRoutes, TFARequiredRespopnse, TFAResetVerifyRoutes, TFASetupRoutes, TFAStatus, TFAType, TokenManager, TokenResponse, TokenType, UpdateUser, UrlBuilderInit, UrlFlows, User, typeToPasswordForgotTFAVerifyRoute, typeToSetupRoute, typeToTFAVerifyRoute }; diff --git a/web_apps_src/identifo.js/dist/identifo.js b/web_apps_src/identifo.js/dist/identifo.js index ff3e7e7f..c9c85a75 100644 --- a/web_apps_src/identifo.js/dist/identifo.js +++ b/web_apps_src/identifo.js/dist/identifo.js @@ -312,6 +312,12 @@ class API { }); }); } + oidcVerify(data) { + return __async$3(this, null, function* () { + const url = `/auth/federated/oidc/complete?appId=${this.appId}&state=${data.state}&code=${data.code}`; + return this.post(url, { scopes: data.scopes }, { credentials: "include" }).then((r) => this.storeToken(r)); + }); + } invite(email, role, callbackUrl) { return __async$3(this, null, function* () { var _a, _b; @@ -703,6 +709,7 @@ exports.Routes = void 0; Routes2["PASSWORD_FORGOT_TFA_SELECT"] = "password/forgot/tfa/select"; Routes2["CALLBACK"] = "callback"; Routes2["LOGIN_PHONE"] = "login_phone"; + Routes2["LOGIN_OIDC"] = "login_oidc"; Routes2["LOGIN_PHONE_VERIFY"] = "login_phone_verify"; Routes2["ERROR"] = "error"; Routes2["PASSWORD_FORGOT_SUCCESS"] = "password/forgot/success"; @@ -859,6 +866,8 @@ class CDK { return this.loginWithPhone(); case (!this.auth.config.loginWith && this.settings.loginWith["email"] || this.auth.config.loginWith === "email" && this.settings.loginWith["email"]): return this.loginWithPassword(); + case (!this.auth.config.loginWith && this.settings.loginWith["federated_oidc"] || this.auth.config.loginWith === "federated_oidc" && this.settings.loginWith["federated_oidc"]): + return this.loginWithOIDC(); default: throw "Unsupported login way"; } @@ -909,6 +918,19 @@ class CDK { }) }); } + loginWithOIDC() { + this.state.next({ + route: exports.Routes.LOGIN_OIDC, + oidcLink: this.settings.federatedOIDCInitURL, + error: this.lastError, + verify: (state, code) => __async(this, null, function* () { + if (!state || !code) { + return; + } + this.auth.api.oidcVerify({ state, code, scopes: [...Array.from(this.scopes)] }).then(this.afterLoginRedirect).catch(this.loginCatchRedirect).catch((e) => this.processError(e)); + }) + }); + } loginWithPassword() { var _a, _b; this.state.next({ diff --git a/web_apps_src/identifo.js/dist/identifo.js.map b/web_apps_src/identifo.js/dist/identifo.js.map index a5700ce6..4f9644ae 100644 --- a/web_apps_src/identifo.js/dist/identifo.js.map +++ b/web_apps_src/identifo.js/dist/identifo.js.map @@ -1 +1 @@ -{"version":3,"file":"identifo.js","sources":["../src/api/model.ts","../src/api/api.ts","../src/constants.ts","../src/store-manager/cookie-storage.ts","../src/store-manager/storage-manager.ts","../src/store-manager/local-storage.ts","../src/store-manager/session-storage.ts","../src/tokenService.ts","../src/UrlBuilder.ts","../src/IdentifoAuth.ts","../src/cdk/model.ts","../src/cdk/cdk.ts"],"sourcesContent":["/* eslint-disable camelcase */\nexport enum APIErrorCodes {\n PleaseEnableTFA = 'error.api.request.2fa.please_enable',\n InvalidCallbackURL = 'error.api.request.callbackurl.invalid',\n NetworkError = 'error.network',\n}\n\nexport enum TFAType {\n TFATypeApp = 'app',\n TFATypeSMS = 'sms',\n TFATypeEmail = 'email',\n}\n\nexport enum TFAStatus {\n DISABLED = 'disabled',\n OPTIONAL = 'optional',\n MANDATORY = 'mandatory',\n}\n\nexport interface ServerSettingsLoginTypes {\n email: boolean;\n federated: boolean;\n phone: boolean;\n username: boolean;\n}\n\nexport type FederatedLoginProvider = 'apple' | 'google' | 'facebook';\nexport interface ApiRequestError {\n error: {\n detailed_message?: string;\n id?: APIErrorCodes;\n message?: string;\n status?: number;\n };\n}\nexport class ApiError extends Error {\n detailedMessage?: string;\n\n id?: APIErrorCodes;\n\n status?: number;\n\n constructor(error?: ApiRequestError['error']) {\n super(error?.message || 'Unknown API error');\n this.detailedMessage = error?.detailed_message;\n this.id = error?.id;\n this.status = error?.status;\n }\n}\nexport interface LoginResponse {\n access_token?: string;\n refresh_token?: string;\n require_2fa: boolean;\n enabled_2fa: boolean;\n user: {\n active: boolean;\n email?: string;\n id: string;\n latest_login_time: number;\n num_of_logins: number;\n username?: string;\n tfa_info: { hotp_expired_at: string };\n phone?: string;\n };\n scopes?: string[];\n callbackUrl?: string;\n}\nexport interface EnableTFAResponse {\n provisioning_uri?: string;\n provisioning_qr?: string;\n access_token?: string;\n}\nexport interface TokenResponse {\n access_token?: string;\n refresh_token?: string;\n}\nexport interface AppSettingsResponse {\n anonymousResitrationAllowed: boolean;\n active: boolean;\n description: string;\n id: string;\n newUserDefaultRole: string;\n offline: boolean;\n registrationForbidden: boolean;\n tfaType: TFAType[] | TFAType;\n tfaResendTimeout: number;\n tfaStatus: TFAStatus;\n federatedProviders: FederatedLoginProvider[];\n loginWith: ServerSettingsLoginTypes;\n}\n\nexport interface User {\n id: string;\n username: string;\n email: string;\n phone: string;\n active: boolean;\n tfa_info: {\n is_enabled: boolean;\n };\n num_of_logins: number;\n latest_login_time: number;\n access_role: string;\n anonymous: boolean;\n federated_ids: string[];\n}\nexport interface UpdateUser {\n new_email?: string;\n new_phone?: string;\n}\nexport interface SuccessResponse {\n result: 'ok';\n message?: string;\n}\n\nexport interface InviteResponse {\n result: 'ok';\n link: string;\n}\n\nexport interface TFARequiredRespopnse {\n result: 'tfa-required';\n}\n","import { InviteResponse } from '..';\nimport TokenService from '../tokenService';\nimport { IdentifoConfig } from '../types/types';\nimport {\n AppSettingsResponse,\n EnableTFAResponse,\n LoginResponse,\n SuccessResponse,\n UpdateUser,\n User,\n ApiRequestError,\n ApiError,\n APIErrorCodes,\n FederatedLoginProvider,\n TokenResponse,\n TFARequiredRespopnse,\n} from './model';\n\nconst APP_ID_HEADER_KEY = 'X-Identifo-Clientid';\nconst AUTHORIZATION_HEADER_KEY = 'Authorization';\n\nexport class API {\n baseUrl: string;\n\n appId: string;\n\n defaultHeaders = {\n [APP_ID_HEADER_KEY]: '',\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n };\n\n catchNetworkErrorHandler = (e: TypeError): never => {\n if (\n e.message === 'Network Error' ||\n e.message === 'Failed to fetch' ||\n e.message === 'Preflight response is not successful' ||\n e.message.indexOf('is not allowed by Access-Control-Allow-Origin') > -1\n ) {\n // eslint-disable-next-line no-console\n console.error(e.message);\n throw new ApiError({\n id: APIErrorCodes.NetworkError,\n status: 0,\n message: 'Configuration error',\n detailed_message:\n 'Please check Identifo URL and add \"' +\n `${window.location.protocol}//${window.location.host}\" ` +\n 'to \"REDIRECT URLS\" in Identifo app settings.',\n });\n }\n throw e;\n };\n\n checkStatusCodeAndGetJSON = async (r: Response): Promise => {\n if (!r.ok) {\n const error = (await r.json()) as ApiRequestError;\n throw new ApiError(error?.error);\n }\n return r.json();\n };\n\n constructor(private config: IdentifoConfig, private tokenService: TokenService) {\n // remove trailing slash if exist\n this.baseUrl = config.url.replace(/\\/$/, '');\n this.defaultHeaders[APP_ID_HEADER_KEY] = config.appId;\n this.appId = config.appId;\n }\n\n get(path: string, options?: RequestInit): Promise {\n return this.send(path, { method: 'GET', ...options });\n }\n\n put(path: string, data: unknown, options?: RequestInit): Promise {\n return this.send(path, { method: 'PUT', body: JSON.stringify(data), ...options });\n }\n\n post(path: string, data: unknown, options?: RequestInit): Promise {\n return this.send(path, { method: 'POST', body: JSON.stringify(data), ...options });\n }\n\n send(path: string, options?: RequestInit): Promise {\n const init = { ...options };\n init.credentials = 'include';\n init.headers = {\n ...init.headers,\n ...this.defaultHeaders,\n };\n return fetch(`${this.baseUrl}${path}`, init)\n .catch(this.catchNetworkErrorHandler)\n .then(this.checkStatusCodeAndGetJSON)\n .then((value) => value as T);\n }\n\n async getUser(): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.get('/me', {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n });\n }\n\n async renewToken(): Promise {\n if (!this.tokenService.getToken('refresh')?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/auth/token',\n { scopes: this.config.scopes },\n {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken('refresh')?.token}`,\n },\n },\n ).then((r) => this.storeToken(r));\n }\n\n async updateUser(user: UpdateUser): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.put('/me', user, {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken('access')?.token}`,\n },\n });\n }\n\n async login(email: string, password: string, deviceToken: string, scopes: string[]): Promise {\n const data = {\n email,\n password,\n device_token: deviceToken,\n scopes,\n };\n\n return this.post('/auth/login', data).then((r) => this.storeToken(r));\n }\n\n async requestPhoneCode(phone: string): Promise {\n const data = {\n phone_number: phone,\n };\n\n return this.post('/auth/request_phone_code', data);\n }\n\n async phoneLogin(phone: string, code: string, scopes: string[]): Promise {\n const data = {\n phone_number: phone,\n code,\n scopes,\n };\n\n return this.post('/auth/phone_login', data).then((r) => this.storeToken(r));\n }\n\n // After complete login on provider browser will be redirected to redirectUrl\n // callbackUrl will be stored in sesson and returned after successfull login complete\n async federatedLogin(\n provider: FederatedLoginProvider,\n scopes: string[],\n redirectUrl: string,\n callbackUrl?: string,\n opts: { width?: number; height?: number; popUp?: boolean } = { width: 600, height: 800, popUp: false },\n ): Promise {\n const dataForm = document.createElement('form');\n dataForm.style.display = 'none';\n if (opts.popUp) {\n dataForm.target = 'TargetWindow'; // Make sure the window name is same as this value\n }\n dataForm.method = 'POST';\n const params = new URLSearchParams();\n params.set('appId', this.config.appId);\n params.set('provider', provider);\n params.set('scopes', scopes.join(','));\n params.set('redirectUrl', redirectUrl);\n if (callbackUrl) {\n params.set('callbackUrl', callbackUrl);\n }\n dataForm.action = `${this.baseUrl}/auth/federated?${params.toString()}`;\n\n document.body.appendChild(dataForm);\n\n if (opts.popUp) {\n const left = window.screenX + window.outerWidth / 2 - (opts.width || 600) / 2;\n const top = window.screenY + window.outerHeight / 2 - (opts.height || 800) / 2;\n const postWindow = window.open(\n '',\n 'TargetWindow',\n `status=0,title=0,height=${opts.height},width=${opts.width},top=${top},left=${left},scrollbars=1`,\n );\n if (postWindow) {\n dataForm.submit();\n }\n } else {\n window.location.assign(`${this.baseUrl}/auth/federated?${params.toString()}`);\n // dataForm.submit();\n }\n }\n\n async federatedLoginComplete(params: URLSearchParams): Promise {\n return this.get(`/auth/federated/complete?${params.toString()}`).then((r) => this.storeToken(r));\n }\n\n async register(email: string, password: string, scopes: string[], invite?: string): Promise {\n const data: Record = {\n email,\n password,\n scopes,\n };\n\n if (invite) {\n data.invite = invite;\n }\n\n return this.post('/auth/register', data).then((r) => this.storeToken(r));\n }\n\n async requestResetPassword(email: string, tfaCode?: string): Promise {\n const data = {\n email,\n tfa_code: tfaCode,\n };\n\n return this.post('/auth/request_reset_password', data);\n }\n\n async resetPassword(password: string): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n const data = {\n password,\n };\n\n return this.post('/auth/reset_password', data, {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n });\n }\n\n async getAppSettings(callbackUrl: string): Promise {\n return this.get(`/auth/app_settings?${new URLSearchParams({ callbackUrl }).toString()}`);\n }\n\n async enableTFA(data: { phone?: string; email?: string }): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.put('/auth/tfa/enable', data, {\n headers: { [AUTHORIZATION_HEADER_KEY]: `BEARER ${this.tokenService.getToken()?.token}` },\n }).then((r) => this.storeToken(r));\n }\n\n async verifyTFA(code: string, scopes: string[]): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/auth/tfa/login',\n { tfa_code: code, scopes },\n { headers: { [AUTHORIZATION_HEADER_KEY]: `BEARER ${this.tokenService.getToken()?.token}` } },\n ).then((r) => this.storeToken(r));\n }\n\n async resendTFA(): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post('/auth/tfa/resend', null, {\n headers: { [AUTHORIZATION_HEADER_KEY]: `BEARER ${this.tokenService.getToken()?.token}` },\n }).then((r) => this.storeToken(r));\n }\n\n async logout(): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/me/logout',\n {\n refresh_token: this.tokenService.getToken('refresh')?.token,\n },\n {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n },\n ).then((r) => {\n this.tokenService.removeToken();\n this.tokenService.removeToken('refresh');\n return r;\n });\n }\n\n async invite(email: string, role: string, callbackUrl: string): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/auth/invite',\n {\n email,\n access_role: role,\n callback_url: callbackUrl,\n },\n {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n },\n );\n }\n\n storeToken(response: T): T {\n if (response.access_token) {\n this.tokenService.saveToken(response.access_token, 'access');\n }\n if (response.refresh_token) {\n this.tokenService.saveToken(response.refresh_token, 'refresh');\n }\n return response;\n }\n}\n","export const jwtRegex = /^([a-zA-Z0-9_=]+)\\.([a-zA-Z0-9_=]+)\\.([a-zA-Z0-9_\\-=]*$)/;\n\n// Error messages\n\nexport const INVALID_TOKEN_ERROR = 'Empty or invalid token';\n\n// url query params keys\nexport const TOKEN_QUERY_KEY = 'token';\nexport const REFRESH_TOKEN_QUERY_KEY = 'refresh_token';\n","class CookieStorage {\n isAccessible = false;\n\n saveToken(): boolean {\n return true;\n }\n\n getToken(): string {\n throw new Error('Can not get token from HttpOnly');\n }\n\n deleteToken(): void {\n // throw new Error('Can not get token from HttpOnly');\n }\n}\n\nexport default CookieStorage;\n","import { TokenManager, TokenType } from '../types/types';\n\nclass StorageManager implements TokenManager {\n preffix = 'identifo_';\n\n storageType: 'localStorage' | 'sessionStorage' = 'localStorage';\n\n access = `${this.preffix}access_token`;\n\n refresh = `${this.preffix}refresh_token`;\n\n isAccessible = true;\n\n constructor(storageType: 'localStorage' | 'sessionStorage', accessKey?: string, refreshKey?: string) {\n this.access = accessKey ? this.preffix + accessKey : this.access;\n this.refresh = refreshKey ? this.preffix + refreshKey : this.refresh;\n this.storageType = storageType;\n }\n\n saveToken(token: string, tokenType: TokenType): boolean {\n if (token) {\n window[this.storageType].setItem(this[tokenType], token);\n return true;\n }\n return false;\n }\n\n getToken(tokenType: TokenType): string {\n return window[this.storageType].getItem(this[tokenType]) ?? '';\n }\n\n deleteToken(tokenType: TokenType): void {\n window[this.storageType].removeItem(this[tokenType]);\n }\n}\n\nexport default StorageManager;\n","import StorageManager from './storage-manager';\n\nclass LocalStorage extends StorageManager {\n constructor(accessKey?: string, refreshKey?: string) {\n super('localStorage', accessKey, refreshKey);\n }\n}\n\nexport default LocalStorage;\n","import StorageManager from './storage-manager';\n\nclass SessionStorage extends StorageManager {\n constructor(accessKey?: string, refreshKey?: string) {\n super('sessionStorage', accessKey, refreshKey);\n }\n}\n\nexport default SessionStorage;\n","import { INVALID_TOKEN_ERROR } from './constants';\nimport { LocalStorageManager } from './store-manager';\nimport { ClientToken, JWTPayload, TokenManager, TokenType } from './types/types';\n\nclass TokenService {\n isAuth = false;\n\n private tokenManager: TokenManager;\n\n constructor(tokenManager?: TokenManager) {\n this.tokenManager = tokenManager || new LocalStorageManager();\n // TODO: implement cookie as default\n // this.tokenManager = tokenManager || new CoockieStorage();\n }\n\n async handleVerification(token: string, audience: string, issuer?: string): Promise {\n if (!this.tokenManager.isAccessible) return true;\n try {\n await this.validateToken(token, audience, issuer);\n this.saveToken(token);\n return true;\n } catch (err) {\n this.removeToken();\n return Promise.reject(err);\n }\n }\n\n async validateToken(token: string, audience: string, issuer?: string): Promise {\n if (!token) throw new Error(INVALID_TOKEN_ERROR);\n const jwtPayload = this.parseJWT(token);\n const isJwtExpired = this.isJWTExpired(jwtPayload);\n if (jwtPayload.aud?.includes(audience) && (!issuer || jwtPayload.iss === issuer) && !isJwtExpired) {\n return Promise.resolve(true);\n }\n throw new Error(INVALID_TOKEN_ERROR);\n }\n\n parseJWT(token: string): JWTPayload {\n const base64Url = token.split('.')[1];\n if (!base64Url) return { aud: [], iss: '', exp: 10 };\n const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split('')\n .map((c) => `%${`00${c.charCodeAt(0).toString(16)}`.slice(-2)}`)\n .join(''),\n );\n return JSON.parse(jsonPayload) as JWTPayload;\n }\n\n isJWTExpired(token: JWTPayload): boolean {\n const now = new Date().getTime() / 1000;\n if (token.exp && now > token.exp) {\n return true;\n }\n return false;\n }\n\n saveToken(token: string, type: TokenType = 'access'): boolean {\n if (type === 'access') {\n this.isAuth = true;\n }\n return this.tokenManager.saveToken(token, type);\n }\n\n removeToken(type: TokenType = 'access'): void {\n if (type === 'access') {\n this.isAuth = false;\n }\n this.tokenManager.deleteToken(type);\n }\n\n getToken(type: TokenType = 'access'): ClientToken | null {\n const token = this.tokenManager.getToken(type);\n if (!token) return null;\n const jwtPayload = this.parseJWT(token);\n return { token, payload: jwtPayload };\n }\n}\n\nexport default TokenService;\n","import { IdentifoConfig, UrlFlows } from './types/types';\n\nexport class UrlBuilder {\n constructor(private config: IdentifoConfig) {}\n\n getUrl(flow: UrlFlows): string {\n const scopes = this.config.scopes?.join() || '';\n const redirectUri = this.config.redirectUri ?? window.location.href;\n const baseParams = `appId=${this.config.appId}&scopes=${scopes}`;\n const urlParams = `${baseParams}&callbackUrl=${encodeURIComponent(redirectUri)}`;\n // if postLogoutRedirectUri is empty, login url will be instead\n const postLogoutRedirectUri = this.config.postLogoutRedirectUri\n ? `${this.config.postLogoutRedirectUri}`\n : `${redirectUri}&redirectUri=${this.config.url}/web/login?${encodeURIComponent(baseParams)}`;\n\n const urls = {\n signup: `${this.config.url}/web/register?${urlParams}`,\n signin: `${this.config.url}/web/login?${urlParams}`,\n logout: `${this.config.url}/web/logout?${baseParams}&callbackUrl=${encodeURIComponent(postLogoutRedirectUri)}`,\n renew: `${this.config.url}/web/token/renew?${baseParams}&redirectUri=${encodeURIComponent(redirectUri)}`,\n default: 'default',\n };\n\n return urls[flow] || urls.default;\n }\n\n createSignupUrl(): string {\n return this.getUrl('signup');\n }\n\n createSigninUrl(): string {\n return this.getUrl('signin');\n }\n\n createLogoutUrl(): string {\n return this.getUrl('logout');\n }\n\n createRenewSessionUrl(): string {\n return this.getUrl('renew');\n }\n}\n","import { API } from './api/api';\nimport { jwtRegex, REFRESH_TOKEN_QUERY_KEY, TOKEN_QUERY_KEY } from './constants';\nimport TokenService from './tokenService';\nimport { ClientToken, IdentifoConfig, UrlBuilderInit } from './types/types';\nimport { UrlBuilder } from './UrlBuilder';\n\nclass IdentifoAuth {\n public api!: API;\n\n public tokenService!: TokenService;\n\n public config!: IdentifoConfig;\n\n public urlBuilder!: UrlBuilderInit;\n\n private token: ClientToken | null = null;\n\n get isAuth(): boolean {\n return !!this.tokenService?.isAuth;\n }\n\n constructor(config?: IdentifoConfig) {\n if (config) {\n this.configure(config);\n }\n }\n\n public configure(config: IdentifoConfig): void {\n this.config = { ...config, autoRenew: config.autoRenew ?? true };\n this.tokenService = new TokenService(config.tokenManager);\n this.urlBuilder = new UrlBuilder(this.config);\n this.api = new API(config, this.tokenService);\n this.handleToken(this.tokenService.getToken()?.token || '', 'access');\n }\n\n private handleToken(token: string, tokenType: 'access' | 'refresh') {\n if (token) {\n if (tokenType === 'access') {\n const payload = this.tokenService.parseJWT(token);\n this.token = { token, payload };\n this.tokenService.saveToken(token);\n } else {\n this.tokenService.saveToken(token, 'refresh');\n }\n }\n }\n\n private resetAuthValues() {\n this.token = null;\n this.tokenService.removeToken();\n this.tokenService.removeToken('refresh');\n }\n\n signup(): void {\n window.location.href = this.urlBuilder.createSignupUrl();\n }\n\n signin(): void {\n window.location.href = this.urlBuilder.createSigninUrl();\n }\n\n logout(): void {\n this.resetAuthValues();\n window.location.href = this.urlBuilder.createLogoutUrl();\n }\n\n async handleAuthentication(): Promise {\n const { access, refresh } = this.getTokenFromUrl();\n if (!access) {\n this.resetAuthValues();\n return Promise.reject();\n }\n try {\n await this.tokenService.handleVerification(access, this.config.appId, this.config.issuer);\n this.handleToken(access, 'access');\n if (refresh) {\n this.handleToken(refresh, 'refresh');\n }\n return await Promise.resolve(true);\n } catch (err) {\n this.resetAuthValues();\n return await Promise.reject();\n } finally {\n window.history.pushState({}, document.title, window.location.pathname);\n }\n }\n\n private getTokenFromUrl(): { access: string; refresh: string } {\n const urlParams = new URLSearchParams(window.location.search);\n const tokens = { access: '', refresh: '' };\n const accessToken = urlParams.get(TOKEN_QUERY_KEY);\n const refreshToken = urlParams.get(REFRESH_TOKEN_QUERY_KEY);\n if (refreshToken && jwtRegex.test(refreshToken)) {\n tokens.refresh = refreshToken;\n }\n if (accessToken && jwtRegex.test(accessToken)) {\n tokens.access = accessToken;\n }\n return tokens;\n }\n\n async getToken(): Promise {\n const token = this.tokenService.getToken();\n const refreshToken = this.tokenService.getToken('refresh');\n if (token) {\n const isExpired = this.tokenService.isJWTExpired(token.payload);\n if (isExpired && refreshToken) {\n try {\n await this.renewSession();\n return await Promise.resolve(this.token);\n } catch (err) {\n this.resetAuthValues();\n throw new Error('No token');\n }\n }\n return Promise.resolve(token);\n }\n return Promise.resolve(null);\n }\n\n async renewSession(): Promise {\n try {\n const { access, refresh } = await this.renewSessionWithToken();\n this.handleToken(access, 'access');\n this.handleToken(refresh, 'refresh');\n return await Promise.resolve(access);\n } catch (err) {\n return Promise.reject();\n }\n }\n\n private async renewSessionWithToken(): Promise<{ access: string; refresh: string }> {\n try {\n const tokens = await this.api\n .renewToken()\n .then((l) => ({ access: l.access_token || '', refresh: l.refresh_token || '' }));\n return tokens;\n } catch (err) {\n return Promise.reject(err);\n }\n }\n}\nexport default IdentifoAuth;\n","import {\n ApiError,\n FederatedLoginProvider,\n LoginResponse,\n ServerSettingsLoginTypes,\n TFAStatus,\n TFAType,\n SuccessResponse,\n} from '../api/model';\n\nexport enum Routes {\n 'LOGIN' = 'login',\n 'REGISTER' = 'register',\n 'TFA_VERIFY_SMS' = 'tfa/verify/sms',\n 'TFA_VERIFY_EMAIL' = 'tfa/verify/email',\n 'TFA_VERIFY_APP' = 'tfa/verify/app',\n 'TFA_VERIFY_SELECT' = 'tfa/verify/select',\n 'TFA_SETUP_SMS' = 'tfa/setup/sms',\n 'TFA_SETUP_EMAIL' = 'tfa/setup/email',\n 'TFA_SETUP_APP' = 'tfa/setup/app',\n 'TFA_SETUP_SELECT' = 'tfa/setup/select',\n 'PASSWORD_RESET' = 'password/reset',\n 'PASSWORD_FORGOT' = 'password/forgot',\n 'PASSWORD_FORGOT_TFA_SMS' = 'password/forgot/tfa/sms',\n 'PASSWORD_FORGOT_TFA_EMAIL' = 'password/forgot/tfa/email',\n 'PASSWORD_FORGOT_TFA_APP' = 'password/forgot/tfa/app',\n 'PASSWORD_FORGOT_TFA_SELECT' = 'password/forgot/tfa/select',\n 'CALLBACK' = 'callback',\n 'LOGIN_PHONE' = 'login_phone',\n 'LOGIN_PHONE_VERIFY' = 'login_phone_verify',\n 'ERROR' = 'error',\n 'PASSWORD_FORGOT_SUCCESS' = 'password/forgot/success',\n 'LOGOUT' = 'logout',\n 'LOADING' = 'loading',\n}\n\nexport type TFASetupRoutes =\n | Routes.TFA_SETUP_SELECT\n | Routes.TFA_SETUP_SMS\n | Routes.TFA_SETUP_EMAIL\n | Routes.TFA_SETUP_APP;\nexport type TFALoginVerifyRoutes =\n | Routes.TFA_VERIFY_SELECT\n | Routes.TFA_VERIFY_SMS\n | Routes.TFA_VERIFY_EMAIL\n | Routes.TFA_VERIFY_APP;\nexport type TFAResetVerifyRoutes =\n | Routes.PASSWORD_FORGOT_TFA_SELECT\n | Routes.PASSWORD_FORGOT_TFA_SMS\n | Routes.PASSWORD_FORGOT_TFA_EMAIL\n | Routes.PASSWORD_FORGOT_TFA_APP;\n\nexport interface State {\n route: Routes;\n}\n\nexport interface StateWithError {\n error?: ApiError;\n}\n\nexport type LoginTypes = Partial<\n Record void; type: keyof ServerSettingsLoginTypes }>\n>;\n\nexport interface StateLogin extends State, StateWithError {\n route: Routes.LOGIN;\n registrationForbidden: boolean;\n federatedProviders: FederatedLoginProvider[];\n loginTypes: LoginTypes;\n signup: () => Promise;\n signin: (email: string, password: string, remember?: boolean) => Promise;\n socialLogin: (provider: FederatedLoginProvider) => Promise;\n passwordForgot: () => Promise;\n}\n\nexport interface StateLoginPhone extends State, StateWithError {\n route: Routes.LOGIN_PHONE;\n registrationForbidden: boolean;\n federatedProviders: FederatedLoginProvider[];\n loginTypes: LoginTypes;\n requestCode: (phone: string) => Promise;\n socialLogin: (provider: FederatedLoginProvider) => Promise;\n}\nexport interface StateLoginPhoneVerify extends State, StateWithError {\n route: Routes.LOGIN_PHONE_VERIFY;\n phone: string;\n resendTimeout: number;\n resendCode: () => Promise;\n login: (code: string) => Promise;\n goback: () => Promise;\n}\n\nexport interface StateRegister extends State, StateWithError {\n route: Routes.REGISTER;\n signup: (email: string, password: string, token?: string) => Promise;\n goback: () => Promise;\n}\n\nexport interface StatePasswordForgot extends State, StateWithError {\n route: Routes.PASSWORD_FORGOT;\n restorePassword: (email: string) => Promise;\n goback: () => Promise;\n}\nexport interface StatePasswordForgotSuccess extends State {\n route: Routes.PASSWORD_FORGOT_SUCCESS;\n goback: () => Promise;\n}\n\nexport interface StateError extends State, StateWithError {\n route: Routes.ERROR;\n}\n\nexport interface StateCallback extends State {\n route: Routes.CALLBACK;\n callbackUrl?: string;\n result: LoginResponse;\n}\n\nexport interface StatePasswordReset extends State, StateWithError {\n route: Routes.PASSWORD_RESET;\n setNewPassword: (password: string) => Promise;\n}\n\nexport interface StateLoading extends State {\n route: Routes.LOADING;\n}\n\ninterface StateTFASetup extends State, StateWithError {}\n\nexport interface StateTFASetupApp extends StateTFASetup {\n route: Routes.TFA_SETUP_APP;\n provisioningURI: string;\n provisioningQR: string;\n setupTFA: () => Promise;\n}\nexport interface StateTFASetupEmail extends StateTFASetup {\n route: Routes.TFA_SETUP_EMAIL;\n email: string;\n setupTFA: (email: string) => Promise;\n}\nexport interface StateTFASetupSMS extends StateTFASetup {\n route: Routes.TFA_SETUP_SMS;\n phone: string;\n setupTFA: (phone: string) => Promise;\n}\n\ninterface StateTFASelect extends State {\n tfaTypes: TFAType[];\n select: (type: TFAType) => Promise;\n email?: string;\n phone?: string;\n}\n\nexport interface StateTFASetupSelect extends StateTFASelect {\n route: Routes.TFA_SETUP_SELECT;\n tfaStatus: TFAStatus;\n setupNextTime: () => Promise;\n}\nexport interface StateTFAVerifySelect extends StateTFASelect {\n route: Routes.TFA_VERIFY_SELECT;\n}\nexport interface StatePasswordForgotTFASelect extends StateTFASelect {\n route: Routes.PASSWORD_FORGOT_TFA_SELECT;\n}\n\nexport interface StateTFAVerifyApp extends State, StateWithError {\n route: Routes.TFA_VERIFY_APP;\n email?: string;\n phone?: string;\n verifyTFA: (code: string) => Promise;\n}\n\nexport interface StateTFAVerifyEmailSms extends State, StateWithError {\n route: Routes.TFA_VERIFY_EMAIL | Routes.TFA_VERIFY_SMS;\n email?: string;\n phone?: string;\n resendTimeout: number;\n verifyTFA: (code: string) => Promise;\n resendTFA: () => Promise;\n}\n\nexport interface StatePasswordForgotTFAVerify extends State, StateWithError {\n route: Routes.PASSWORD_FORGOT_TFA_APP | Routes.PASSWORD_FORGOT_TFA_EMAIL | Routes.PASSWORD_FORGOT_TFA_SMS;\n email?: string;\n phone?: string;\n verifyTFA: (code: string) => Promise;\n}\n\nexport interface StateLogout extends State {\n route: Routes.LOGOUT;\n logout: () => Promise;\n}\n\nexport const typeToSetupRoute = {\n [TFAType.TFATypeApp]: Routes.TFA_SETUP_APP,\n [TFAType.TFATypeEmail]: Routes.TFA_SETUP_EMAIL,\n [TFAType.TFATypeSMS]: Routes.TFA_SETUP_SMS,\n};\n\nexport const typeToTFAVerifyRoute = {\n [TFAType.TFATypeApp]: Routes.TFA_VERIFY_APP,\n [TFAType.TFATypeEmail]: Routes.TFA_VERIFY_EMAIL,\n [TFAType.TFATypeSMS]: Routes.TFA_VERIFY_SMS,\n};\nexport const typeToPasswordForgotTFAVerifyRoute = {\n [TFAType.TFATypeApp]: Routes.PASSWORD_FORGOT_TFA_APP,\n [TFAType.TFATypeEmail]: Routes.PASSWORD_FORGOT_TFA_EMAIL,\n [TFAType.TFATypeSMS]: Routes.PASSWORD_FORGOT_TFA_SMS,\n};\n\n// TODO exclude generalState\nexport type States =\n | State\n | StateTFASetupApp\n | StateTFASetupEmail\n | StateTFASetupSMS\n | StatePasswordReset\n | StatePasswordForgot\n | StatePasswordForgotSuccess\n | StateLoading\n | StateCallback\n | StateLogin\n | StateRegister\n | StateError;\n","import { BehaviorSubject } from 'rxjs';\nimport { StateLoginPhone, StateLoginPhoneVerify } from '..';\nimport {\n ApiError,\n APIErrorCodes,\n AppSettingsResponse,\n FederatedLoginProvider,\n LoginResponse,\n ServerSettingsLoginTypes,\n TFAStatus,\n TFAType,\n} from '../api/model';\nimport IdentifoAuth from '../IdentifoAuth';\nimport { IdentifoConfig } from '../types/types';\nimport {\n LoginTypes,\n Routes,\n State,\n StateCallback,\n StateError,\n StateLogout,\n StatePasswordForgotTFASelect,\n StatePasswordForgotTFAVerify,\n States,\n StateTFASetupSelect,\n StateTFAVerifyApp,\n StateTFAVerifyEmailSms,\n StateTFAVerifySelect,\n StateWithError,\n typeToPasswordForgotTFAVerifyRoute,\n typeToTFAVerifyRoute,\n} from './model';\n\nconst emailRegex =\n // eslint-disable-next-line max-len\n /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\nconst phoneRegex = /^[\\+][0-9]{9,15}$/;\n\nexport class CDK {\n auth: IdentifoAuth;\n\n settings!: AppSettingsResponse;\n\n lastError!: ApiError;\n\n callbackUrl?: string;\n\n postLogoutRedirectUri?: string;\n\n scopes: Set = new Set();\n\n state: BehaviorSubject = new BehaviorSubject({ route: Routes.LOADING } as States);\n\n constructor() {\n this.auth = new IdentifoAuth();\n }\n\n // eslint-disable-next-line max-statements\n async configure(authConfig: IdentifoConfig, callbackUrl: string): Promise {\n this.state.next({ route: Routes.LOADING });\n\n this.callbackUrl = callbackUrl;\n this.scopes = new Set(authConfig.scopes ?? []);\n\n this.postLogoutRedirectUri = window.location.origin + window.location.pathname;\n // this.postLogoutRedirectUri = this.postLogoutRedirectUri || window.location.origin + window.location.pathname;\n\n if (!authConfig.appId) {\n this.state.next({\n route: Routes.ERROR,\n error: { message: 'app-id param is empty', name: 'app-id empty' },\n } as StateError);\n return;\n }\n if (!authConfig.url) {\n this.state.next({\n route: Routes.ERROR,\n error: { message: 'url param is empty', name: 'url empty' },\n } as StateError);\n return;\n }\n\n this.auth.configure(authConfig);\n try {\n this.settings = await this.auth.api.getAppSettings(callbackUrl);\n } catch (err) {\n this.state.next({\n route: Routes.ERROR,\n error: err as ApiError,\n } as StateError);\n return;\n }\n this.settings.tfaType = Array.isArray(this.settings.tfaType) ? this.settings.tfaType : [this.settings.tfaType];\n\n // // If we have provider and state then we need to complete federated login\n const href = new URL(window.location.href);\n if (!!href.searchParams.get('provider') && !!href.searchParams.get('state')) {\n // Also we clear all url params after parsing\n const u = new URL(window.location.href);\n const sp = new URLSearchParams();\n const appId = href.searchParams.get('appId');\n if (appId === null) {\n this.state.next({\n route: Routes.ERROR,\n error: { message: 'app-id param is empty', name: 'app-id empty' },\n } as StateError);\n return;\n }\n sp.set('appId', appId);\n window.history.replaceState({}, document.title, `${u.pathname}?${sp.toString()}`);\n this.auth.api\n .federatedLoginComplete(u.searchParams)\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n }\n }\n\n login(): void {\n // check for allowed login with\n switch (true) {\n case (!this.auth.config.loginWith && this.settings.loginWith['phone']) ||\n (this.auth.config.loginWith === 'phone' && this.settings.loginWith['phone']):\n return this.loginWithPhone();\n case (!this.auth.config.loginWith && this.settings.loginWith['email']) ||\n (this.auth.config.loginWith === 'email' && this.settings.loginWith['email']):\n return this.loginWithPassword();\n default:\n throw 'Unsupported login way';\n }\n }\n loginWithPhone(): void {\n this.state.next({\n route: Routes.LOGIN_PHONE,\n registrationForbidden: this.settings?.registrationForbidden,\n error: this.lastError,\n federatedProviders: this.settings?.federatedProviders,\n loginTypes: this.getLoginTypes('phone'),\n requestCode: async (phone: string, remember?: boolean): Promise => {\n if (!this.validatePhone(phone)) {\n return;\n }\n const scopes = new Set(this.scopes);\n if (remember) {\n scopes.add('offline');\n }\n await this.auth.api\n .requestPhoneCode(phone)\n .then(() => this.loginWithPhoneVerify(phone, remember))\n .catch((e) => this.processError(e));\n },\n socialLogin: async (provider: FederatedLoginProvider) => {\n this.state.next({ route: Routes.LOADING });\n const federatedRedirectUrl = window.location.origin + window.location.pathname;\n return this.auth.api.federatedLogin(\n provider,\n [...Array.from(this.scopes)],\n federatedRedirectUrl,\n this.callbackUrl,\n );\n },\n } as StateLoginPhone);\n }\n loginWithPhoneVerify(phone: string, remember?: boolean): void {\n this.state.next({\n route: Routes.LOGIN_PHONE_VERIFY,\n error: this.lastError,\n phone: phone,\n resendTimeout: this.settings.tfaResendTimeout * 1000,\n resendCode: async () => {\n await this.auth.api.requestPhoneCode(phone);\n },\n login: async (code: string): Promise => {\n const scopes = new Set(this.scopes);\n if (remember) {\n scopes.add('offline');\n }\n await this.auth.api\n .phoneLogin(phone, code, [...Array.from(this.scopes)])\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n goback: async (): Promise => {\n this.login();\n },\n } as StateLoginPhoneVerify);\n }\n loginWithPassword(): void {\n this.state.next({\n route: Routes.LOGIN,\n registrationForbidden: this.settings?.registrationForbidden,\n error: this.lastError,\n federatedProviders: this.settings?.federatedProviders,\n loginTypes: this.getLoginTypes('email'),\n signup: async (): Promise => {\n this.register();\n },\n signin: async (email: string, password: string, remember?: boolean): Promise => {\n if (!this.validateEmail(email)) {\n return;\n }\n const scopes = new Set(this.scopes);\n if (remember) {\n scopes.add('offline');\n }\n await this.auth.api\n .login(email, password, '', [...Array.from(scopes)])\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n socialLogin: async (provider: FederatedLoginProvider) => {\n this.state.next({ route: Routes.LOADING });\n const federatedRedirectUrl = window.location.origin + window.location.pathname;\n return this.auth.api.federatedLogin(\n provider,\n [...Array.from(this.scopes)],\n federatedRedirectUrl,\n this.callbackUrl,\n );\n },\n passwordForgot: async () => {\n this.forgotPassword();\n },\n });\n }\n\n register(): void {\n this.state.next({\n route: Routes.REGISTER,\n signup: async (email: string, password: string, token?: string): Promise => {\n if (!this.validateEmail(email)) {\n return;\n }\n await this.auth.api\n .register(email, password, [...Array.from(this.scopes)], token)\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n\n forgotPassword(): void {\n this.state.next({\n route: Routes.PASSWORD_FORGOT,\n restorePassword: async (email: string): Promise => {\n return this.auth.api\n .requestResetPassword(email)\n .then(async (response) => {\n if (response.result === 'tfa-required') {\n await this.redirectTfaForgot(email);\n return;\n }\n if (response.result === 'ok') {\n this.forgotPasswordSuccess();\n }\n })\n .catch((e) => this.processError(e));\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n\n forgotPasswordSuccess(): void {\n this.state.next({\n route: Routes.PASSWORD_FORGOT_SUCCESS,\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n\n passwordReset(): void {\n this.state.next({\n route: Routes.PASSWORD_RESET,\n setNewPassword: async (password: string): Promise => {\n this.auth.api\n .resetPassword(password)\n .then(() => {\n this.login();\n })\n .catch((e) => this.processError(e));\n },\n });\n }\n\n callback(result: LoginResponse): void {\n this.state.next({\n route: Routes.CALLBACK,\n callbackUrl: this.callbackUrl,\n result,\n } as StateCallback);\n if (this.callbackUrl) {\n const url = new URL(this.callbackUrl);\n if (result.access_token) {\n url.searchParams.set('token', result.access_token);\n }\n if (result.refresh_token) {\n url.searchParams.set('refresh_token', result.refresh_token);\n }\n window.location.href = url.toString();\n }\n }\n\n validateEmail(email: string): boolean {\n if (!emailRegex.test(email)) {\n this.processError({\n detailedMessage: 'Email address is not valid',\n name: 'Validation error',\n message: 'Email address is not valid',\n } as ApiError);\n return false;\n }\n return true;\n }\n\n validatePhone(email: string): boolean {\n if (!phoneRegex.test(email)) {\n this.processError({\n detailedMessage: 'Phone is not valid',\n name: 'Validation error',\n message: 'Phone is not valid',\n } as ApiError);\n return false;\n }\n return true;\n }\n\n async tfaSetup(loginResponse: LoginResponse, type: TFAType): Promise {\n switch (type) {\n case TFAType.TFATypeApp: {\n this.state.next({\n route: Routes.TFA_SETUP_APP,\n provisioningURI: '',\n provisioningQR: '',\n setupTFA: async () => {},\n goback: async (): Promise => {\n this.login();\n },\n });\n const tfa = await this.auth.api.enableTFA({});\n if (tfa.provisioning_uri) {\n this.state.next({\n route: Routes.TFA_SETUP_APP,\n provisioningURI: tfa.provisioning_uri,\n provisioningQR: tfa.provisioning_qr || '',\n setupTFA: async () => this.tfaVerify(loginResponse, type),\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n break;\n }\n case TFAType.TFATypeEmail: {\n this.state.next({\n route: Routes.TFA_SETUP_EMAIL,\n email: loginResponse.user.email || '',\n setupTFA: async (email: string) => {\n await this.auth.api.enableTFA({ email });\n return this.tfaVerify({ ...loginResponse, user: { ...loginResponse.user, email } }, type);\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n break;\n }\n case TFAType.TFATypeSMS: {\n this.state.next({\n route: Routes.TFA_SETUP_SMS,\n phone: loginResponse.user.phone || '',\n setupTFA: async (phone: string) => {\n await this.auth.api.enableTFA({ phone });\n return this.tfaVerify({ ...loginResponse, user: { ...loginResponse.user, phone } }, type);\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n break;\n }\n default:\n }\n }\n\n async tfaVerify(loginResponse: LoginResponse, type: TFAType): Promise {\n const state = {\n route: typeToTFAVerifyRoute[type],\n email: loginResponse.user.email,\n phone: loginResponse.user.phone,\n verifyTFA: async (code: string) => {\n await this.auth.api\n .verifyTFA(code, [...Array.from(this.scopes)])\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n };\n switch (type) {\n case TFAType.TFATypeApp: {\n this.state.next({ ...state } as StateTFAVerifyApp);\n break;\n }\n case TFAType.TFATypeEmail:\n case TFAType.TFATypeSMS: {\n this.state.next({\n ...state,\n resendTimeout: this.settings.tfaResendTimeout * 1000, // in ms\n resendTFA: async () => {\n await this.auth.api.resendTFA();\n },\n } as StateTFAVerifyEmailSms);\n break;\n }\n default:\n }\n }\n\n async passwordForgotTFAVerify(email: string, type: TFAType): Promise {\n this.state.next({\n route: typeToPasswordForgotTFAVerifyRoute[type],\n verifyTFA: async (code: string) => {\n this.auth.api\n .requestResetPassword(email, code)\n .then(() => {\n this.forgotPasswordSuccess();\n })\n .catch((e) => this.processError(e));\n },\n } as StatePasswordForgotTFAVerify);\n }\n\n async logout(): Promise {\n this.state.next({\n route: Routes.LOGOUT,\n logout: async () => this.auth.api.logout(),\n } as StateLogout);\n }\n\n // restorePassword(token: string): void {}\n\n private processError(e: ApiError) {\n e.detailedMessage = e.detailedMessage?.trim();\n e.message = e.message?.trim();\n\n this.state.next({\n ...this.state.getValue(),\n error: e,\n } as State & StateWithError);\n }\n\n private async redirectTfaSetup(loginResponse: LoginResponse): Promise {\n if (this.settings.tfaType.length === 1) {\n await this.tfaSetup(loginResponse, this.settings.tfaType[0] as TFAType);\n return;\n }\n this.tfaSetupSelect(loginResponse);\n }\n\n private tfaSetupSelect(loginResponse: LoginResponse): void {\n this.state.next({\n route: Routes.TFA_SETUP_SELECT,\n tfaStatus: this.settings.tfaStatus,\n tfaTypes: this.settings.tfaType,\n select: async (type: TFAType) => {\n await this.tfaSetup(loginResponse, type);\n },\n setupNextTime: () => {\n this.callback(loginResponse);\n },\n } as StateTFASetupSelect);\n }\n\n private async redirectTfaVerify(e: LoginResponse): Promise {\n if (this.settings.tfaType.length === 1) {\n await this.tfaVerify(e, this.settings.tfaType[0] as TFAType);\n return;\n }\n this.state.next({\n route: Routes.TFA_VERIFY_SELECT,\n tfaStatus: this.settings.tfaStatus,\n tfaTypes: this.settings.tfaType,\n select: async (type: TFAType) => {\n await this.tfaVerify(e, type);\n },\n } as StateTFAVerifySelect);\n }\n\n private async redirectTfaForgot(email: string): Promise {\n if (this.settings.tfaType.length === 1) {\n await this.passwordForgotTFAVerify(email, this.settings.tfaType[0] as TFAType);\n return;\n }\n this.state.next({\n route: Routes.PASSWORD_FORGOT_TFA_SELECT,\n tfaStatus: this.settings.tfaStatus,\n tfaTypes: this.settings.tfaType,\n select: async (type: TFAType) => {\n await this.passwordForgotTFAVerify(email, type);\n },\n } as StatePasswordForgotTFASelect);\n }\n\n // eslint-disable-next-line complexity\n private afterLoginRedirect = async (loginResponse: LoginResponse): Promise => {\n if (loginResponse.require_2fa) {\n if (!loginResponse.enabled_2fa) {\n await this.redirectTfaSetup(loginResponse);\n return;\n }\n if (loginResponse.enabled_2fa) {\n await this.redirectTfaVerify(loginResponse);\n return;\n }\n }\n // Ask about tfa on login only\n if (\n this.settings.tfaStatus === TFAStatus.OPTIONAL &&\n [Routes.LOGIN, Routes.REGISTER].includes(this.state.getValue().route)\n ) {\n this.tfaSetupSelect(loginResponse);\n return;\n }\n if (loginResponse.access_token && loginResponse.refresh_token) {\n this.callback(loginResponse);\n return;\n }\n if (loginResponse.access_token && !loginResponse.refresh_token) {\n this.callback(loginResponse);\n return;\n }\n this.login();\n };\n\n private loginCatchRedirect = (data: ApiError): void => {\n if (data.id === APIErrorCodes.PleaseEnableTFA) {\n // this.redirectTfaSetup();\n return;\n }\n throw data;\n };\n private getLoginTypes(current: keyof ServerSettingsLoginTypes): LoginTypes {\n const result: LoginTypes = {};\n Object.entries(this.settings.loginWith)\n .filter((v) => v[1] && v[0] !== current)\n .forEach((v) => {\n result[v[0] as keyof ServerSettingsLoginTypes] = {\n type: v[0] as keyof ServerSettingsLoginTypes,\n click: () => {\n this.auth.config.loginWith = v[0] as keyof ServerSettingsLoginTypes;\n this.login();\n },\n };\n });\n return result;\n }\n}\n"],"names":["APIErrorCodes","TFAType","TFAStatus","__async","__spreadValues","LocalStorageManager","__spreadProps","Routes","BehaviorSubject"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"identifo.js","sources":["../src/api/model.ts","../src/api/api.ts","../src/constants.ts","../src/store-manager/cookie-storage.ts","../src/store-manager/storage-manager.ts","../src/store-manager/local-storage.ts","../src/store-manager/session-storage.ts","../src/tokenService.ts","../src/UrlBuilder.ts","../src/IdentifoAuth.ts","../src/cdk/model.ts","../src/cdk/cdk.ts"],"sourcesContent":["/* eslint-disable camelcase */\nexport enum APIErrorCodes {\n PleaseEnableTFA = 'error.api.request.2fa.please_enable',\n InvalidCallbackURL = 'error.api.request.callbackurl.invalid',\n NetworkError = 'error.network',\n}\n\nexport enum TFAType {\n TFATypeApp = 'app',\n TFATypeSMS = 'sms',\n TFATypeEmail = 'email',\n}\n\nexport enum TFAStatus {\n DISABLED = 'disabled',\n OPTIONAL = 'optional',\n MANDATORY = 'mandatory',\n}\n\nexport interface ServerSettingsLoginTypes {\n email: boolean;\n federated: boolean;\n federated_oidc: boolean;\n phone: boolean;\n username: boolean;\n}\n\nexport type FederatedLoginProvider = 'apple' | 'google' | 'facebook';\nexport interface ApiRequestError {\n error: {\n detailed_message?: string;\n id?: APIErrorCodes;\n message?: string;\n status?: number;\n };\n}\nexport class ApiError extends Error {\n detailedMessage?: string;\n\n id?: APIErrorCodes;\n\n status?: number;\n\n constructor(error?: ApiRequestError['error']) {\n super(error?.message || 'Unknown API error');\n this.detailedMessage = error?.detailed_message;\n this.id = error?.id;\n this.status = error?.status;\n }\n}\nexport interface LoginResponse {\n access_token?: string;\n refresh_token?: string;\n require_2fa: boolean;\n enabled_2fa: boolean;\n user: {\n active: boolean;\n email?: string;\n id: string;\n latest_login_time: number;\n num_of_logins: number;\n username?: string;\n tfa_info: { hotp_expired_at: string };\n phone?: string;\n };\n scopes?: string[];\n callbackUrl?: string;\n}\nexport interface EnableTFAResponse {\n provisioning_uri?: string;\n provisioning_qr?: string;\n access_token?: string;\n}\nexport interface TokenResponse {\n access_token?: string;\n refresh_token?: string;\n}\nexport interface AppSettingsResponse {\n anonymousResitrationAllowed: boolean;\n active: boolean;\n description: string;\n id: string;\n newUserDefaultRole: string;\n offline: boolean;\n registrationForbidden: boolean;\n tfaType: TFAType[] | TFAType;\n tfaResendTimeout: number;\n tfaStatus: TFAStatus;\n federatedProviders: FederatedLoginProvider[];\n loginWith: ServerSettingsLoginTypes;\n federatedOIDCInitURL: string;\n}\n\nexport interface User {\n id: string;\n username: string;\n email: string;\n phone: string;\n active: boolean;\n tfa_info: {\n is_enabled: boolean;\n };\n num_of_logins: number;\n latest_login_time: number;\n access_role: string;\n anonymous: boolean;\n federated_ids: string[];\n}\nexport interface UpdateUser {\n new_email?: string;\n new_phone?: string;\n}\nexport interface SuccessResponse {\n result: 'ok';\n message?: string;\n}\n\nexport interface InviteResponse {\n result: 'ok';\n link: string;\n}\n\nexport interface TFARequiredRespopnse {\n result: 'tfa-required';\n}\n","import { InviteResponse } from '..';\nimport TokenService from '../tokenService';\nimport { IdentifoConfig } from '../types/types';\nimport {\n AppSettingsResponse,\n EnableTFAResponse,\n LoginResponse,\n SuccessResponse,\n UpdateUser,\n User,\n ApiRequestError,\n ApiError,\n APIErrorCodes,\n FederatedLoginProvider,\n TokenResponse,\n TFARequiredRespopnse,\n} from './model';\n\nconst APP_ID_HEADER_KEY = 'X-Identifo-Clientid';\nconst AUTHORIZATION_HEADER_KEY = 'Authorization';\n\nexport class API {\n baseUrl: string;\n\n appId: string;\n\n defaultHeaders = {\n [APP_ID_HEADER_KEY]: '',\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n };\n\n catchNetworkErrorHandler = (e: TypeError): never => {\n if (\n e.message === 'Network Error' ||\n e.message === 'Failed to fetch' ||\n e.message === 'Preflight response is not successful' ||\n e.message.indexOf('is not allowed by Access-Control-Allow-Origin') > -1\n ) {\n // eslint-disable-next-line no-console\n console.error(e.message);\n throw new ApiError({\n id: APIErrorCodes.NetworkError,\n status: 0,\n message: 'Configuration error',\n detailed_message:\n 'Please check Identifo URL and add \"' +\n `${window.location.protocol}//${window.location.host}\" ` +\n 'to \"REDIRECT URLS\" in Identifo app settings.',\n });\n }\n throw e;\n };\n\n checkStatusCodeAndGetJSON = async (r: Response): Promise => {\n if (!r.ok) {\n const error = (await r.json()) as ApiRequestError;\n throw new ApiError(error?.error);\n }\n return r.json();\n };\n\n constructor(private config: IdentifoConfig, private tokenService: TokenService) {\n // remove trailing slash if exist\n this.baseUrl = config.url.replace(/\\/$/, '');\n this.defaultHeaders[APP_ID_HEADER_KEY] = config.appId;\n this.appId = config.appId;\n }\n\n get(path: string, options?: RequestInit): Promise {\n return this.send(path, { method: 'GET', ...options });\n }\n\n put(path: string, data: unknown, options?: RequestInit): Promise {\n return this.send(path, { method: 'PUT', body: JSON.stringify(data), ...options });\n }\n\n post(path: string, data: unknown, options?: RequestInit): Promise {\n return this.send(path, { method: 'POST', body: JSON.stringify(data), ...options });\n }\n\n send(path: string, options?: RequestInit): Promise {\n const init = { ...options };\n init.credentials = 'include';\n init.headers = {\n ...init.headers,\n ...this.defaultHeaders,\n };\n return fetch(`${this.baseUrl}${path}`, init)\n .catch(this.catchNetworkErrorHandler)\n .then(this.checkStatusCodeAndGetJSON)\n .then((value) => value as T);\n }\n\n async getUser(): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.get('/me', {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n });\n }\n\n async renewToken(): Promise {\n if (!this.tokenService.getToken('refresh')?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/auth/token',\n { scopes: this.config.scopes },\n {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken('refresh')?.token}`,\n },\n },\n ).then((r) => this.storeToken(r));\n }\n\n async updateUser(user: UpdateUser): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.put('/me', user, {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken('access')?.token}`,\n },\n });\n }\n\n async login(email: string, password: string, deviceToken: string, scopes: string[]): Promise {\n const data = {\n email,\n password,\n device_token: deviceToken,\n scopes,\n };\n\n return this.post('/auth/login', data).then((r) => this.storeToken(r));\n }\n\n async requestPhoneCode(phone: string): Promise {\n const data = {\n phone_number: phone,\n };\n\n return this.post('/auth/request_phone_code', data);\n }\n\n async phoneLogin(phone: string, code: string, scopes: string[]): Promise {\n const data = {\n phone_number: phone,\n code,\n scopes,\n };\n\n return this.post('/auth/phone_login', data).then((r) => this.storeToken(r));\n }\n\n // After complete login on provider browser will be redirected to redirectUrl\n // callbackUrl will be stored in sesson and returned after successfull login complete\n async federatedLogin(\n provider: FederatedLoginProvider,\n scopes: string[],\n redirectUrl: string,\n callbackUrl?: string,\n opts: { width?: number; height?: number; popUp?: boolean } = { width: 600, height: 800, popUp: false },\n ): Promise {\n const dataForm = document.createElement('form');\n dataForm.style.display = 'none';\n if (opts.popUp) {\n dataForm.target = 'TargetWindow'; // Make sure the window name is same as this value\n }\n dataForm.method = 'POST';\n const params = new URLSearchParams();\n params.set('appId', this.config.appId);\n params.set('provider', provider);\n params.set('scopes', scopes.join(','));\n params.set('redirectUrl', redirectUrl);\n if (callbackUrl) {\n params.set('callbackUrl', callbackUrl);\n }\n dataForm.action = `${this.baseUrl}/auth/federated?${params.toString()}`;\n\n document.body.appendChild(dataForm);\n\n if (opts.popUp) {\n const left = window.screenX + window.outerWidth / 2 - (opts.width || 600) / 2;\n const top = window.screenY + window.outerHeight / 2 - (opts.height || 800) / 2;\n const postWindow = window.open(\n '',\n 'TargetWindow',\n `status=0,title=0,height=${opts.height},width=${opts.width},top=${top},left=${left},scrollbars=1`,\n );\n if (postWindow) {\n dataForm.submit();\n }\n } else {\n window.location.assign(`${this.baseUrl}/auth/federated?${params.toString()}`);\n // dataForm.submit();\n }\n }\n\n async federatedLoginComplete(params: URLSearchParams): Promise {\n return this.get(`/auth/federated/complete?${params.toString()}`).then((r) => this.storeToken(r));\n }\n\n async register(email: string, password: string, scopes: string[], invite?: string): Promise {\n const data: Record = {\n email,\n password,\n scopes,\n };\n\n if (invite) {\n data.invite = invite;\n }\n\n return this.post('/auth/register', data).then((r) => this.storeToken(r));\n }\n\n async requestResetPassword(email: string, tfaCode?: string): Promise {\n const data = {\n email,\n tfa_code: tfaCode,\n };\n\n return this.post('/auth/request_reset_password', data);\n }\n\n async resetPassword(password: string): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n const data = {\n password,\n };\n\n return this.post('/auth/reset_password', data, {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n });\n }\n\n async getAppSettings(callbackUrl: string): Promise {\n return this.get(`/auth/app_settings?${new URLSearchParams({ callbackUrl }).toString()}`);\n }\n\n async enableTFA(data: { phone?: string; email?: string }): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.put('/auth/tfa/enable', data, {\n headers: { [AUTHORIZATION_HEADER_KEY]: `BEARER ${this.tokenService.getToken()?.token}` },\n }).then((r) => this.storeToken(r));\n }\n\n async verifyTFA(code: string, scopes: string[]): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/auth/tfa/login',\n { tfa_code: code, scopes },\n { headers: { [AUTHORIZATION_HEADER_KEY]: `BEARER ${this.tokenService.getToken()?.token}` } },\n ).then((r) => this.storeToken(r));\n }\n\n async resendTFA(): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post('/auth/tfa/resend', null, {\n headers: { [AUTHORIZATION_HEADER_KEY]: `BEARER ${this.tokenService.getToken()?.token}` },\n }).then((r) => this.storeToken(r));\n }\n\n async logout(): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/me/logout',\n {\n refresh_token: this.tokenService.getToken('refresh')?.token,\n },\n {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n },\n ).then((r) => {\n this.tokenService.removeToken();\n this.tokenService.removeToken('refresh');\n return r;\n });\n }\n\n async oidcVerify(data: { state: string; code: string; scopes: string[] }): Promise {\n const url = `/auth/federated/oidc/complete?appId=${this.appId}&state=${data.state}&code=${data.code}`;\n return this.post(url, { scopes: data.scopes }, { credentials: 'include' }).then((r) =>\n this.storeToken(r),\n );\n }\n\n async invite(email: string, role: string, callbackUrl: string): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/auth/invite',\n {\n email,\n access_role: role,\n callback_url: callbackUrl,\n },\n {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n },\n );\n }\n\n storeToken(response: T): T {\n if (response.access_token) {\n this.tokenService.saveToken(response.access_token, 'access');\n }\n if (response.refresh_token) {\n this.tokenService.saveToken(response.refresh_token, 'refresh');\n }\n return response;\n }\n}\n","export const jwtRegex = /^([a-zA-Z0-9_=]+)\\.([a-zA-Z0-9_=]+)\\.([a-zA-Z0-9_\\-=]*$)/;\n\n// Error messages\n\nexport const INVALID_TOKEN_ERROR = 'Empty or invalid token';\n\n// url query params keys\nexport const TOKEN_QUERY_KEY = 'token';\nexport const REFRESH_TOKEN_QUERY_KEY = 'refresh_token';\n","class CookieStorage {\n isAccessible = false;\n\n saveToken(): boolean {\n return true;\n }\n\n getToken(): string {\n throw new Error('Can not get token from HttpOnly');\n }\n\n deleteToken(): void {\n // throw new Error('Can not get token from HttpOnly');\n }\n}\n\nexport default CookieStorage;\n","import { TokenManager, TokenType } from '../types/types';\n\nclass StorageManager implements TokenManager {\n preffix = 'identifo_';\n\n storageType: 'localStorage' | 'sessionStorage' = 'localStorage';\n\n access = `${this.preffix}access_token`;\n\n refresh = `${this.preffix}refresh_token`;\n\n isAccessible = true;\n\n constructor(storageType: 'localStorage' | 'sessionStorage', accessKey?: string, refreshKey?: string) {\n this.access = accessKey ? this.preffix + accessKey : this.access;\n this.refresh = refreshKey ? this.preffix + refreshKey : this.refresh;\n this.storageType = storageType;\n }\n\n saveToken(token: string, tokenType: TokenType): boolean {\n if (token) {\n window[this.storageType].setItem(this[tokenType], token);\n return true;\n }\n return false;\n }\n\n getToken(tokenType: TokenType): string {\n return window[this.storageType].getItem(this[tokenType]) ?? '';\n }\n\n deleteToken(tokenType: TokenType): void {\n window[this.storageType].removeItem(this[tokenType]);\n }\n}\n\nexport default StorageManager;\n","import StorageManager from './storage-manager';\n\nclass LocalStorage extends StorageManager {\n constructor(accessKey?: string, refreshKey?: string) {\n super('localStorage', accessKey, refreshKey);\n }\n}\n\nexport default LocalStorage;\n","import StorageManager from './storage-manager';\n\nclass SessionStorage extends StorageManager {\n constructor(accessKey?: string, refreshKey?: string) {\n super('sessionStorage', accessKey, refreshKey);\n }\n}\n\nexport default SessionStorage;\n","import { INVALID_TOKEN_ERROR } from './constants';\nimport { LocalStorageManager } from './store-manager';\nimport { ClientToken, JWTPayload, TokenManager, TokenType } from './types/types';\n\nclass TokenService {\n isAuth = false;\n\n private tokenManager: TokenManager;\n\n constructor(tokenManager?: TokenManager) {\n this.tokenManager = tokenManager || new LocalStorageManager();\n // TODO: implement cookie as default\n // this.tokenManager = tokenManager || new CoockieStorage();\n }\n\n async handleVerification(token: string, audience: string, issuer?: string): Promise {\n if (!this.tokenManager.isAccessible) return true;\n try {\n await this.validateToken(token, audience, issuer);\n this.saveToken(token);\n return true;\n } catch (err) {\n this.removeToken();\n return Promise.reject(err);\n }\n }\n\n async validateToken(token: string, audience: string, issuer?: string): Promise {\n if (!token) throw new Error(INVALID_TOKEN_ERROR);\n const jwtPayload = this.parseJWT(token);\n const isJwtExpired = this.isJWTExpired(jwtPayload);\n if (jwtPayload.aud?.includes(audience) && (!issuer || jwtPayload.iss === issuer) && !isJwtExpired) {\n return Promise.resolve(true);\n }\n throw new Error(INVALID_TOKEN_ERROR);\n }\n\n parseJWT(token: string): JWTPayload {\n const base64Url = token.split('.')[1];\n if (!base64Url) return { aud: [], iss: '', exp: 10 };\n const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split('')\n .map((c) => `%${`00${c.charCodeAt(0).toString(16)}`.slice(-2)}`)\n .join(''),\n );\n return JSON.parse(jsonPayload) as JWTPayload;\n }\n\n isJWTExpired(token: JWTPayload): boolean {\n const now = new Date().getTime() / 1000;\n if (token.exp && now > token.exp) {\n return true;\n }\n return false;\n }\n\n saveToken(token: string, type: TokenType = 'access'): boolean {\n if (type === 'access') {\n this.isAuth = true;\n }\n return this.tokenManager.saveToken(token, type);\n }\n\n removeToken(type: TokenType = 'access'): void {\n if (type === 'access') {\n this.isAuth = false;\n }\n this.tokenManager.deleteToken(type);\n }\n\n getToken(type: TokenType = 'access'): ClientToken | null {\n const token = this.tokenManager.getToken(type);\n if (!token) return null;\n const jwtPayload = this.parseJWT(token);\n return { token, payload: jwtPayload };\n }\n}\n\nexport default TokenService;\n","import { IdentifoConfig, UrlFlows } from './types/types';\n\nexport class UrlBuilder {\n constructor(private config: IdentifoConfig) {}\n\n getUrl(flow: UrlFlows): string {\n const scopes = this.config.scopes?.join() || '';\n const redirectUri = this.config.redirectUri ?? window.location.href;\n const baseParams = `appId=${this.config.appId}&scopes=${scopes}`;\n const urlParams = `${baseParams}&callbackUrl=${encodeURIComponent(redirectUri)}`;\n // if postLogoutRedirectUri is empty, login url will be instead\n const postLogoutRedirectUri = this.config.postLogoutRedirectUri\n ? `${this.config.postLogoutRedirectUri}`\n : `${redirectUri}&redirectUri=${this.config.url}/web/login?${encodeURIComponent(baseParams)}`;\n\n const urls = {\n signup: `${this.config.url}/web/register?${urlParams}`,\n signin: `${this.config.url}/web/login?${urlParams}`,\n logout: `${this.config.url}/web/logout?${baseParams}&callbackUrl=${encodeURIComponent(postLogoutRedirectUri)}`,\n renew: `${this.config.url}/web/token/renew?${baseParams}&redirectUri=${encodeURIComponent(redirectUri)}`,\n default: 'default',\n };\n\n return urls[flow] || urls.default;\n }\n\n createSignupUrl(): string {\n return this.getUrl('signup');\n }\n\n createSigninUrl(): string {\n return this.getUrl('signin');\n }\n\n createLogoutUrl(): string {\n return this.getUrl('logout');\n }\n\n createRenewSessionUrl(): string {\n return this.getUrl('renew');\n }\n}\n","import { API } from './api/api';\nimport { jwtRegex, REFRESH_TOKEN_QUERY_KEY, TOKEN_QUERY_KEY } from './constants';\nimport TokenService from './tokenService';\nimport { ClientToken, IdentifoConfig, UrlBuilderInit } from './types/types';\nimport { UrlBuilder } from './UrlBuilder';\n\nclass IdentifoAuth {\n public api!: API;\n\n public tokenService!: TokenService;\n\n public config!: IdentifoConfig;\n\n public urlBuilder!: UrlBuilderInit;\n\n private token: ClientToken | null = null;\n\n get isAuth(): boolean {\n return !!this.tokenService?.isAuth;\n }\n\n constructor(config?: IdentifoConfig) {\n if (config) {\n this.configure(config);\n }\n }\n\n public configure(config: IdentifoConfig): void {\n this.config = { ...config, autoRenew: config.autoRenew ?? true };\n this.tokenService = new TokenService(config.tokenManager);\n this.urlBuilder = new UrlBuilder(this.config);\n this.api = new API(config, this.tokenService);\n this.handleToken(this.tokenService.getToken()?.token || '', 'access');\n }\n\n private handleToken(token: string, tokenType: 'access' | 'refresh') {\n if (token) {\n if (tokenType === 'access') {\n const payload = this.tokenService.parseJWT(token);\n this.token = { token, payload };\n this.tokenService.saveToken(token);\n } else {\n this.tokenService.saveToken(token, 'refresh');\n }\n }\n }\n\n private resetAuthValues() {\n this.token = null;\n this.tokenService.removeToken();\n this.tokenService.removeToken('refresh');\n }\n\n signup(): void {\n window.location.href = this.urlBuilder.createSignupUrl();\n }\n\n signin(): void {\n window.location.href = this.urlBuilder.createSigninUrl();\n }\n\n logout(): void {\n this.resetAuthValues();\n window.location.href = this.urlBuilder.createLogoutUrl();\n }\n\n async handleAuthentication(): Promise {\n const { access, refresh } = this.getTokenFromUrl();\n if (!access) {\n this.resetAuthValues();\n return Promise.reject();\n }\n try {\n await this.tokenService.handleVerification(access, this.config.appId, this.config.issuer);\n this.handleToken(access, 'access');\n if (refresh) {\n this.handleToken(refresh, 'refresh');\n }\n return await Promise.resolve(true);\n } catch (err) {\n this.resetAuthValues();\n return await Promise.reject();\n } finally {\n window.history.pushState({}, document.title, window.location.pathname);\n }\n }\n\n private getTokenFromUrl(): { access: string; refresh: string } {\n const urlParams = new URLSearchParams(window.location.search);\n const tokens = { access: '', refresh: '' };\n const accessToken = urlParams.get(TOKEN_QUERY_KEY);\n const refreshToken = urlParams.get(REFRESH_TOKEN_QUERY_KEY);\n if (refreshToken && jwtRegex.test(refreshToken)) {\n tokens.refresh = refreshToken;\n }\n if (accessToken && jwtRegex.test(accessToken)) {\n tokens.access = accessToken;\n }\n return tokens;\n }\n\n async getToken(): Promise {\n const token = this.tokenService.getToken();\n const refreshToken = this.tokenService.getToken('refresh');\n if (token) {\n const isExpired = this.tokenService.isJWTExpired(token.payload);\n if (isExpired && refreshToken) {\n try {\n await this.renewSession();\n return await Promise.resolve(this.token);\n } catch (err) {\n this.resetAuthValues();\n throw new Error('No token');\n }\n }\n return Promise.resolve(token);\n }\n return Promise.resolve(null);\n }\n\n async renewSession(): Promise {\n try {\n const { access, refresh } = await this.renewSessionWithToken();\n this.handleToken(access, 'access');\n this.handleToken(refresh, 'refresh');\n return await Promise.resolve(access);\n } catch (err) {\n return Promise.reject();\n }\n }\n\n private async renewSessionWithToken(): Promise<{ access: string; refresh: string }> {\n try {\n const tokens = await this.api\n .renewToken()\n .then((l) => ({ access: l.access_token || '', refresh: l.refresh_token || '' }));\n return tokens;\n } catch (err) {\n return Promise.reject(err);\n }\n }\n}\nexport default IdentifoAuth;\n","import {\n ApiError,\n FederatedLoginProvider,\n LoginResponse,\n ServerSettingsLoginTypes,\n TFAStatus,\n TFAType,\n SuccessResponse,\n} from '../api/model';\n\nexport enum Routes {\n 'LOGIN' = 'login',\n 'REGISTER' = 'register',\n 'TFA_VERIFY_SMS' = 'tfa/verify/sms',\n 'TFA_VERIFY_EMAIL' = 'tfa/verify/email',\n 'TFA_VERIFY_APP' = 'tfa/verify/app',\n 'TFA_VERIFY_SELECT' = 'tfa/verify/select',\n 'TFA_SETUP_SMS' = 'tfa/setup/sms',\n 'TFA_SETUP_EMAIL' = 'tfa/setup/email',\n 'TFA_SETUP_APP' = 'tfa/setup/app',\n 'TFA_SETUP_SELECT' = 'tfa/setup/select',\n 'PASSWORD_RESET' = 'password/reset',\n 'PASSWORD_FORGOT' = 'password/forgot',\n 'PASSWORD_FORGOT_TFA_SMS' = 'password/forgot/tfa/sms',\n 'PASSWORD_FORGOT_TFA_EMAIL' = 'password/forgot/tfa/email',\n 'PASSWORD_FORGOT_TFA_APP' = 'password/forgot/tfa/app',\n 'PASSWORD_FORGOT_TFA_SELECT' = 'password/forgot/tfa/select',\n 'CALLBACK' = 'callback',\n 'LOGIN_PHONE' = 'login_phone',\n 'LOGIN_OIDC' = 'login_oidc',\n 'LOGIN_PHONE_VERIFY' = 'login_phone_verify',\n 'ERROR' = 'error',\n 'PASSWORD_FORGOT_SUCCESS' = 'password/forgot/success',\n 'LOGOUT' = 'logout',\n 'LOADING' = 'loading',\n}\n\nexport type TFASetupRoutes =\n | Routes.TFA_SETUP_SELECT\n | Routes.TFA_SETUP_SMS\n | Routes.TFA_SETUP_EMAIL\n | Routes.TFA_SETUP_APP;\nexport type TFALoginVerifyRoutes =\n | Routes.TFA_VERIFY_SELECT\n | Routes.TFA_VERIFY_SMS\n | Routes.TFA_VERIFY_EMAIL\n | Routes.TFA_VERIFY_APP;\nexport type TFAResetVerifyRoutes =\n | Routes.PASSWORD_FORGOT_TFA_SELECT\n | Routes.PASSWORD_FORGOT_TFA_SMS\n | Routes.PASSWORD_FORGOT_TFA_EMAIL\n | Routes.PASSWORD_FORGOT_TFA_APP;\n\nexport interface State {\n route: Routes;\n}\n\nexport interface StateWithError {\n error?: ApiError;\n}\n\nexport type LoginTypes = Partial<\n Record void; type: keyof ServerSettingsLoginTypes }>\n>;\n\nexport interface StateLogin extends State, StateWithError {\n route: Routes.LOGIN;\n registrationForbidden: boolean;\n federatedProviders: FederatedLoginProvider[];\n loginTypes: LoginTypes;\n signup: () => Promise;\n signin: (email: string, password: string, remember?: boolean) => Promise;\n socialLogin: (provider: FederatedLoginProvider) => Promise;\n passwordForgot: () => Promise;\n}\n\nexport interface StateLoginOidc extends State, StateWithError {\n route: Routes.LOGIN_OIDC;\n oidcLink: string;\n verify: (state?: string, code?: string) => Promise;\n}\n\nexport interface StateLoginPhone extends State, StateWithError {\n route: Routes.LOGIN_PHONE;\n registrationForbidden: boolean;\n federatedProviders: FederatedLoginProvider[];\n loginTypes: LoginTypes;\n requestCode: (phone: string) => Promise;\n socialLogin: (provider: FederatedLoginProvider) => Promise;\n}\nexport interface StateLoginPhoneVerify extends State, StateWithError {\n route: Routes.LOGIN_PHONE_VERIFY;\n phone: string;\n resendTimeout: number;\n resendCode: () => Promise;\n login: (code: string) => Promise;\n goback: () => Promise;\n}\n\nexport interface StateRegister extends State, StateWithError {\n route: Routes.REGISTER;\n signup: (email: string, password: string, token?: string) => Promise;\n goback: () => Promise;\n}\n\nexport interface StatePasswordForgot extends State, StateWithError {\n route: Routes.PASSWORD_FORGOT;\n restorePassword: (email: string) => Promise;\n goback: () => Promise;\n}\nexport interface StatePasswordForgotSuccess extends State {\n route: Routes.PASSWORD_FORGOT_SUCCESS;\n goback: () => Promise;\n}\n\nexport interface StateError extends State, StateWithError {\n route: Routes.ERROR;\n}\n\nexport interface StateCallback extends State {\n route: Routes.CALLBACK;\n callbackUrl?: string;\n result: LoginResponse;\n}\n\nexport interface StatePasswordReset extends State, StateWithError {\n route: Routes.PASSWORD_RESET;\n setNewPassword: (password: string) => Promise;\n}\n\nexport interface StateLoading extends State {\n route: Routes.LOADING;\n}\n\ninterface StateTFASetup extends State, StateWithError {}\n\nexport interface StateTFASetupApp extends StateTFASetup {\n route: Routes.TFA_SETUP_APP;\n provisioningURI: string;\n provisioningQR: string;\n setupTFA: () => Promise;\n}\nexport interface StateTFASetupEmail extends StateTFASetup {\n route: Routes.TFA_SETUP_EMAIL;\n email: string;\n setupTFA: (email: string) => Promise;\n}\nexport interface StateTFASetupSMS extends StateTFASetup {\n route: Routes.TFA_SETUP_SMS;\n phone: string;\n setupTFA: (phone: string) => Promise;\n}\n\ninterface StateTFASelect extends State {\n tfaTypes: TFAType[];\n select: (type: TFAType) => Promise;\n email?: string;\n phone?: string;\n}\n\nexport interface StateTFASetupSelect extends StateTFASelect {\n route: Routes.TFA_SETUP_SELECT;\n tfaStatus: TFAStatus;\n setupNextTime: () => Promise;\n}\nexport interface StateTFAVerifySelect extends StateTFASelect {\n route: Routes.TFA_VERIFY_SELECT;\n}\nexport interface StatePasswordForgotTFASelect extends StateTFASelect {\n route: Routes.PASSWORD_FORGOT_TFA_SELECT;\n}\n\nexport interface StateTFAVerifyApp extends State, StateWithError {\n route: Routes.TFA_VERIFY_APP;\n email?: string;\n phone?: string;\n verifyTFA: (code: string) => Promise;\n}\n\nexport interface StateTFAVerifyEmailSms extends State, StateWithError {\n route: Routes.TFA_VERIFY_EMAIL | Routes.TFA_VERIFY_SMS;\n email?: string;\n phone?: string;\n resendTimeout: number;\n verifyTFA: (code: string) => Promise;\n resendTFA: () => Promise;\n}\n\nexport interface StatePasswordForgotTFAVerify extends State, StateWithError {\n route: Routes.PASSWORD_FORGOT_TFA_APP | Routes.PASSWORD_FORGOT_TFA_EMAIL | Routes.PASSWORD_FORGOT_TFA_SMS;\n email?: string;\n phone?: string;\n verifyTFA: (code: string) => Promise;\n}\n\nexport interface StateLogout extends State {\n route: Routes.LOGOUT;\n logout: () => Promise;\n}\n\nexport const typeToSetupRoute = {\n [TFAType.TFATypeApp]: Routes.TFA_SETUP_APP,\n [TFAType.TFATypeEmail]: Routes.TFA_SETUP_EMAIL,\n [TFAType.TFATypeSMS]: Routes.TFA_SETUP_SMS,\n};\n\nexport const typeToTFAVerifyRoute = {\n [TFAType.TFATypeApp]: Routes.TFA_VERIFY_APP,\n [TFAType.TFATypeEmail]: Routes.TFA_VERIFY_EMAIL,\n [TFAType.TFATypeSMS]: Routes.TFA_VERIFY_SMS,\n};\nexport const typeToPasswordForgotTFAVerifyRoute = {\n [TFAType.TFATypeApp]: Routes.PASSWORD_FORGOT_TFA_APP,\n [TFAType.TFATypeEmail]: Routes.PASSWORD_FORGOT_TFA_EMAIL,\n [TFAType.TFATypeSMS]: Routes.PASSWORD_FORGOT_TFA_SMS,\n};\n\n// TODO exclude generalState\nexport type States =\n | State\n | StateTFASetupApp\n | StateTFASetupEmail\n | StateTFASetupSMS\n | StatePasswordReset\n | StatePasswordForgot\n | StatePasswordForgotSuccess\n | StateLoading\n | StateCallback\n | StateLogin\n | StateRegister\n | StateError\n | StateLoginOidc;\n","import { BehaviorSubject } from 'rxjs';\nimport { StateLoginPhone, StateLoginPhoneVerify } from '..';\nimport {\n ApiError,\n APIErrorCodes,\n AppSettingsResponse,\n FederatedLoginProvider,\n LoginResponse,\n ServerSettingsLoginTypes,\n TFAStatus,\n TFAType,\n} from '../api/model';\nimport IdentifoAuth from '../IdentifoAuth';\nimport { IdentifoConfig } from '../types/types';\nimport {\n LoginTypes,\n Routes,\n State,\n StateCallback,\n StateError,\n StateLoginOidc,\n StateLogout,\n StatePasswordForgotTFASelect,\n StatePasswordForgotTFAVerify,\n States,\n StateTFASetupSelect,\n StateTFAVerifyApp,\n StateTFAVerifyEmailSms,\n StateTFAVerifySelect,\n StateWithError,\n typeToPasswordForgotTFAVerifyRoute,\n typeToTFAVerifyRoute,\n} from './model';\n\nconst emailRegex =\n // eslint-disable-next-line max-len\n /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\nconst phoneRegex = /^[\\+][0-9]{9,15}$/;\n\nexport class CDK {\n auth: IdentifoAuth;\n\n settings!: AppSettingsResponse;\n\n lastError!: ApiError;\n\n callbackUrl?: string;\n\n postLogoutRedirectUri?: string;\n\n scopes: Set = new Set();\n\n state: BehaviorSubject = new BehaviorSubject({ route: Routes.LOADING } as States);\n\n constructor() {\n this.auth = new IdentifoAuth();\n }\n\n // eslint-disable-next-line max-statements\n async configure(authConfig: IdentifoConfig, callbackUrl: string): Promise {\n this.state.next({ route: Routes.LOADING });\n\n this.callbackUrl = callbackUrl;\n this.scopes = new Set(authConfig.scopes ?? []);\n\n this.postLogoutRedirectUri = window.location.origin + window.location.pathname;\n // this.postLogoutRedirectUri = this.postLogoutRedirectUri || window.location.origin + window.location.pathname;\n\n if (!authConfig.appId) {\n this.state.next({\n route: Routes.ERROR,\n error: { message: 'app-id param is empty', name: 'app-id empty' },\n } as StateError);\n return;\n }\n if (!authConfig.url) {\n this.state.next({\n route: Routes.ERROR,\n error: { message: 'url param is empty', name: 'url empty' },\n } as StateError);\n return;\n }\n\n this.auth.configure(authConfig);\n try {\n this.settings = await this.auth.api.getAppSettings(callbackUrl);\n } catch (err) {\n this.state.next({\n route: Routes.ERROR,\n error: err as ApiError,\n } as StateError);\n return;\n }\n this.settings.tfaType = Array.isArray(this.settings.tfaType) ? this.settings.tfaType : [this.settings.tfaType];\n\n // // If we have provider and state then we need to complete federated login\n const href = new URL(window.location.href);\n if (!!href.searchParams.get('provider') && !!href.searchParams.get('state')) {\n // Also we clear all url params after parsing\n const u = new URL(window.location.href);\n const sp = new URLSearchParams();\n const appId = href.searchParams.get('appId');\n if (appId === null) {\n this.state.next({\n route: Routes.ERROR,\n error: { message: 'app-id param is empty', name: 'app-id empty' },\n } as StateError);\n return;\n }\n sp.set('appId', appId);\n window.history.replaceState({}, document.title, `${u.pathname}?${sp.toString()}`);\n this.auth.api\n .federatedLoginComplete(u.searchParams)\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n }\n }\n\n login(): void {\n // check for allowed login with\n switch (true) {\n case (!this.auth.config.loginWith && this.settings.loginWith['phone']) ||\n (this.auth.config.loginWith === 'phone' && this.settings.loginWith['phone']):\n return this.loginWithPhone();\n case (!this.auth.config.loginWith && this.settings.loginWith['email']) ||\n (this.auth.config.loginWith === 'email' && this.settings.loginWith['email']):\n return this.loginWithPassword();\n case (!this.auth.config.loginWith && this.settings.loginWith['federated_oidc']) ||\n (this.auth.config.loginWith === 'federated_oidc' && this.settings.loginWith['federated_oidc']):\n return this.loginWithOIDC();\n default:\n throw 'Unsupported login way';\n }\n }\n loginWithPhone(): void {\n this.state.next({\n route: Routes.LOGIN_PHONE,\n registrationForbidden: this.settings?.registrationForbidden,\n error: this.lastError,\n federatedProviders: this.settings?.federatedProviders,\n loginTypes: this.getLoginTypes('phone'),\n requestCode: async (phone: string, remember?: boolean): Promise => {\n if (!this.validatePhone(phone)) {\n return;\n }\n const scopes = new Set(this.scopes);\n if (remember) {\n scopes.add('offline');\n }\n await this.auth.api\n .requestPhoneCode(phone)\n .then(() => this.loginWithPhoneVerify(phone, remember))\n .catch((e) => this.processError(e));\n },\n socialLogin: async (provider: FederatedLoginProvider) => {\n this.state.next({ route: Routes.LOADING });\n const federatedRedirectUrl = window.location.origin + window.location.pathname;\n return this.auth.api.federatedLogin(\n provider,\n [...Array.from(this.scopes)],\n federatedRedirectUrl,\n this.callbackUrl,\n );\n },\n } as StateLoginPhone);\n }\n loginWithPhoneVerify(phone: string, remember?: boolean): void {\n this.state.next({\n route: Routes.LOGIN_PHONE_VERIFY,\n error: this.lastError,\n phone: phone,\n resendTimeout: this.settings.tfaResendTimeout * 1000,\n resendCode: async () => {\n await this.auth.api.requestPhoneCode(phone);\n },\n login: async (code: string): Promise => {\n const scopes = new Set(this.scopes);\n if (remember) {\n scopes.add('offline');\n }\n await this.auth.api\n .phoneLogin(phone, code, [...Array.from(this.scopes)])\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n goback: async (): Promise => {\n this.login();\n },\n } as StateLoginPhoneVerify);\n }\n\n loginWithOIDC(): void {\n this.state.next({\n route: Routes.LOGIN_OIDC,\n oidcLink: this.settings.federatedOIDCInitURL,\n error: this.lastError,\n verify: async (state?: string, code?: string) => {\n if (!state || !code) {\n return;\n }\n this.auth.api\n .oidcVerify({ state, code, scopes: [...Array.from(this.scopes)] })\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n } as StateLoginOidc);\n }\n\n loginWithPassword(): void {\n this.state.next({\n route: Routes.LOGIN,\n registrationForbidden: this.settings?.registrationForbidden,\n error: this.lastError,\n federatedProviders: this.settings?.federatedProviders,\n loginTypes: this.getLoginTypes('email'),\n signup: async (): Promise => {\n this.register();\n },\n signin: async (email: string, password: string, remember?: boolean): Promise => {\n if (!this.validateEmail(email)) {\n return;\n }\n const scopes = new Set(this.scopes);\n if (remember) {\n scopes.add('offline');\n }\n await this.auth.api\n .login(email, password, '', [...Array.from(scopes)])\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n socialLogin: async (provider: FederatedLoginProvider) => {\n this.state.next({ route: Routes.LOADING });\n const federatedRedirectUrl = window.location.origin + window.location.pathname;\n return this.auth.api.federatedLogin(\n provider,\n [...Array.from(this.scopes)],\n federatedRedirectUrl,\n this.callbackUrl,\n );\n },\n passwordForgot: async () => {\n this.forgotPassword();\n },\n });\n }\n\n register(): void {\n this.state.next({\n route: Routes.REGISTER,\n signup: async (email: string, password: string, token?: string): Promise => {\n if (!this.validateEmail(email)) {\n return;\n }\n await this.auth.api\n .register(email, password, [...Array.from(this.scopes)], token)\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n\n forgotPassword(): void {\n this.state.next({\n route: Routes.PASSWORD_FORGOT,\n restorePassword: async (email: string): Promise => {\n return this.auth.api\n .requestResetPassword(email)\n .then(async (response) => {\n if (response.result === 'tfa-required') {\n await this.redirectTfaForgot(email);\n return;\n }\n if (response.result === 'ok') {\n this.forgotPasswordSuccess();\n }\n })\n .catch((e) => this.processError(e));\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n\n forgotPasswordSuccess(): void {\n this.state.next({\n route: Routes.PASSWORD_FORGOT_SUCCESS,\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n\n passwordReset(): void {\n this.state.next({\n route: Routes.PASSWORD_RESET,\n setNewPassword: async (password: string): Promise => {\n this.auth.api\n .resetPassword(password)\n .then(() => {\n this.login();\n })\n .catch((e) => this.processError(e));\n },\n });\n }\n\n callback(result: LoginResponse): void {\n this.state.next({\n route: Routes.CALLBACK,\n callbackUrl: this.callbackUrl,\n result,\n } as StateCallback);\n if (this.callbackUrl) {\n const url = new URL(this.callbackUrl);\n if (result.access_token) {\n url.searchParams.set('token', result.access_token);\n }\n if (result.refresh_token) {\n url.searchParams.set('refresh_token', result.refresh_token);\n }\n window.location.href = url.toString();\n }\n }\n\n validateEmail(email: string): boolean {\n if (!emailRegex.test(email)) {\n this.processError({\n detailedMessage: 'Email address is not valid',\n name: 'Validation error',\n message: 'Email address is not valid',\n } as ApiError);\n return false;\n }\n return true;\n }\n\n validatePhone(email: string): boolean {\n if (!phoneRegex.test(email)) {\n this.processError({\n detailedMessage: 'Phone is not valid',\n name: 'Validation error',\n message: 'Phone is not valid',\n } as ApiError);\n return false;\n }\n return true;\n }\n\n async tfaSetup(loginResponse: LoginResponse, type: TFAType): Promise {\n switch (type) {\n case TFAType.TFATypeApp: {\n this.state.next({\n route: Routes.TFA_SETUP_APP,\n provisioningURI: '',\n provisioningQR: '',\n setupTFA: async () => {},\n goback: async (): Promise => {\n this.login();\n },\n });\n const tfa = await this.auth.api.enableTFA({});\n if (tfa.provisioning_uri) {\n this.state.next({\n route: Routes.TFA_SETUP_APP,\n provisioningURI: tfa.provisioning_uri,\n provisioningQR: tfa.provisioning_qr || '',\n setupTFA: async () => this.tfaVerify(loginResponse, type),\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n break;\n }\n case TFAType.TFATypeEmail: {\n this.state.next({\n route: Routes.TFA_SETUP_EMAIL,\n email: loginResponse.user.email || '',\n setupTFA: async (email: string) => {\n await this.auth.api.enableTFA({ email });\n return this.tfaVerify({ ...loginResponse, user: { ...loginResponse.user, email } }, type);\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n break;\n }\n case TFAType.TFATypeSMS: {\n this.state.next({\n route: Routes.TFA_SETUP_SMS,\n phone: loginResponse.user.phone || '',\n setupTFA: async (phone: string) => {\n await this.auth.api.enableTFA({ phone });\n return this.tfaVerify({ ...loginResponse, user: { ...loginResponse.user, phone } }, type);\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n break;\n }\n default:\n }\n }\n\n async tfaVerify(loginResponse: LoginResponse, type: TFAType): Promise {\n const state = {\n route: typeToTFAVerifyRoute[type],\n email: loginResponse.user.email,\n phone: loginResponse.user.phone,\n verifyTFA: async (code: string) => {\n await this.auth.api\n .verifyTFA(code, [...Array.from(this.scopes)])\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n };\n switch (type) {\n case TFAType.TFATypeApp: {\n this.state.next({ ...state } as StateTFAVerifyApp);\n break;\n }\n case TFAType.TFATypeEmail:\n case TFAType.TFATypeSMS: {\n this.state.next({\n ...state,\n resendTimeout: this.settings.tfaResendTimeout * 1000, // in ms\n resendTFA: async () => {\n await this.auth.api.resendTFA();\n },\n } as StateTFAVerifyEmailSms);\n break;\n }\n default:\n }\n }\n\n async passwordForgotTFAVerify(email: string, type: TFAType): Promise {\n this.state.next({\n route: typeToPasswordForgotTFAVerifyRoute[type],\n verifyTFA: async (code: string) => {\n this.auth.api\n .requestResetPassword(email, code)\n .then(() => {\n this.forgotPasswordSuccess();\n })\n .catch((e) => this.processError(e));\n },\n } as StatePasswordForgotTFAVerify);\n }\n\n async logout(): Promise {\n this.state.next({\n route: Routes.LOGOUT,\n logout: async () => this.auth.api.logout(),\n } as StateLogout);\n }\n\n // restorePassword(token: string): void {}\n\n private processError(e: ApiError) {\n e.detailedMessage = e.detailedMessage?.trim();\n e.message = e.message?.trim();\n\n this.state.next({\n ...this.state.getValue(),\n error: e,\n } as State & StateWithError);\n }\n\n private async redirectTfaSetup(loginResponse: LoginResponse): Promise {\n if (this.settings.tfaType.length === 1) {\n await this.tfaSetup(loginResponse, this.settings.tfaType[0] as TFAType);\n return;\n }\n this.tfaSetupSelect(loginResponse);\n }\n\n private tfaSetupSelect(loginResponse: LoginResponse): void {\n this.state.next({\n route: Routes.TFA_SETUP_SELECT,\n tfaStatus: this.settings.tfaStatus,\n tfaTypes: this.settings.tfaType,\n select: async (type: TFAType) => {\n await this.tfaSetup(loginResponse, type);\n },\n setupNextTime: () => {\n this.callback(loginResponse);\n },\n } as StateTFASetupSelect);\n }\n\n private async redirectTfaVerify(e: LoginResponse): Promise {\n if (this.settings.tfaType.length === 1) {\n await this.tfaVerify(e, this.settings.tfaType[0] as TFAType);\n return;\n }\n this.state.next({\n route: Routes.TFA_VERIFY_SELECT,\n tfaStatus: this.settings.tfaStatus,\n tfaTypes: this.settings.tfaType,\n select: async (type: TFAType) => {\n await this.tfaVerify(e, type);\n },\n } as StateTFAVerifySelect);\n }\n\n private async redirectTfaForgot(email: string): Promise {\n if (this.settings.tfaType.length === 1) {\n await this.passwordForgotTFAVerify(email, this.settings.tfaType[0] as TFAType);\n return;\n }\n this.state.next({\n route: Routes.PASSWORD_FORGOT_TFA_SELECT,\n tfaStatus: this.settings.tfaStatus,\n tfaTypes: this.settings.tfaType,\n select: async (type: TFAType) => {\n await this.passwordForgotTFAVerify(email, type);\n },\n } as StatePasswordForgotTFASelect);\n }\n\n // eslint-disable-next-line complexity\n private afterLoginRedirect = async (loginResponse: LoginResponse): Promise => {\n if (loginResponse.require_2fa) {\n if (!loginResponse.enabled_2fa) {\n await this.redirectTfaSetup(loginResponse);\n return;\n }\n if (loginResponse.enabled_2fa) {\n await this.redirectTfaVerify(loginResponse);\n return;\n }\n }\n // Ask about tfa on login only\n if (\n this.settings.tfaStatus === TFAStatus.OPTIONAL &&\n [Routes.LOGIN, Routes.REGISTER].includes(this.state.getValue().route)\n ) {\n this.tfaSetupSelect(loginResponse);\n return;\n }\n if (loginResponse.access_token && loginResponse.refresh_token) {\n this.callback(loginResponse);\n return;\n }\n if (loginResponse.access_token && !loginResponse.refresh_token) {\n this.callback(loginResponse);\n return;\n }\n this.login();\n };\n\n private loginCatchRedirect = (data: ApiError): void => {\n if (data.id === APIErrorCodes.PleaseEnableTFA) {\n // this.redirectTfaSetup();\n return;\n }\n throw data;\n };\n private getLoginTypes(current: keyof ServerSettingsLoginTypes): LoginTypes {\n const result: LoginTypes = {};\n Object.entries(this.settings.loginWith)\n .filter((v) => v[1] && v[0] !== current)\n .forEach((v) => {\n result[v[0] as keyof ServerSettingsLoginTypes] = {\n type: v[0] as keyof ServerSettingsLoginTypes,\n click: () => {\n this.auth.config.loginWith = v[0] as keyof ServerSettingsLoginTypes;\n this.login();\n },\n };\n });\n return result;\n }\n}\n"],"names":["APIErrorCodes","TFAType","TFAStatus","__async","__spreadValues","LocalStorageManager","__spreadProps","Routes","BehaviorSubject"],"mappings":"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"} \ No newline at end of file diff --git a/web_apps_src/identifo.js/dist/identifo.mjs b/web_apps_src/identifo.js/dist/identifo.mjs index daca6a9a..2d639001 100644 --- a/web_apps_src/identifo.js/dist/identifo.mjs +++ b/web_apps_src/identifo.js/dist/identifo.mjs @@ -308,6 +308,12 @@ class API { }); }); } + oidcVerify(data) { + return __async$3(this, null, function* () { + const url = `/auth/federated/oidc/complete?appId=${this.appId}&state=${data.state}&code=${data.code}`; + return this.post(url, { scopes: data.scopes }, { credentials: "include" }).then((r) => this.storeToken(r)); + }); + } invite(email, role, callbackUrl) { return __async$3(this, null, function* () { var _a, _b; @@ -699,6 +705,7 @@ var Routes; Routes2["PASSWORD_FORGOT_TFA_SELECT"] = "password/forgot/tfa/select"; Routes2["CALLBACK"] = "callback"; Routes2["LOGIN_PHONE"] = "login_phone"; + Routes2["LOGIN_OIDC"] = "login_oidc"; Routes2["LOGIN_PHONE_VERIFY"] = "login_phone_verify"; Routes2["ERROR"] = "error"; Routes2["PASSWORD_FORGOT_SUCCESS"] = "password/forgot/success"; @@ -855,6 +862,8 @@ class CDK { return this.loginWithPhone(); case (!this.auth.config.loginWith && this.settings.loginWith["email"] || this.auth.config.loginWith === "email" && this.settings.loginWith["email"]): return this.loginWithPassword(); + case (!this.auth.config.loginWith && this.settings.loginWith["federated_oidc"] || this.auth.config.loginWith === "federated_oidc" && this.settings.loginWith["federated_oidc"]): + return this.loginWithOIDC(); default: throw "Unsupported login way"; } @@ -905,6 +914,19 @@ class CDK { }) }); } + loginWithOIDC() { + this.state.next({ + route: Routes.LOGIN_OIDC, + oidcLink: this.settings.federatedOIDCInitURL, + error: this.lastError, + verify: (state, code) => __async(this, null, function* () { + if (!state || !code) { + return; + } + this.auth.api.oidcVerify({ state, code, scopes: [...Array.from(this.scopes)] }).then(this.afterLoginRedirect).catch(this.loginCatchRedirect).catch((e) => this.processError(e)); + }) + }); + } loginWithPassword() { var _a, _b; this.state.next({ diff --git a/web_apps_src/identifo.js/dist/identifo.mjs.map b/web_apps_src/identifo.js/dist/identifo.mjs.map index e81a38e8..bc330f28 100644 --- a/web_apps_src/identifo.js/dist/identifo.mjs.map +++ b/web_apps_src/identifo.js/dist/identifo.mjs.map @@ -1 +1 @@ -{"version":3,"file":"identifo.mjs","sources":["../src/api/model.ts","../src/api/api.ts","../src/constants.ts","../src/store-manager/cookie-storage.ts","../src/store-manager/storage-manager.ts","../src/store-manager/local-storage.ts","../src/store-manager/session-storage.ts","../src/tokenService.ts","../src/UrlBuilder.ts","../src/IdentifoAuth.ts","../src/cdk/model.ts","../src/cdk/cdk.ts"],"sourcesContent":["/* eslint-disable camelcase */\nexport enum APIErrorCodes {\n PleaseEnableTFA = 'error.api.request.2fa.please_enable',\n InvalidCallbackURL = 'error.api.request.callbackurl.invalid',\n NetworkError = 'error.network',\n}\n\nexport enum TFAType {\n TFATypeApp = 'app',\n TFATypeSMS = 'sms',\n TFATypeEmail = 'email',\n}\n\nexport enum TFAStatus {\n DISABLED = 'disabled',\n OPTIONAL = 'optional',\n MANDATORY = 'mandatory',\n}\n\nexport interface ServerSettingsLoginTypes {\n email: boolean;\n federated: boolean;\n phone: boolean;\n username: boolean;\n}\n\nexport type FederatedLoginProvider = 'apple' | 'google' | 'facebook';\nexport interface ApiRequestError {\n error: {\n detailed_message?: string;\n id?: APIErrorCodes;\n message?: string;\n status?: number;\n };\n}\nexport class ApiError extends Error {\n detailedMessage?: string;\n\n id?: APIErrorCodes;\n\n status?: number;\n\n constructor(error?: ApiRequestError['error']) {\n super(error?.message || 'Unknown API error');\n this.detailedMessage = error?.detailed_message;\n this.id = error?.id;\n this.status = error?.status;\n }\n}\nexport interface LoginResponse {\n access_token?: string;\n refresh_token?: string;\n require_2fa: boolean;\n enabled_2fa: boolean;\n user: {\n active: boolean;\n email?: string;\n id: string;\n latest_login_time: number;\n num_of_logins: number;\n username?: string;\n tfa_info: { hotp_expired_at: string };\n phone?: string;\n };\n scopes?: string[];\n callbackUrl?: string;\n}\nexport interface EnableTFAResponse {\n provisioning_uri?: string;\n provisioning_qr?: string;\n access_token?: string;\n}\nexport interface TokenResponse {\n access_token?: string;\n refresh_token?: string;\n}\nexport interface AppSettingsResponse {\n anonymousResitrationAllowed: boolean;\n active: boolean;\n description: string;\n id: string;\n newUserDefaultRole: string;\n offline: boolean;\n registrationForbidden: boolean;\n tfaType: TFAType[] | TFAType;\n tfaResendTimeout: number;\n tfaStatus: TFAStatus;\n federatedProviders: FederatedLoginProvider[];\n loginWith: ServerSettingsLoginTypes;\n}\n\nexport interface User {\n id: string;\n username: string;\n email: string;\n phone: string;\n active: boolean;\n tfa_info: {\n is_enabled: boolean;\n };\n num_of_logins: number;\n latest_login_time: number;\n access_role: string;\n anonymous: boolean;\n federated_ids: string[];\n}\nexport interface UpdateUser {\n new_email?: string;\n new_phone?: string;\n}\nexport interface SuccessResponse {\n result: 'ok';\n message?: string;\n}\n\nexport interface InviteResponse {\n result: 'ok';\n link: string;\n}\n\nexport interface TFARequiredRespopnse {\n result: 'tfa-required';\n}\n","import { InviteResponse } from '..';\nimport TokenService from '../tokenService';\nimport { IdentifoConfig } from '../types/types';\nimport {\n AppSettingsResponse,\n EnableTFAResponse,\n LoginResponse,\n SuccessResponse,\n UpdateUser,\n User,\n ApiRequestError,\n ApiError,\n APIErrorCodes,\n FederatedLoginProvider,\n TokenResponse,\n TFARequiredRespopnse,\n} from './model';\n\nconst APP_ID_HEADER_KEY = 'X-Identifo-Clientid';\nconst AUTHORIZATION_HEADER_KEY = 'Authorization';\n\nexport class API {\n baseUrl: string;\n\n appId: string;\n\n defaultHeaders = {\n [APP_ID_HEADER_KEY]: '',\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n };\n\n catchNetworkErrorHandler = (e: TypeError): never => {\n if (\n e.message === 'Network Error' ||\n e.message === 'Failed to fetch' ||\n e.message === 'Preflight response is not successful' ||\n e.message.indexOf('is not allowed by Access-Control-Allow-Origin') > -1\n ) {\n // eslint-disable-next-line no-console\n console.error(e.message);\n throw new ApiError({\n id: APIErrorCodes.NetworkError,\n status: 0,\n message: 'Configuration error',\n detailed_message:\n 'Please check Identifo URL and add \"' +\n `${window.location.protocol}//${window.location.host}\" ` +\n 'to \"REDIRECT URLS\" in Identifo app settings.',\n });\n }\n throw e;\n };\n\n checkStatusCodeAndGetJSON = async (r: Response): Promise => {\n if (!r.ok) {\n const error = (await r.json()) as ApiRequestError;\n throw new ApiError(error?.error);\n }\n return r.json();\n };\n\n constructor(private config: IdentifoConfig, private tokenService: TokenService) {\n // remove trailing slash if exist\n this.baseUrl = config.url.replace(/\\/$/, '');\n this.defaultHeaders[APP_ID_HEADER_KEY] = config.appId;\n this.appId = config.appId;\n }\n\n get(path: string, options?: RequestInit): Promise {\n return this.send(path, { method: 'GET', ...options });\n }\n\n put(path: string, data: unknown, options?: RequestInit): Promise {\n return this.send(path, { method: 'PUT', body: JSON.stringify(data), ...options });\n }\n\n post(path: string, data: unknown, options?: RequestInit): Promise {\n return this.send(path, { method: 'POST', body: JSON.stringify(data), ...options });\n }\n\n send(path: string, options?: RequestInit): Promise {\n const init = { ...options };\n init.credentials = 'include';\n init.headers = {\n ...init.headers,\n ...this.defaultHeaders,\n };\n return fetch(`${this.baseUrl}${path}`, init)\n .catch(this.catchNetworkErrorHandler)\n .then(this.checkStatusCodeAndGetJSON)\n .then((value) => value as T);\n }\n\n async getUser(): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.get('/me', {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n });\n }\n\n async renewToken(): Promise {\n if (!this.tokenService.getToken('refresh')?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/auth/token',\n { scopes: this.config.scopes },\n {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken('refresh')?.token}`,\n },\n },\n ).then((r) => this.storeToken(r));\n }\n\n async updateUser(user: UpdateUser): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.put('/me', user, {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken('access')?.token}`,\n },\n });\n }\n\n async login(email: string, password: string, deviceToken: string, scopes: string[]): Promise {\n const data = {\n email,\n password,\n device_token: deviceToken,\n scopes,\n };\n\n return this.post('/auth/login', data).then((r) => this.storeToken(r));\n }\n\n async requestPhoneCode(phone: string): Promise {\n const data = {\n phone_number: phone,\n };\n\n return this.post('/auth/request_phone_code', data);\n }\n\n async phoneLogin(phone: string, code: string, scopes: string[]): Promise {\n const data = {\n phone_number: phone,\n code,\n scopes,\n };\n\n return this.post('/auth/phone_login', data).then((r) => this.storeToken(r));\n }\n\n // After complete login on provider browser will be redirected to redirectUrl\n // callbackUrl will be stored in sesson and returned after successfull login complete\n async federatedLogin(\n provider: FederatedLoginProvider,\n scopes: string[],\n redirectUrl: string,\n callbackUrl?: string,\n opts: { width?: number; height?: number; popUp?: boolean } = { width: 600, height: 800, popUp: false },\n ): Promise {\n const dataForm = document.createElement('form');\n dataForm.style.display = 'none';\n if (opts.popUp) {\n dataForm.target = 'TargetWindow'; // Make sure the window name is same as this value\n }\n dataForm.method = 'POST';\n const params = new URLSearchParams();\n params.set('appId', this.config.appId);\n params.set('provider', provider);\n params.set('scopes', scopes.join(','));\n params.set('redirectUrl', redirectUrl);\n if (callbackUrl) {\n params.set('callbackUrl', callbackUrl);\n }\n dataForm.action = `${this.baseUrl}/auth/federated?${params.toString()}`;\n\n document.body.appendChild(dataForm);\n\n if (opts.popUp) {\n const left = window.screenX + window.outerWidth / 2 - (opts.width || 600) / 2;\n const top = window.screenY + window.outerHeight / 2 - (opts.height || 800) / 2;\n const postWindow = window.open(\n '',\n 'TargetWindow',\n `status=0,title=0,height=${opts.height},width=${opts.width},top=${top},left=${left},scrollbars=1`,\n );\n if (postWindow) {\n dataForm.submit();\n }\n } else {\n window.location.assign(`${this.baseUrl}/auth/federated?${params.toString()}`);\n // dataForm.submit();\n }\n }\n\n async federatedLoginComplete(params: URLSearchParams): Promise {\n return this.get(`/auth/federated/complete?${params.toString()}`).then((r) => this.storeToken(r));\n }\n\n async register(email: string, password: string, scopes: string[], invite?: string): Promise {\n const data: Record = {\n email,\n password,\n scopes,\n };\n\n if (invite) {\n data.invite = invite;\n }\n\n return this.post('/auth/register', data).then((r) => this.storeToken(r));\n }\n\n async requestResetPassword(email: string, tfaCode?: string): Promise {\n const data = {\n email,\n tfa_code: tfaCode,\n };\n\n return this.post('/auth/request_reset_password', data);\n }\n\n async resetPassword(password: string): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n const data = {\n password,\n };\n\n return this.post('/auth/reset_password', data, {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n });\n }\n\n async getAppSettings(callbackUrl: string): Promise {\n return this.get(`/auth/app_settings?${new URLSearchParams({ callbackUrl }).toString()}`);\n }\n\n async enableTFA(data: { phone?: string; email?: string }): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.put('/auth/tfa/enable', data, {\n headers: { [AUTHORIZATION_HEADER_KEY]: `BEARER ${this.tokenService.getToken()?.token}` },\n }).then((r) => this.storeToken(r));\n }\n\n async verifyTFA(code: string, scopes: string[]): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/auth/tfa/login',\n { tfa_code: code, scopes },\n { headers: { [AUTHORIZATION_HEADER_KEY]: `BEARER ${this.tokenService.getToken()?.token}` } },\n ).then((r) => this.storeToken(r));\n }\n\n async resendTFA(): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post('/auth/tfa/resend', null, {\n headers: { [AUTHORIZATION_HEADER_KEY]: `BEARER ${this.tokenService.getToken()?.token}` },\n }).then((r) => this.storeToken(r));\n }\n\n async logout(): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/me/logout',\n {\n refresh_token: this.tokenService.getToken('refresh')?.token,\n },\n {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n },\n ).then((r) => {\n this.tokenService.removeToken();\n this.tokenService.removeToken('refresh');\n return r;\n });\n }\n\n async invite(email: string, role: string, callbackUrl: string): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/auth/invite',\n {\n email,\n access_role: role,\n callback_url: callbackUrl,\n },\n {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n },\n );\n }\n\n storeToken(response: T): T {\n if (response.access_token) {\n this.tokenService.saveToken(response.access_token, 'access');\n }\n if (response.refresh_token) {\n this.tokenService.saveToken(response.refresh_token, 'refresh');\n }\n return response;\n }\n}\n","export const jwtRegex = /^([a-zA-Z0-9_=]+)\\.([a-zA-Z0-9_=]+)\\.([a-zA-Z0-9_\\-=]*$)/;\n\n// Error messages\n\nexport const INVALID_TOKEN_ERROR = 'Empty or invalid token';\n\n// url query params keys\nexport const TOKEN_QUERY_KEY = 'token';\nexport const REFRESH_TOKEN_QUERY_KEY = 'refresh_token';\n","class CookieStorage {\n isAccessible = false;\n\n saveToken(): boolean {\n return true;\n }\n\n getToken(): string {\n throw new Error('Can not get token from HttpOnly');\n }\n\n deleteToken(): void {\n // throw new Error('Can not get token from HttpOnly');\n }\n}\n\nexport default CookieStorage;\n","import { TokenManager, TokenType } from '../types/types';\n\nclass StorageManager implements TokenManager {\n preffix = 'identifo_';\n\n storageType: 'localStorage' | 'sessionStorage' = 'localStorage';\n\n access = `${this.preffix}access_token`;\n\n refresh = `${this.preffix}refresh_token`;\n\n isAccessible = true;\n\n constructor(storageType: 'localStorage' | 'sessionStorage', accessKey?: string, refreshKey?: string) {\n this.access = accessKey ? this.preffix + accessKey : this.access;\n this.refresh = refreshKey ? this.preffix + refreshKey : this.refresh;\n this.storageType = storageType;\n }\n\n saveToken(token: string, tokenType: TokenType): boolean {\n if (token) {\n window[this.storageType].setItem(this[tokenType], token);\n return true;\n }\n return false;\n }\n\n getToken(tokenType: TokenType): string {\n return window[this.storageType].getItem(this[tokenType]) ?? '';\n }\n\n deleteToken(tokenType: TokenType): void {\n window[this.storageType].removeItem(this[tokenType]);\n }\n}\n\nexport default StorageManager;\n","import StorageManager from './storage-manager';\n\nclass LocalStorage extends StorageManager {\n constructor(accessKey?: string, refreshKey?: string) {\n super('localStorage', accessKey, refreshKey);\n }\n}\n\nexport default LocalStorage;\n","import StorageManager from './storage-manager';\n\nclass SessionStorage extends StorageManager {\n constructor(accessKey?: string, refreshKey?: string) {\n super('sessionStorage', accessKey, refreshKey);\n }\n}\n\nexport default SessionStorage;\n","import { INVALID_TOKEN_ERROR } from './constants';\nimport { LocalStorageManager } from './store-manager';\nimport { ClientToken, JWTPayload, TokenManager, TokenType } from './types/types';\n\nclass TokenService {\n isAuth = false;\n\n private tokenManager: TokenManager;\n\n constructor(tokenManager?: TokenManager) {\n this.tokenManager = tokenManager || new LocalStorageManager();\n // TODO: implement cookie as default\n // this.tokenManager = tokenManager || new CoockieStorage();\n }\n\n async handleVerification(token: string, audience: string, issuer?: string): Promise {\n if (!this.tokenManager.isAccessible) return true;\n try {\n await this.validateToken(token, audience, issuer);\n this.saveToken(token);\n return true;\n } catch (err) {\n this.removeToken();\n return Promise.reject(err);\n }\n }\n\n async validateToken(token: string, audience: string, issuer?: string): Promise {\n if (!token) throw new Error(INVALID_TOKEN_ERROR);\n const jwtPayload = this.parseJWT(token);\n const isJwtExpired = this.isJWTExpired(jwtPayload);\n if (jwtPayload.aud?.includes(audience) && (!issuer || jwtPayload.iss === issuer) && !isJwtExpired) {\n return Promise.resolve(true);\n }\n throw new Error(INVALID_TOKEN_ERROR);\n }\n\n parseJWT(token: string): JWTPayload {\n const base64Url = token.split('.')[1];\n if (!base64Url) return { aud: [], iss: '', exp: 10 };\n const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split('')\n .map((c) => `%${`00${c.charCodeAt(0).toString(16)}`.slice(-2)}`)\n .join(''),\n );\n return JSON.parse(jsonPayload) as JWTPayload;\n }\n\n isJWTExpired(token: JWTPayload): boolean {\n const now = new Date().getTime() / 1000;\n if (token.exp && now > token.exp) {\n return true;\n }\n return false;\n }\n\n saveToken(token: string, type: TokenType = 'access'): boolean {\n if (type === 'access') {\n this.isAuth = true;\n }\n return this.tokenManager.saveToken(token, type);\n }\n\n removeToken(type: TokenType = 'access'): void {\n if (type === 'access') {\n this.isAuth = false;\n }\n this.tokenManager.deleteToken(type);\n }\n\n getToken(type: TokenType = 'access'): ClientToken | null {\n const token = this.tokenManager.getToken(type);\n if (!token) return null;\n const jwtPayload = this.parseJWT(token);\n return { token, payload: jwtPayload };\n }\n}\n\nexport default TokenService;\n","import { IdentifoConfig, UrlFlows } from './types/types';\n\nexport class UrlBuilder {\n constructor(private config: IdentifoConfig) {}\n\n getUrl(flow: UrlFlows): string {\n const scopes = this.config.scopes?.join() || '';\n const redirectUri = this.config.redirectUri ?? window.location.href;\n const baseParams = `appId=${this.config.appId}&scopes=${scopes}`;\n const urlParams = `${baseParams}&callbackUrl=${encodeURIComponent(redirectUri)}`;\n // if postLogoutRedirectUri is empty, login url will be instead\n const postLogoutRedirectUri = this.config.postLogoutRedirectUri\n ? `${this.config.postLogoutRedirectUri}`\n : `${redirectUri}&redirectUri=${this.config.url}/web/login?${encodeURIComponent(baseParams)}`;\n\n const urls = {\n signup: `${this.config.url}/web/register?${urlParams}`,\n signin: `${this.config.url}/web/login?${urlParams}`,\n logout: `${this.config.url}/web/logout?${baseParams}&callbackUrl=${encodeURIComponent(postLogoutRedirectUri)}`,\n renew: `${this.config.url}/web/token/renew?${baseParams}&redirectUri=${encodeURIComponent(redirectUri)}`,\n default: 'default',\n };\n\n return urls[flow] || urls.default;\n }\n\n createSignupUrl(): string {\n return this.getUrl('signup');\n }\n\n createSigninUrl(): string {\n return this.getUrl('signin');\n }\n\n createLogoutUrl(): string {\n return this.getUrl('logout');\n }\n\n createRenewSessionUrl(): string {\n return this.getUrl('renew');\n }\n}\n","import { API } from './api/api';\nimport { jwtRegex, REFRESH_TOKEN_QUERY_KEY, TOKEN_QUERY_KEY } from './constants';\nimport TokenService from './tokenService';\nimport { ClientToken, IdentifoConfig, UrlBuilderInit } from './types/types';\nimport { UrlBuilder } from './UrlBuilder';\n\nclass IdentifoAuth {\n public api!: API;\n\n public tokenService!: TokenService;\n\n public config!: IdentifoConfig;\n\n public urlBuilder!: UrlBuilderInit;\n\n private token: ClientToken | null = null;\n\n get isAuth(): boolean {\n return !!this.tokenService?.isAuth;\n }\n\n constructor(config?: IdentifoConfig) {\n if (config) {\n this.configure(config);\n }\n }\n\n public configure(config: IdentifoConfig): void {\n this.config = { ...config, autoRenew: config.autoRenew ?? true };\n this.tokenService = new TokenService(config.tokenManager);\n this.urlBuilder = new UrlBuilder(this.config);\n this.api = new API(config, this.tokenService);\n this.handleToken(this.tokenService.getToken()?.token || '', 'access');\n }\n\n private handleToken(token: string, tokenType: 'access' | 'refresh') {\n if (token) {\n if (tokenType === 'access') {\n const payload = this.tokenService.parseJWT(token);\n this.token = { token, payload };\n this.tokenService.saveToken(token);\n } else {\n this.tokenService.saveToken(token, 'refresh');\n }\n }\n }\n\n private resetAuthValues() {\n this.token = null;\n this.tokenService.removeToken();\n this.tokenService.removeToken('refresh');\n }\n\n signup(): void {\n window.location.href = this.urlBuilder.createSignupUrl();\n }\n\n signin(): void {\n window.location.href = this.urlBuilder.createSigninUrl();\n }\n\n logout(): void {\n this.resetAuthValues();\n window.location.href = this.urlBuilder.createLogoutUrl();\n }\n\n async handleAuthentication(): Promise {\n const { access, refresh } = this.getTokenFromUrl();\n if (!access) {\n this.resetAuthValues();\n return Promise.reject();\n }\n try {\n await this.tokenService.handleVerification(access, this.config.appId, this.config.issuer);\n this.handleToken(access, 'access');\n if (refresh) {\n this.handleToken(refresh, 'refresh');\n }\n return await Promise.resolve(true);\n } catch (err) {\n this.resetAuthValues();\n return await Promise.reject();\n } finally {\n window.history.pushState({}, document.title, window.location.pathname);\n }\n }\n\n private getTokenFromUrl(): { access: string; refresh: string } {\n const urlParams = new URLSearchParams(window.location.search);\n const tokens = { access: '', refresh: '' };\n const accessToken = urlParams.get(TOKEN_QUERY_KEY);\n const refreshToken = urlParams.get(REFRESH_TOKEN_QUERY_KEY);\n if (refreshToken && jwtRegex.test(refreshToken)) {\n tokens.refresh = refreshToken;\n }\n if (accessToken && jwtRegex.test(accessToken)) {\n tokens.access = accessToken;\n }\n return tokens;\n }\n\n async getToken(): Promise {\n const token = this.tokenService.getToken();\n const refreshToken = this.tokenService.getToken('refresh');\n if (token) {\n const isExpired = this.tokenService.isJWTExpired(token.payload);\n if (isExpired && refreshToken) {\n try {\n await this.renewSession();\n return await Promise.resolve(this.token);\n } catch (err) {\n this.resetAuthValues();\n throw new Error('No token');\n }\n }\n return Promise.resolve(token);\n }\n return Promise.resolve(null);\n }\n\n async renewSession(): Promise {\n try {\n const { access, refresh } = await this.renewSessionWithToken();\n this.handleToken(access, 'access');\n this.handleToken(refresh, 'refresh');\n return await Promise.resolve(access);\n } catch (err) {\n return Promise.reject();\n }\n }\n\n private async renewSessionWithToken(): Promise<{ access: string; refresh: string }> {\n try {\n const tokens = await this.api\n .renewToken()\n .then((l) => ({ access: l.access_token || '', refresh: l.refresh_token || '' }));\n return tokens;\n } catch (err) {\n return Promise.reject(err);\n }\n }\n}\nexport default IdentifoAuth;\n","import {\n ApiError,\n FederatedLoginProvider,\n LoginResponse,\n ServerSettingsLoginTypes,\n TFAStatus,\n TFAType,\n SuccessResponse,\n} from '../api/model';\n\nexport enum Routes {\n 'LOGIN' = 'login',\n 'REGISTER' = 'register',\n 'TFA_VERIFY_SMS' = 'tfa/verify/sms',\n 'TFA_VERIFY_EMAIL' = 'tfa/verify/email',\n 'TFA_VERIFY_APP' = 'tfa/verify/app',\n 'TFA_VERIFY_SELECT' = 'tfa/verify/select',\n 'TFA_SETUP_SMS' = 'tfa/setup/sms',\n 'TFA_SETUP_EMAIL' = 'tfa/setup/email',\n 'TFA_SETUP_APP' = 'tfa/setup/app',\n 'TFA_SETUP_SELECT' = 'tfa/setup/select',\n 'PASSWORD_RESET' = 'password/reset',\n 'PASSWORD_FORGOT' = 'password/forgot',\n 'PASSWORD_FORGOT_TFA_SMS' = 'password/forgot/tfa/sms',\n 'PASSWORD_FORGOT_TFA_EMAIL' = 'password/forgot/tfa/email',\n 'PASSWORD_FORGOT_TFA_APP' = 'password/forgot/tfa/app',\n 'PASSWORD_FORGOT_TFA_SELECT' = 'password/forgot/tfa/select',\n 'CALLBACK' = 'callback',\n 'LOGIN_PHONE' = 'login_phone',\n 'LOGIN_PHONE_VERIFY' = 'login_phone_verify',\n 'ERROR' = 'error',\n 'PASSWORD_FORGOT_SUCCESS' = 'password/forgot/success',\n 'LOGOUT' = 'logout',\n 'LOADING' = 'loading',\n}\n\nexport type TFASetupRoutes =\n | Routes.TFA_SETUP_SELECT\n | Routes.TFA_SETUP_SMS\n | Routes.TFA_SETUP_EMAIL\n | Routes.TFA_SETUP_APP;\nexport type TFALoginVerifyRoutes =\n | Routes.TFA_VERIFY_SELECT\n | Routes.TFA_VERIFY_SMS\n | Routes.TFA_VERIFY_EMAIL\n | Routes.TFA_VERIFY_APP;\nexport type TFAResetVerifyRoutes =\n | Routes.PASSWORD_FORGOT_TFA_SELECT\n | Routes.PASSWORD_FORGOT_TFA_SMS\n | Routes.PASSWORD_FORGOT_TFA_EMAIL\n | Routes.PASSWORD_FORGOT_TFA_APP;\n\nexport interface State {\n route: Routes;\n}\n\nexport interface StateWithError {\n error?: ApiError;\n}\n\nexport type LoginTypes = Partial<\n Record void; type: keyof ServerSettingsLoginTypes }>\n>;\n\nexport interface StateLogin extends State, StateWithError {\n route: Routes.LOGIN;\n registrationForbidden: boolean;\n federatedProviders: FederatedLoginProvider[];\n loginTypes: LoginTypes;\n signup: () => Promise;\n signin: (email: string, password: string, remember?: boolean) => Promise;\n socialLogin: (provider: FederatedLoginProvider) => Promise;\n passwordForgot: () => Promise;\n}\n\nexport interface StateLoginPhone extends State, StateWithError {\n route: Routes.LOGIN_PHONE;\n registrationForbidden: boolean;\n federatedProviders: FederatedLoginProvider[];\n loginTypes: LoginTypes;\n requestCode: (phone: string) => Promise;\n socialLogin: (provider: FederatedLoginProvider) => Promise;\n}\nexport interface StateLoginPhoneVerify extends State, StateWithError {\n route: Routes.LOGIN_PHONE_VERIFY;\n phone: string;\n resendTimeout: number;\n resendCode: () => Promise;\n login: (code: string) => Promise;\n goback: () => Promise;\n}\n\nexport interface StateRegister extends State, StateWithError {\n route: Routes.REGISTER;\n signup: (email: string, password: string, token?: string) => Promise;\n goback: () => Promise;\n}\n\nexport interface StatePasswordForgot extends State, StateWithError {\n route: Routes.PASSWORD_FORGOT;\n restorePassword: (email: string) => Promise;\n goback: () => Promise;\n}\nexport interface StatePasswordForgotSuccess extends State {\n route: Routes.PASSWORD_FORGOT_SUCCESS;\n goback: () => Promise;\n}\n\nexport interface StateError extends State, StateWithError {\n route: Routes.ERROR;\n}\n\nexport interface StateCallback extends State {\n route: Routes.CALLBACK;\n callbackUrl?: string;\n result: LoginResponse;\n}\n\nexport interface StatePasswordReset extends State, StateWithError {\n route: Routes.PASSWORD_RESET;\n setNewPassword: (password: string) => Promise;\n}\n\nexport interface StateLoading extends State {\n route: Routes.LOADING;\n}\n\ninterface StateTFASetup extends State, StateWithError {}\n\nexport interface StateTFASetupApp extends StateTFASetup {\n route: Routes.TFA_SETUP_APP;\n provisioningURI: string;\n provisioningQR: string;\n setupTFA: () => Promise;\n}\nexport interface StateTFASetupEmail extends StateTFASetup {\n route: Routes.TFA_SETUP_EMAIL;\n email: string;\n setupTFA: (email: string) => Promise;\n}\nexport interface StateTFASetupSMS extends StateTFASetup {\n route: Routes.TFA_SETUP_SMS;\n phone: string;\n setupTFA: (phone: string) => Promise;\n}\n\ninterface StateTFASelect extends State {\n tfaTypes: TFAType[];\n select: (type: TFAType) => Promise;\n email?: string;\n phone?: string;\n}\n\nexport interface StateTFASetupSelect extends StateTFASelect {\n route: Routes.TFA_SETUP_SELECT;\n tfaStatus: TFAStatus;\n setupNextTime: () => Promise;\n}\nexport interface StateTFAVerifySelect extends StateTFASelect {\n route: Routes.TFA_VERIFY_SELECT;\n}\nexport interface StatePasswordForgotTFASelect extends StateTFASelect {\n route: Routes.PASSWORD_FORGOT_TFA_SELECT;\n}\n\nexport interface StateTFAVerifyApp extends State, StateWithError {\n route: Routes.TFA_VERIFY_APP;\n email?: string;\n phone?: string;\n verifyTFA: (code: string) => Promise;\n}\n\nexport interface StateTFAVerifyEmailSms extends State, StateWithError {\n route: Routes.TFA_VERIFY_EMAIL | Routes.TFA_VERIFY_SMS;\n email?: string;\n phone?: string;\n resendTimeout: number;\n verifyTFA: (code: string) => Promise;\n resendTFA: () => Promise;\n}\n\nexport interface StatePasswordForgotTFAVerify extends State, StateWithError {\n route: Routes.PASSWORD_FORGOT_TFA_APP | Routes.PASSWORD_FORGOT_TFA_EMAIL | Routes.PASSWORD_FORGOT_TFA_SMS;\n email?: string;\n phone?: string;\n verifyTFA: (code: string) => Promise;\n}\n\nexport interface StateLogout extends State {\n route: Routes.LOGOUT;\n logout: () => Promise;\n}\n\nexport const typeToSetupRoute = {\n [TFAType.TFATypeApp]: Routes.TFA_SETUP_APP,\n [TFAType.TFATypeEmail]: Routes.TFA_SETUP_EMAIL,\n [TFAType.TFATypeSMS]: Routes.TFA_SETUP_SMS,\n};\n\nexport const typeToTFAVerifyRoute = {\n [TFAType.TFATypeApp]: Routes.TFA_VERIFY_APP,\n [TFAType.TFATypeEmail]: Routes.TFA_VERIFY_EMAIL,\n [TFAType.TFATypeSMS]: Routes.TFA_VERIFY_SMS,\n};\nexport const typeToPasswordForgotTFAVerifyRoute = {\n [TFAType.TFATypeApp]: Routes.PASSWORD_FORGOT_TFA_APP,\n [TFAType.TFATypeEmail]: Routes.PASSWORD_FORGOT_TFA_EMAIL,\n [TFAType.TFATypeSMS]: Routes.PASSWORD_FORGOT_TFA_SMS,\n};\n\n// TODO exclude generalState\nexport type States =\n | State\n | StateTFASetupApp\n | StateTFASetupEmail\n | StateTFASetupSMS\n | StatePasswordReset\n | StatePasswordForgot\n | StatePasswordForgotSuccess\n | StateLoading\n | StateCallback\n | StateLogin\n | StateRegister\n | StateError;\n","import { BehaviorSubject } from 'rxjs';\nimport { StateLoginPhone, StateLoginPhoneVerify } from '..';\nimport {\n ApiError,\n APIErrorCodes,\n AppSettingsResponse,\n FederatedLoginProvider,\n LoginResponse,\n ServerSettingsLoginTypes,\n TFAStatus,\n TFAType,\n} from '../api/model';\nimport IdentifoAuth from '../IdentifoAuth';\nimport { IdentifoConfig } from '../types/types';\nimport {\n LoginTypes,\n Routes,\n State,\n StateCallback,\n StateError,\n StateLogout,\n StatePasswordForgotTFASelect,\n StatePasswordForgotTFAVerify,\n States,\n StateTFASetupSelect,\n StateTFAVerifyApp,\n StateTFAVerifyEmailSms,\n StateTFAVerifySelect,\n StateWithError,\n typeToPasswordForgotTFAVerifyRoute,\n typeToTFAVerifyRoute,\n} from './model';\n\nconst emailRegex =\n // eslint-disable-next-line max-len\n /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\nconst phoneRegex = /^[\\+][0-9]{9,15}$/;\n\nexport class CDK {\n auth: IdentifoAuth;\n\n settings!: AppSettingsResponse;\n\n lastError!: ApiError;\n\n callbackUrl?: string;\n\n postLogoutRedirectUri?: string;\n\n scopes: Set = new Set();\n\n state: BehaviorSubject = new BehaviorSubject({ route: Routes.LOADING } as States);\n\n constructor() {\n this.auth = new IdentifoAuth();\n }\n\n // eslint-disable-next-line max-statements\n async configure(authConfig: IdentifoConfig, callbackUrl: string): Promise {\n this.state.next({ route: Routes.LOADING });\n\n this.callbackUrl = callbackUrl;\n this.scopes = new Set(authConfig.scopes ?? []);\n\n this.postLogoutRedirectUri = window.location.origin + window.location.pathname;\n // this.postLogoutRedirectUri = this.postLogoutRedirectUri || window.location.origin + window.location.pathname;\n\n if (!authConfig.appId) {\n this.state.next({\n route: Routes.ERROR,\n error: { message: 'app-id param is empty', name: 'app-id empty' },\n } as StateError);\n return;\n }\n if (!authConfig.url) {\n this.state.next({\n route: Routes.ERROR,\n error: { message: 'url param is empty', name: 'url empty' },\n } as StateError);\n return;\n }\n\n this.auth.configure(authConfig);\n try {\n this.settings = await this.auth.api.getAppSettings(callbackUrl);\n } catch (err) {\n this.state.next({\n route: Routes.ERROR,\n error: err as ApiError,\n } as StateError);\n return;\n }\n this.settings.tfaType = Array.isArray(this.settings.tfaType) ? this.settings.tfaType : [this.settings.tfaType];\n\n // // If we have provider and state then we need to complete federated login\n const href = new URL(window.location.href);\n if (!!href.searchParams.get('provider') && !!href.searchParams.get('state')) {\n // Also we clear all url params after parsing\n const u = new URL(window.location.href);\n const sp = new URLSearchParams();\n const appId = href.searchParams.get('appId');\n if (appId === null) {\n this.state.next({\n route: Routes.ERROR,\n error: { message: 'app-id param is empty', name: 'app-id empty' },\n } as StateError);\n return;\n }\n sp.set('appId', appId);\n window.history.replaceState({}, document.title, `${u.pathname}?${sp.toString()}`);\n this.auth.api\n .federatedLoginComplete(u.searchParams)\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n }\n }\n\n login(): void {\n // check for allowed login with\n switch (true) {\n case (!this.auth.config.loginWith && this.settings.loginWith['phone']) ||\n (this.auth.config.loginWith === 'phone' && this.settings.loginWith['phone']):\n return this.loginWithPhone();\n case (!this.auth.config.loginWith && this.settings.loginWith['email']) ||\n (this.auth.config.loginWith === 'email' && this.settings.loginWith['email']):\n return this.loginWithPassword();\n default:\n throw 'Unsupported login way';\n }\n }\n loginWithPhone(): void {\n this.state.next({\n route: Routes.LOGIN_PHONE,\n registrationForbidden: this.settings?.registrationForbidden,\n error: this.lastError,\n federatedProviders: this.settings?.federatedProviders,\n loginTypes: this.getLoginTypes('phone'),\n requestCode: async (phone: string, remember?: boolean): Promise => {\n if (!this.validatePhone(phone)) {\n return;\n }\n const scopes = new Set(this.scopes);\n if (remember) {\n scopes.add('offline');\n }\n await this.auth.api\n .requestPhoneCode(phone)\n .then(() => this.loginWithPhoneVerify(phone, remember))\n .catch((e) => this.processError(e));\n },\n socialLogin: async (provider: FederatedLoginProvider) => {\n this.state.next({ route: Routes.LOADING });\n const federatedRedirectUrl = window.location.origin + window.location.pathname;\n return this.auth.api.federatedLogin(\n provider,\n [...Array.from(this.scopes)],\n federatedRedirectUrl,\n this.callbackUrl,\n );\n },\n } as StateLoginPhone);\n }\n loginWithPhoneVerify(phone: string, remember?: boolean): void {\n this.state.next({\n route: Routes.LOGIN_PHONE_VERIFY,\n error: this.lastError,\n phone: phone,\n resendTimeout: this.settings.tfaResendTimeout * 1000,\n resendCode: async () => {\n await this.auth.api.requestPhoneCode(phone);\n },\n login: async (code: string): Promise => {\n const scopes = new Set(this.scopes);\n if (remember) {\n scopes.add('offline');\n }\n await this.auth.api\n .phoneLogin(phone, code, [...Array.from(this.scopes)])\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n goback: async (): Promise => {\n this.login();\n },\n } as StateLoginPhoneVerify);\n }\n loginWithPassword(): void {\n this.state.next({\n route: Routes.LOGIN,\n registrationForbidden: this.settings?.registrationForbidden,\n error: this.lastError,\n federatedProviders: this.settings?.federatedProviders,\n loginTypes: this.getLoginTypes('email'),\n signup: async (): Promise => {\n this.register();\n },\n signin: async (email: string, password: string, remember?: boolean): Promise => {\n if (!this.validateEmail(email)) {\n return;\n }\n const scopes = new Set(this.scopes);\n if (remember) {\n scopes.add('offline');\n }\n await this.auth.api\n .login(email, password, '', [...Array.from(scopes)])\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n socialLogin: async (provider: FederatedLoginProvider) => {\n this.state.next({ route: Routes.LOADING });\n const federatedRedirectUrl = window.location.origin + window.location.pathname;\n return this.auth.api.federatedLogin(\n provider,\n [...Array.from(this.scopes)],\n federatedRedirectUrl,\n this.callbackUrl,\n );\n },\n passwordForgot: async () => {\n this.forgotPassword();\n },\n });\n }\n\n register(): void {\n this.state.next({\n route: Routes.REGISTER,\n signup: async (email: string, password: string, token?: string): Promise => {\n if (!this.validateEmail(email)) {\n return;\n }\n await this.auth.api\n .register(email, password, [...Array.from(this.scopes)], token)\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n\n forgotPassword(): void {\n this.state.next({\n route: Routes.PASSWORD_FORGOT,\n restorePassword: async (email: string): Promise => {\n return this.auth.api\n .requestResetPassword(email)\n .then(async (response) => {\n if (response.result === 'tfa-required') {\n await this.redirectTfaForgot(email);\n return;\n }\n if (response.result === 'ok') {\n this.forgotPasswordSuccess();\n }\n })\n .catch((e) => this.processError(e));\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n\n forgotPasswordSuccess(): void {\n this.state.next({\n route: Routes.PASSWORD_FORGOT_SUCCESS,\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n\n passwordReset(): void {\n this.state.next({\n route: Routes.PASSWORD_RESET,\n setNewPassword: async (password: string): Promise => {\n this.auth.api\n .resetPassword(password)\n .then(() => {\n this.login();\n })\n .catch((e) => this.processError(e));\n },\n });\n }\n\n callback(result: LoginResponse): void {\n this.state.next({\n route: Routes.CALLBACK,\n callbackUrl: this.callbackUrl,\n result,\n } as StateCallback);\n if (this.callbackUrl) {\n const url = new URL(this.callbackUrl);\n if (result.access_token) {\n url.searchParams.set('token', result.access_token);\n }\n if (result.refresh_token) {\n url.searchParams.set('refresh_token', result.refresh_token);\n }\n window.location.href = url.toString();\n }\n }\n\n validateEmail(email: string): boolean {\n if (!emailRegex.test(email)) {\n this.processError({\n detailedMessage: 'Email address is not valid',\n name: 'Validation error',\n message: 'Email address is not valid',\n } as ApiError);\n return false;\n }\n return true;\n }\n\n validatePhone(email: string): boolean {\n if (!phoneRegex.test(email)) {\n this.processError({\n detailedMessage: 'Phone is not valid',\n name: 'Validation error',\n message: 'Phone is not valid',\n } as ApiError);\n return false;\n }\n return true;\n }\n\n async tfaSetup(loginResponse: LoginResponse, type: TFAType): Promise {\n switch (type) {\n case TFAType.TFATypeApp: {\n this.state.next({\n route: Routes.TFA_SETUP_APP,\n provisioningURI: '',\n provisioningQR: '',\n setupTFA: async () => {},\n goback: async (): Promise => {\n this.login();\n },\n });\n const tfa = await this.auth.api.enableTFA({});\n if (tfa.provisioning_uri) {\n this.state.next({\n route: Routes.TFA_SETUP_APP,\n provisioningURI: tfa.provisioning_uri,\n provisioningQR: tfa.provisioning_qr || '',\n setupTFA: async () => this.tfaVerify(loginResponse, type),\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n break;\n }\n case TFAType.TFATypeEmail: {\n this.state.next({\n route: Routes.TFA_SETUP_EMAIL,\n email: loginResponse.user.email || '',\n setupTFA: async (email: string) => {\n await this.auth.api.enableTFA({ email });\n return this.tfaVerify({ ...loginResponse, user: { ...loginResponse.user, email } }, type);\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n break;\n }\n case TFAType.TFATypeSMS: {\n this.state.next({\n route: Routes.TFA_SETUP_SMS,\n phone: loginResponse.user.phone || '',\n setupTFA: async (phone: string) => {\n await this.auth.api.enableTFA({ phone });\n return this.tfaVerify({ ...loginResponse, user: { ...loginResponse.user, phone } }, type);\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n break;\n }\n default:\n }\n }\n\n async tfaVerify(loginResponse: LoginResponse, type: TFAType): Promise {\n const state = {\n route: typeToTFAVerifyRoute[type],\n email: loginResponse.user.email,\n phone: loginResponse.user.phone,\n verifyTFA: async (code: string) => {\n await this.auth.api\n .verifyTFA(code, [...Array.from(this.scopes)])\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n };\n switch (type) {\n case TFAType.TFATypeApp: {\n this.state.next({ ...state } as StateTFAVerifyApp);\n break;\n }\n case TFAType.TFATypeEmail:\n case TFAType.TFATypeSMS: {\n this.state.next({\n ...state,\n resendTimeout: this.settings.tfaResendTimeout * 1000, // in ms\n resendTFA: async () => {\n await this.auth.api.resendTFA();\n },\n } as StateTFAVerifyEmailSms);\n break;\n }\n default:\n }\n }\n\n async passwordForgotTFAVerify(email: string, type: TFAType): Promise {\n this.state.next({\n route: typeToPasswordForgotTFAVerifyRoute[type],\n verifyTFA: async (code: string) => {\n this.auth.api\n .requestResetPassword(email, code)\n .then(() => {\n this.forgotPasswordSuccess();\n })\n .catch((e) => this.processError(e));\n },\n } as StatePasswordForgotTFAVerify);\n }\n\n async logout(): Promise {\n this.state.next({\n route: Routes.LOGOUT,\n logout: async () => this.auth.api.logout(),\n } as StateLogout);\n }\n\n // restorePassword(token: string): void {}\n\n private processError(e: ApiError) {\n e.detailedMessage = e.detailedMessage?.trim();\n e.message = e.message?.trim();\n\n this.state.next({\n ...this.state.getValue(),\n error: e,\n } as State & StateWithError);\n }\n\n private async redirectTfaSetup(loginResponse: LoginResponse): Promise {\n if (this.settings.tfaType.length === 1) {\n await this.tfaSetup(loginResponse, this.settings.tfaType[0] as TFAType);\n return;\n }\n this.tfaSetupSelect(loginResponse);\n }\n\n private tfaSetupSelect(loginResponse: LoginResponse): void {\n this.state.next({\n route: Routes.TFA_SETUP_SELECT,\n tfaStatus: this.settings.tfaStatus,\n tfaTypes: this.settings.tfaType,\n select: async (type: TFAType) => {\n await this.tfaSetup(loginResponse, type);\n },\n setupNextTime: () => {\n this.callback(loginResponse);\n },\n } as StateTFASetupSelect);\n }\n\n private async redirectTfaVerify(e: LoginResponse): Promise {\n if (this.settings.tfaType.length === 1) {\n await this.tfaVerify(e, this.settings.tfaType[0] as TFAType);\n return;\n }\n this.state.next({\n route: Routes.TFA_VERIFY_SELECT,\n tfaStatus: this.settings.tfaStatus,\n tfaTypes: this.settings.tfaType,\n select: async (type: TFAType) => {\n await this.tfaVerify(e, type);\n },\n } as StateTFAVerifySelect);\n }\n\n private async redirectTfaForgot(email: string): Promise {\n if (this.settings.tfaType.length === 1) {\n await this.passwordForgotTFAVerify(email, this.settings.tfaType[0] as TFAType);\n return;\n }\n this.state.next({\n route: Routes.PASSWORD_FORGOT_TFA_SELECT,\n tfaStatus: this.settings.tfaStatus,\n tfaTypes: this.settings.tfaType,\n select: async (type: TFAType) => {\n await this.passwordForgotTFAVerify(email, type);\n },\n } as StatePasswordForgotTFASelect);\n }\n\n // eslint-disable-next-line complexity\n private afterLoginRedirect = async (loginResponse: LoginResponse): Promise => {\n if (loginResponse.require_2fa) {\n if (!loginResponse.enabled_2fa) {\n await this.redirectTfaSetup(loginResponse);\n return;\n }\n if (loginResponse.enabled_2fa) {\n await this.redirectTfaVerify(loginResponse);\n return;\n }\n }\n // Ask about tfa on login only\n if (\n this.settings.tfaStatus === TFAStatus.OPTIONAL &&\n [Routes.LOGIN, Routes.REGISTER].includes(this.state.getValue().route)\n ) {\n this.tfaSetupSelect(loginResponse);\n return;\n }\n if (loginResponse.access_token && loginResponse.refresh_token) {\n this.callback(loginResponse);\n return;\n }\n if (loginResponse.access_token && !loginResponse.refresh_token) {\n this.callback(loginResponse);\n return;\n }\n this.login();\n };\n\n private loginCatchRedirect = (data: ApiError): void => {\n if (data.id === APIErrorCodes.PleaseEnableTFA) {\n // this.redirectTfaSetup();\n return;\n }\n throw data;\n };\n private getLoginTypes(current: keyof ServerSettingsLoginTypes): LoginTypes {\n const result: LoginTypes = {};\n Object.entries(this.settings.loginWith)\n .filter((v) => v[1] && v[0] !== current)\n .forEach((v) => {\n result[v[0] as keyof ServerSettingsLoginTypes] = {\n type: v[0] as keyof ServerSettingsLoginTypes,\n click: () => {\n this.auth.config.loginWith = v[0] as keyof ServerSettingsLoginTypes;\n this.login();\n },\n };\n });\n return result;\n }\n}\n"],"names":["__async","__spreadValues","LocalStorageManager","__spreadProps"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"identifo.mjs","sources":["../src/api/model.ts","../src/api/api.ts","../src/constants.ts","../src/store-manager/cookie-storage.ts","../src/store-manager/storage-manager.ts","../src/store-manager/local-storage.ts","../src/store-manager/session-storage.ts","../src/tokenService.ts","../src/UrlBuilder.ts","../src/IdentifoAuth.ts","../src/cdk/model.ts","../src/cdk/cdk.ts"],"sourcesContent":["/* eslint-disable camelcase */\nexport enum APIErrorCodes {\n PleaseEnableTFA = 'error.api.request.2fa.please_enable',\n InvalidCallbackURL = 'error.api.request.callbackurl.invalid',\n NetworkError = 'error.network',\n}\n\nexport enum TFAType {\n TFATypeApp = 'app',\n TFATypeSMS = 'sms',\n TFATypeEmail = 'email',\n}\n\nexport enum TFAStatus {\n DISABLED = 'disabled',\n OPTIONAL = 'optional',\n MANDATORY = 'mandatory',\n}\n\nexport interface ServerSettingsLoginTypes {\n email: boolean;\n federated: boolean;\n federated_oidc: boolean;\n phone: boolean;\n username: boolean;\n}\n\nexport type FederatedLoginProvider = 'apple' | 'google' | 'facebook';\nexport interface ApiRequestError {\n error: {\n detailed_message?: string;\n id?: APIErrorCodes;\n message?: string;\n status?: number;\n };\n}\nexport class ApiError extends Error {\n detailedMessage?: string;\n\n id?: APIErrorCodes;\n\n status?: number;\n\n constructor(error?: ApiRequestError['error']) {\n super(error?.message || 'Unknown API error');\n this.detailedMessage = error?.detailed_message;\n this.id = error?.id;\n this.status = error?.status;\n }\n}\nexport interface LoginResponse {\n access_token?: string;\n refresh_token?: string;\n require_2fa: boolean;\n enabled_2fa: boolean;\n user: {\n active: boolean;\n email?: string;\n id: string;\n latest_login_time: number;\n num_of_logins: number;\n username?: string;\n tfa_info: { hotp_expired_at: string };\n phone?: string;\n };\n scopes?: string[];\n callbackUrl?: string;\n}\nexport interface EnableTFAResponse {\n provisioning_uri?: string;\n provisioning_qr?: string;\n access_token?: string;\n}\nexport interface TokenResponse {\n access_token?: string;\n refresh_token?: string;\n}\nexport interface AppSettingsResponse {\n anonymousResitrationAllowed: boolean;\n active: boolean;\n description: string;\n id: string;\n newUserDefaultRole: string;\n offline: boolean;\n registrationForbidden: boolean;\n tfaType: TFAType[] | TFAType;\n tfaResendTimeout: number;\n tfaStatus: TFAStatus;\n federatedProviders: FederatedLoginProvider[];\n loginWith: ServerSettingsLoginTypes;\n federatedOIDCInitURL: string;\n}\n\nexport interface User {\n id: string;\n username: string;\n email: string;\n phone: string;\n active: boolean;\n tfa_info: {\n is_enabled: boolean;\n };\n num_of_logins: number;\n latest_login_time: number;\n access_role: string;\n anonymous: boolean;\n federated_ids: string[];\n}\nexport interface UpdateUser {\n new_email?: string;\n new_phone?: string;\n}\nexport interface SuccessResponse {\n result: 'ok';\n message?: string;\n}\n\nexport interface InviteResponse {\n result: 'ok';\n link: string;\n}\n\nexport interface TFARequiredRespopnse {\n result: 'tfa-required';\n}\n","import { InviteResponse } from '..';\nimport TokenService from '../tokenService';\nimport { IdentifoConfig } from '../types/types';\nimport {\n AppSettingsResponse,\n EnableTFAResponse,\n LoginResponse,\n SuccessResponse,\n UpdateUser,\n User,\n ApiRequestError,\n ApiError,\n APIErrorCodes,\n FederatedLoginProvider,\n TokenResponse,\n TFARequiredRespopnse,\n} from './model';\n\nconst APP_ID_HEADER_KEY = 'X-Identifo-Clientid';\nconst AUTHORIZATION_HEADER_KEY = 'Authorization';\n\nexport class API {\n baseUrl: string;\n\n appId: string;\n\n defaultHeaders = {\n [APP_ID_HEADER_KEY]: '',\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n };\n\n catchNetworkErrorHandler = (e: TypeError): never => {\n if (\n e.message === 'Network Error' ||\n e.message === 'Failed to fetch' ||\n e.message === 'Preflight response is not successful' ||\n e.message.indexOf('is not allowed by Access-Control-Allow-Origin') > -1\n ) {\n // eslint-disable-next-line no-console\n console.error(e.message);\n throw new ApiError({\n id: APIErrorCodes.NetworkError,\n status: 0,\n message: 'Configuration error',\n detailed_message:\n 'Please check Identifo URL and add \"' +\n `${window.location.protocol}//${window.location.host}\" ` +\n 'to \"REDIRECT URLS\" in Identifo app settings.',\n });\n }\n throw e;\n };\n\n checkStatusCodeAndGetJSON = async (r: Response): Promise => {\n if (!r.ok) {\n const error = (await r.json()) as ApiRequestError;\n throw new ApiError(error?.error);\n }\n return r.json();\n };\n\n constructor(private config: IdentifoConfig, private tokenService: TokenService) {\n // remove trailing slash if exist\n this.baseUrl = config.url.replace(/\\/$/, '');\n this.defaultHeaders[APP_ID_HEADER_KEY] = config.appId;\n this.appId = config.appId;\n }\n\n get(path: string, options?: RequestInit): Promise {\n return this.send(path, { method: 'GET', ...options });\n }\n\n put(path: string, data: unknown, options?: RequestInit): Promise {\n return this.send(path, { method: 'PUT', body: JSON.stringify(data), ...options });\n }\n\n post(path: string, data: unknown, options?: RequestInit): Promise {\n return this.send(path, { method: 'POST', body: JSON.stringify(data), ...options });\n }\n\n send(path: string, options?: RequestInit): Promise {\n const init = { ...options };\n init.credentials = 'include';\n init.headers = {\n ...init.headers,\n ...this.defaultHeaders,\n };\n return fetch(`${this.baseUrl}${path}`, init)\n .catch(this.catchNetworkErrorHandler)\n .then(this.checkStatusCodeAndGetJSON)\n .then((value) => value as T);\n }\n\n async getUser(): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.get('/me', {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n });\n }\n\n async renewToken(): Promise {\n if (!this.tokenService.getToken('refresh')?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/auth/token',\n { scopes: this.config.scopes },\n {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken('refresh')?.token}`,\n },\n },\n ).then((r) => this.storeToken(r));\n }\n\n async updateUser(user: UpdateUser): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.put('/me', user, {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken('access')?.token}`,\n },\n });\n }\n\n async login(email: string, password: string, deviceToken: string, scopes: string[]): Promise {\n const data = {\n email,\n password,\n device_token: deviceToken,\n scopes,\n };\n\n return this.post('/auth/login', data).then((r) => this.storeToken(r));\n }\n\n async requestPhoneCode(phone: string): Promise {\n const data = {\n phone_number: phone,\n };\n\n return this.post('/auth/request_phone_code', data);\n }\n\n async phoneLogin(phone: string, code: string, scopes: string[]): Promise {\n const data = {\n phone_number: phone,\n code,\n scopes,\n };\n\n return this.post('/auth/phone_login', data).then((r) => this.storeToken(r));\n }\n\n // After complete login on provider browser will be redirected to redirectUrl\n // callbackUrl will be stored in sesson and returned after successfull login complete\n async federatedLogin(\n provider: FederatedLoginProvider,\n scopes: string[],\n redirectUrl: string,\n callbackUrl?: string,\n opts: { width?: number; height?: number; popUp?: boolean } = { width: 600, height: 800, popUp: false },\n ): Promise {\n const dataForm = document.createElement('form');\n dataForm.style.display = 'none';\n if (opts.popUp) {\n dataForm.target = 'TargetWindow'; // Make sure the window name is same as this value\n }\n dataForm.method = 'POST';\n const params = new URLSearchParams();\n params.set('appId', this.config.appId);\n params.set('provider', provider);\n params.set('scopes', scopes.join(','));\n params.set('redirectUrl', redirectUrl);\n if (callbackUrl) {\n params.set('callbackUrl', callbackUrl);\n }\n dataForm.action = `${this.baseUrl}/auth/federated?${params.toString()}`;\n\n document.body.appendChild(dataForm);\n\n if (opts.popUp) {\n const left = window.screenX + window.outerWidth / 2 - (opts.width || 600) / 2;\n const top = window.screenY + window.outerHeight / 2 - (opts.height || 800) / 2;\n const postWindow = window.open(\n '',\n 'TargetWindow',\n `status=0,title=0,height=${opts.height},width=${opts.width},top=${top},left=${left},scrollbars=1`,\n );\n if (postWindow) {\n dataForm.submit();\n }\n } else {\n window.location.assign(`${this.baseUrl}/auth/federated?${params.toString()}`);\n // dataForm.submit();\n }\n }\n\n async federatedLoginComplete(params: URLSearchParams): Promise {\n return this.get(`/auth/federated/complete?${params.toString()}`).then((r) => this.storeToken(r));\n }\n\n async register(email: string, password: string, scopes: string[], invite?: string): Promise {\n const data: Record = {\n email,\n password,\n scopes,\n };\n\n if (invite) {\n data.invite = invite;\n }\n\n return this.post('/auth/register', data).then((r) => this.storeToken(r));\n }\n\n async requestResetPassword(email: string, tfaCode?: string): Promise {\n const data = {\n email,\n tfa_code: tfaCode,\n };\n\n return this.post('/auth/request_reset_password', data);\n }\n\n async resetPassword(password: string): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n const data = {\n password,\n };\n\n return this.post('/auth/reset_password', data, {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n });\n }\n\n async getAppSettings(callbackUrl: string): Promise {\n return this.get(`/auth/app_settings?${new URLSearchParams({ callbackUrl }).toString()}`);\n }\n\n async enableTFA(data: { phone?: string; email?: string }): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.put('/auth/tfa/enable', data, {\n headers: { [AUTHORIZATION_HEADER_KEY]: `BEARER ${this.tokenService.getToken()?.token}` },\n }).then((r) => this.storeToken(r));\n }\n\n async verifyTFA(code: string, scopes: string[]): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/auth/tfa/login',\n { tfa_code: code, scopes },\n { headers: { [AUTHORIZATION_HEADER_KEY]: `BEARER ${this.tokenService.getToken()?.token}` } },\n ).then((r) => this.storeToken(r));\n }\n\n async resendTFA(): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post('/auth/tfa/resend', null, {\n headers: { [AUTHORIZATION_HEADER_KEY]: `BEARER ${this.tokenService.getToken()?.token}` },\n }).then((r) => this.storeToken(r));\n }\n\n async logout(): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/me/logout',\n {\n refresh_token: this.tokenService.getToken('refresh')?.token,\n },\n {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n },\n ).then((r) => {\n this.tokenService.removeToken();\n this.tokenService.removeToken('refresh');\n return r;\n });\n }\n\n async oidcVerify(data: { state: string; code: string; scopes: string[] }): Promise {\n const url = `/auth/federated/oidc/complete?appId=${this.appId}&state=${data.state}&code=${data.code}`;\n return this.post(url, { scopes: data.scopes }, { credentials: 'include' }).then((r) =>\n this.storeToken(r),\n );\n }\n\n async invite(email: string, role: string, callbackUrl: string): Promise {\n if (!this.tokenService.getToken()?.token) {\n throw new Error('No token in token service.');\n }\n return this.post(\n '/auth/invite',\n {\n email,\n access_role: role,\n callback_url: callbackUrl,\n },\n {\n headers: {\n [AUTHORIZATION_HEADER_KEY]: `Bearer ${this.tokenService.getToken()?.token}`,\n },\n },\n );\n }\n\n storeToken(response: T): T {\n if (response.access_token) {\n this.tokenService.saveToken(response.access_token, 'access');\n }\n if (response.refresh_token) {\n this.tokenService.saveToken(response.refresh_token, 'refresh');\n }\n return response;\n }\n}\n","export const jwtRegex = /^([a-zA-Z0-9_=]+)\\.([a-zA-Z0-9_=]+)\\.([a-zA-Z0-9_\\-=]*$)/;\n\n// Error messages\n\nexport const INVALID_TOKEN_ERROR = 'Empty or invalid token';\n\n// url query params keys\nexport const TOKEN_QUERY_KEY = 'token';\nexport const REFRESH_TOKEN_QUERY_KEY = 'refresh_token';\n","class CookieStorage {\n isAccessible = false;\n\n saveToken(): boolean {\n return true;\n }\n\n getToken(): string {\n throw new Error('Can not get token from HttpOnly');\n }\n\n deleteToken(): void {\n // throw new Error('Can not get token from HttpOnly');\n }\n}\n\nexport default CookieStorage;\n","import { TokenManager, TokenType } from '../types/types';\n\nclass StorageManager implements TokenManager {\n preffix = 'identifo_';\n\n storageType: 'localStorage' | 'sessionStorage' = 'localStorage';\n\n access = `${this.preffix}access_token`;\n\n refresh = `${this.preffix}refresh_token`;\n\n isAccessible = true;\n\n constructor(storageType: 'localStorage' | 'sessionStorage', accessKey?: string, refreshKey?: string) {\n this.access = accessKey ? this.preffix + accessKey : this.access;\n this.refresh = refreshKey ? this.preffix + refreshKey : this.refresh;\n this.storageType = storageType;\n }\n\n saveToken(token: string, tokenType: TokenType): boolean {\n if (token) {\n window[this.storageType].setItem(this[tokenType], token);\n return true;\n }\n return false;\n }\n\n getToken(tokenType: TokenType): string {\n return window[this.storageType].getItem(this[tokenType]) ?? '';\n }\n\n deleteToken(tokenType: TokenType): void {\n window[this.storageType].removeItem(this[tokenType]);\n }\n}\n\nexport default StorageManager;\n","import StorageManager from './storage-manager';\n\nclass LocalStorage extends StorageManager {\n constructor(accessKey?: string, refreshKey?: string) {\n super('localStorage', accessKey, refreshKey);\n }\n}\n\nexport default LocalStorage;\n","import StorageManager from './storage-manager';\n\nclass SessionStorage extends StorageManager {\n constructor(accessKey?: string, refreshKey?: string) {\n super('sessionStorage', accessKey, refreshKey);\n }\n}\n\nexport default SessionStorage;\n","import { INVALID_TOKEN_ERROR } from './constants';\nimport { LocalStorageManager } from './store-manager';\nimport { ClientToken, JWTPayload, TokenManager, TokenType } from './types/types';\n\nclass TokenService {\n isAuth = false;\n\n private tokenManager: TokenManager;\n\n constructor(tokenManager?: TokenManager) {\n this.tokenManager = tokenManager || new LocalStorageManager();\n // TODO: implement cookie as default\n // this.tokenManager = tokenManager || new CoockieStorage();\n }\n\n async handleVerification(token: string, audience: string, issuer?: string): Promise {\n if (!this.tokenManager.isAccessible) return true;\n try {\n await this.validateToken(token, audience, issuer);\n this.saveToken(token);\n return true;\n } catch (err) {\n this.removeToken();\n return Promise.reject(err);\n }\n }\n\n async validateToken(token: string, audience: string, issuer?: string): Promise {\n if (!token) throw new Error(INVALID_TOKEN_ERROR);\n const jwtPayload = this.parseJWT(token);\n const isJwtExpired = this.isJWTExpired(jwtPayload);\n if (jwtPayload.aud?.includes(audience) && (!issuer || jwtPayload.iss === issuer) && !isJwtExpired) {\n return Promise.resolve(true);\n }\n throw new Error(INVALID_TOKEN_ERROR);\n }\n\n parseJWT(token: string): JWTPayload {\n const base64Url = token.split('.')[1];\n if (!base64Url) return { aud: [], iss: '', exp: 10 };\n const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');\n const jsonPayload = decodeURIComponent(\n atob(base64)\n .split('')\n .map((c) => `%${`00${c.charCodeAt(0).toString(16)}`.slice(-2)}`)\n .join(''),\n );\n return JSON.parse(jsonPayload) as JWTPayload;\n }\n\n isJWTExpired(token: JWTPayload): boolean {\n const now = new Date().getTime() / 1000;\n if (token.exp && now > token.exp) {\n return true;\n }\n return false;\n }\n\n saveToken(token: string, type: TokenType = 'access'): boolean {\n if (type === 'access') {\n this.isAuth = true;\n }\n return this.tokenManager.saveToken(token, type);\n }\n\n removeToken(type: TokenType = 'access'): void {\n if (type === 'access') {\n this.isAuth = false;\n }\n this.tokenManager.deleteToken(type);\n }\n\n getToken(type: TokenType = 'access'): ClientToken | null {\n const token = this.tokenManager.getToken(type);\n if (!token) return null;\n const jwtPayload = this.parseJWT(token);\n return { token, payload: jwtPayload };\n }\n}\n\nexport default TokenService;\n","import { IdentifoConfig, UrlFlows } from './types/types';\n\nexport class UrlBuilder {\n constructor(private config: IdentifoConfig) {}\n\n getUrl(flow: UrlFlows): string {\n const scopes = this.config.scopes?.join() || '';\n const redirectUri = this.config.redirectUri ?? window.location.href;\n const baseParams = `appId=${this.config.appId}&scopes=${scopes}`;\n const urlParams = `${baseParams}&callbackUrl=${encodeURIComponent(redirectUri)}`;\n // if postLogoutRedirectUri is empty, login url will be instead\n const postLogoutRedirectUri = this.config.postLogoutRedirectUri\n ? `${this.config.postLogoutRedirectUri}`\n : `${redirectUri}&redirectUri=${this.config.url}/web/login?${encodeURIComponent(baseParams)}`;\n\n const urls = {\n signup: `${this.config.url}/web/register?${urlParams}`,\n signin: `${this.config.url}/web/login?${urlParams}`,\n logout: `${this.config.url}/web/logout?${baseParams}&callbackUrl=${encodeURIComponent(postLogoutRedirectUri)}`,\n renew: `${this.config.url}/web/token/renew?${baseParams}&redirectUri=${encodeURIComponent(redirectUri)}`,\n default: 'default',\n };\n\n return urls[flow] || urls.default;\n }\n\n createSignupUrl(): string {\n return this.getUrl('signup');\n }\n\n createSigninUrl(): string {\n return this.getUrl('signin');\n }\n\n createLogoutUrl(): string {\n return this.getUrl('logout');\n }\n\n createRenewSessionUrl(): string {\n return this.getUrl('renew');\n }\n}\n","import { API } from './api/api';\nimport { jwtRegex, REFRESH_TOKEN_QUERY_KEY, TOKEN_QUERY_KEY } from './constants';\nimport TokenService from './tokenService';\nimport { ClientToken, IdentifoConfig, UrlBuilderInit } from './types/types';\nimport { UrlBuilder } from './UrlBuilder';\n\nclass IdentifoAuth {\n public api!: API;\n\n public tokenService!: TokenService;\n\n public config!: IdentifoConfig;\n\n public urlBuilder!: UrlBuilderInit;\n\n private token: ClientToken | null = null;\n\n get isAuth(): boolean {\n return !!this.tokenService?.isAuth;\n }\n\n constructor(config?: IdentifoConfig) {\n if (config) {\n this.configure(config);\n }\n }\n\n public configure(config: IdentifoConfig): void {\n this.config = { ...config, autoRenew: config.autoRenew ?? true };\n this.tokenService = new TokenService(config.tokenManager);\n this.urlBuilder = new UrlBuilder(this.config);\n this.api = new API(config, this.tokenService);\n this.handleToken(this.tokenService.getToken()?.token || '', 'access');\n }\n\n private handleToken(token: string, tokenType: 'access' | 'refresh') {\n if (token) {\n if (tokenType === 'access') {\n const payload = this.tokenService.parseJWT(token);\n this.token = { token, payload };\n this.tokenService.saveToken(token);\n } else {\n this.tokenService.saveToken(token, 'refresh');\n }\n }\n }\n\n private resetAuthValues() {\n this.token = null;\n this.tokenService.removeToken();\n this.tokenService.removeToken('refresh');\n }\n\n signup(): void {\n window.location.href = this.urlBuilder.createSignupUrl();\n }\n\n signin(): void {\n window.location.href = this.urlBuilder.createSigninUrl();\n }\n\n logout(): void {\n this.resetAuthValues();\n window.location.href = this.urlBuilder.createLogoutUrl();\n }\n\n async handleAuthentication(): Promise {\n const { access, refresh } = this.getTokenFromUrl();\n if (!access) {\n this.resetAuthValues();\n return Promise.reject();\n }\n try {\n await this.tokenService.handleVerification(access, this.config.appId, this.config.issuer);\n this.handleToken(access, 'access');\n if (refresh) {\n this.handleToken(refresh, 'refresh');\n }\n return await Promise.resolve(true);\n } catch (err) {\n this.resetAuthValues();\n return await Promise.reject();\n } finally {\n window.history.pushState({}, document.title, window.location.pathname);\n }\n }\n\n private getTokenFromUrl(): { access: string; refresh: string } {\n const urlParams = new URLSearchParams(window.location.search);\n const tokens = { access: '', refresh: '' };\n const accessToken = urlParams.get(TOKEN_QUERY_KEY);\n const refreshToken = urlParams.get(REFRESH_TOKEN_QUERY_KEY);\n if (refreshToken && jwtRegex.test(refreshToken)) {\n tokens.refresh = refreshToken;\n }\n if (accessToken && jwtRegex.test(accessToken)) {\n tokens.access = accessToken;\n }\n return tokens;\n }\n\n async getToken(): Promise {\n const token = this.tokenService.getToken();\n const refreshToken = this.tokenService.getToken('refresh');\n if (token) {\n const isExpired = this.tokenService.isJWTExpired(token.payload);\n if (isExpired && refreshToken) {\n try {\n await this.renewSession();\n return await Promise.resolve(this.token);\n } catch (err) {\n this.resetAuthValues();\n throw new Error('No token');\n }\n }\n return Promise.resolve(token);\n }\n return Promise.resolve(null);\n }\n\n async renewSession(): Promise {\n try {\n const { access, refresh } = await this.renewSessionWithToken();\n this.handleToken(access, 'access');\n this.handleToken(refresh, 'refresh');\n return await Promise.resolve(access);\n } catch (err) {\n return Promise.reject();\n }\n }\n\n private async renewSessionWithToken(): Promise<{ access: string; refresh: string }> {\n try {\n const tokens = await this.api\n .renewToken()\n .then((l) => ({ access: l.access_token || '', refresh: l.refresh_token || '' }));\n return tokens;\n } catch (err) {\n return Promise.reject(err);\n }\n }\n}\nexport default IdentifoAuth;\n","import {\n ApiError,\n FederatedLoginProvider,\n LoginResponse,\n ServerSettingsLoginTypes,\n TFAStatus,\n TFAType,\n SuccessResponse,\n} from '../api/model';\n\nexport enum Routes {\n 'LOGIN' = 'login',\n 'REGISTER' = 'register',\n 'TFA_VERIFY_SMS' = 'tfa/verify/sms',\n 'TFA_VERIFY_EMAIL' = 'tfa/verify/email',\n 'TFA_VERIFY_APP' = 'tfa/verify/app',\n 'TFA_VERIFY_SELECT' = 'tfa/verify/select',\n 'TFA_SETUP_SMS' = 'tfa/setup/sms',\n 'TFA_SETUP_EMAIL' = 'tfa/setup/email',\n 'TFA_SETUP_APP' = 'tfa/setup/app',\n 'TFA_SETUP_SELECT' = 'tfa/setup/select',\n 'PASSWORD_RESET' = 'password/reset',\n 'PASSWORD_FORGOT' = 'password/forgot',\n 'PASSWORD_FORGOT_TFA_SMS' = 'password/forgot/tfa/sms',\n 'PASSWORD_FORGOT_TFA_EMAIL' = 'password/forgot/tfa/email',\n 'PASSWORD_FORGOT_TFA_APP' = 'password/forgot/tfa/app',\n 'PASSWORD_FORGOT_TFA_SELECT' = 'password/forgot/tfa/select',\n 'CALLBACK' = 'callback',\n 'LOGIN_PHONE' = 'login_phone',\n 'LOGIN_OIDC' = 'login_oidc',\n 'LOGIN_PHONE_VERIFY' = 'login_phone_verify',\n 'ERROR' = 'error',\n 'PASSWORD_FORGOT_SUCCESS' = 'password/forgot/success',\n 'LOGOUT' = 'logout',\n 'LOADING' = 'loading',\n}\n\nexport type TFASetupRoutes =\n | Routes.TFA_SETUP_SELECT\n | Routes.TFA_SETUP_SMS\n | Routes.TFA_SETUP_EMAIL\n | Routes.TFA_SETUP_APP;\nexport type TFALoginVerifyRoutes =\n | Routes.TFA_VERIFY_SELECT\n | Routes.TFA_VERIFY_SMS\n | Routes.TFA_VERIFY_EMAIL\n | Routes.TFA_VERIFY_APP;\nexport type TFAResetVerifyRoutes =\n | Routes.PASSWORD_FORGOT_TFA_SELECT\n | Routes.PASSWORD_FORGOT_TFA_SMS\n | Routes.PASSWORD_FORGOT_TFA_EMAIL\n | Routes.PASSWORD_FORGOT_TFA_APP;\n\nexport interface State {\n route: Routes;\n}\n\nexport interface StateWithError {\n error?: ApiError;\n}\n\nexport type LoginTypes = Partial<\n Record void; type: keyof ServerSettingsLoginTypes }>\n>;\n\nexport interface StateLogin extends State, StateWithError {\n route: Routes.LOGIN;\n registrationForbidden: boolean;\n federatedProviders: FederatedLoginProvider[];\n loginTypes: LoginTypes;\n signup: () => Promise;\n signin: (email: string, password: string, remember?: boolean) => Promise;\n socialLogin: (provider: FederatedLoginProvider) => Promise;\n passwordForgot: () => Promise;\n}\n\nexport interface StateLoginOidc extends State, StateWithError {\n route: Routes.LOGIN_OIDC;\n oidcLink: string;\n verify: (state?: string, code?: string) => Promise;\n}\n\nexport interface StateLoginPhone extends State, StateWithError {\n route: Routes.LOGIN_PHONE;\n registrationForbidden: boolean;\n federatedProviders: FederatedLoginProvider[];\n loginTypes: LoginTypes;\n requestCode: (phone: string) => Promise;\n socialLogin: (provider: FederatedLoginProvider) => Promise;\n}\nexport interface StateLoginPhoneVerify extends State, StateWithError {\n route: Routes.LOGIN_PHONE_VERIFY;\n phone: string;\n resendTimeout: number;\n resendCode: () => Promise;\n login: (code: string) => Promise;\n goback: () => Promise;\n}\n\nexport interface StateRegister extends State, StateWithError {\n route: Routes.REGISTER;\n signup: (email: string, password: string, token?: string) => Promise;\n goback: () => Promise;\n}\n\nexport interface StatePasswordForgot extends State, StateWithError {\n route: Routes.PASSWORD_FORGOT;\n restorePassword: (email: string) => Promise;\n goback: () => Promise;\n}\nexport interface StatePasswordForgotSuccess extends State {\n route: Routes.PASSWORD_FORGOT_SUCCESS;\n goback: () => Promise;\n}\n\nexport interface StateError extends State, StateWithError {\n route: Routes.ERROR;\n}\n\nexport interface StateCallback extends State {\n route: Routes.CALLBACK;\n callbackUrl?: string;\n result: LoginResponse;\n}\n\nexport interface StatePasswordReset extends State, StateWithError {\n route: Routes.PASSWORD_RESET;\n setNewPassword: (password: string) => Promise;\n}\n\nexport interface StateLoading extends State {\n route: Routes.LOADING;\n}\n\ninterface StateTFASetup extends State, StateWithError {}\n\nexport interface StateTFASetupApp extends StateTFASetup {\n route: Routes.TFA_SETUP_APP;\n provisioningURI: string;\n provisioningQR: string;\n setupTFA: () => Promise;\n}\nexport interface StateTFASetupEmail extends StateTFASetup {\n route: Routes.TFA_SETUP_EMAIL;\n email: string;\n setupTFA: (email: string) => Promise;\n}\nexport interface StateTFASetupSMS extends StateTFASetup {\n route: Routes.TFA_SETUP_SMS;\n phone: string;\n setupTFA: (phone: string) => Promise;\n}\n\ninterface StateTFASelect extends State {\n tfaTypes: TFAType[];\n select: (type: TFAType) => Promise;\n email?: string;\n phone?: string;\n}\n\nexport interface StateTFASetupSelect extends StateTFASelect {\n route: Routes.TFA_SETUP_SELECT;\n tfaStatus: TFAStatus;\n setupNextTime: () => Promise;\n}\nexport interface StateTFAVerifySelect extends StateTFASelect {\n route: Routes.TFA_VERIFY_SELECT;\n}\nexport interface StatePasswordForgotTFASelect extends StateTFASelect {\n route: Routes.PASSWORD_FORGOT_TFA_SELECT;\n}\n\nexport interface StateTFAVerifyApp extends State, StateWithError {\n route: Routes.TFA_VERIFY_APP;\n email?: string;\n phone?: string;\n verifyTFA: (code: string) => Promise;\n}\n\nexport interface StateTFAVerifyEmailSms extends State, StateWithError {\n route: Routes.TFA_VERIFY_EMAIL | Routes.TFA_VERIFY_SMS;\n email?: string;\n phone?: string;\n resendTimeout: number;\n verifyTFA: (code: string) => Promise;\n resendTFA: () => Promise;\n}\n\nexport interface StatePasswordForgotTFAVerify extends State, StateWithError {\n route: Routes.PASSWORD_FORGOT_TFA_APP | Routes.PASSWORD_FORGOT_TFA_EMAIL | Routes.PASSWORD_FORGOT_TFA_SMS;\n email?: string;\n phone?: string;\n verifyTFA: (code: string) => Promise;\n}\n\nexport interface StateLogout extends State {\n route: Routes.LOGOUT;\n logout: () => Promise;\n}\n\nexport const typeToSetupRoute = {\n [TFAType.TFATypeApp]: Routes.TFA_SETUP_APP,\n [TFAType.TFATypeEmail]: Routes.TFA_SETUP_EMAIL,\n [TFAType.TFATypeSMS]: Routes.TFA_SETUP_SMS,\n};\n\nexport const typeToTFAVerifyRoute = {\n [TFAType.TFATypeApp]: Routes.TFA_VERIFY_APP,\n [TFAType.TFATypeEmail]: Routes.TFA_VERIFY_EMAIL,\n [TFAType.TFATypeSMS]: Routes.TFA_VERIFY_SMS,\n};\nexport const typeToPasswordForgotTFAVerifyRoute = {\n [TFAType.TFATypeApp]: Routes.PASSWORD_FORGOT_TFA_APP,\n [TFAType.TFATypeEmail]: Routes.PASSWORD_FORGOT_TFA_EMAIL,\n [TFAType.TFATypeSMS]: Routes.PASSWORD_FORGOT_TFA_SMS,\n};\n\n// TODO exclude generalState\nexport type States =\n | State\n | StateTFASetupApp\n | StateTFASetupEmail\n | StateTFASetupSMS\n | StatePasswordReset\n | StatePasswordForgot\n | StatePasswordForgotSuccess\n | StateLoading\n | StateCallback\n | StateLogin\n | StateRegister\n | StateError\n | StateLoginOidc;\n","import { BehaviorSubject } from 'rxjs';\nimport { StateLoginPhone, StateLoginPhoneVerify } from '..';\nimport {\n ApiError,\n APIErrorCodes,\n AppSettingsResponse,\n FederatedLoginProvider,\n LoginResponse,\n ServerSettingsLoginTypes,\n TFAStatus,\n TFAType,\n} from '../api/model';\nimport IdentifoAuth from '../IdentifoAuth';\nimport { IdentifoConfig } from '../types/types';\nimport {\n LoginTypes,\n Routes,\n State,\n StateCallback,\n StateError,\n StateLoginOidc,\n StateLogout,\n StatePasswordForgotTFASelect,\n StatePasswordForgotTFAVerify,\n States,\n StateTFASetupSelect,\n StateTFAVerifyApp,\n StateTFAVerifyEmailSms,\n StateTFAVerifySelect,\n StateWithError,\n typeToPasswordForgotTFAVerifyRoute,\n typeToTFAVerifyRoute,\n} from './model';\n\nconst emailRegex =\n // eslint-disable-next-line max-len\n /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;\n\nconst phoneRegex = /^[\\+][0-9]{9,15}$/;\n\nexport class CDK {\n auth: IdentifoAuth;\n\n settings!: AppSettingsResponse;\n\n lastError!: ApiError;\n\n callbackUrl?: string;\n\n postLogoutRedirectUri?: string;\n\n scopes: Set = new Set();\n\n state: BehaviorSubject = new BehaviorSubject({ route: Routes.LOADING } as States);\n\n constructor() {\n this.auth = new IdentifoAuth();\n }\n\n // eslint-disable-next-line max-statements\n async configure(authConfig: IdentifoConfig, callbackUrl: string): Promise {\n this.state.next({ route: Routes.LOADING });\n\n this.callbackUrl = callbackUrl;\n this.scopes = new Set(authConfig.scopes ?? []);\n\n this.postLogoutRedirectUri = window.location.origin + window.location.pathname;\n // this.postLogoutRedirectUri = this.postLogoutRedirectUri || window.location.origin + window.location.pathname;\n\n if (!authConfig.appId) {\n this.state.next({\n route: Routes.ERROR,\n error: { message: 'app-id param is empty', name: 'app-id empty' },\n } as StateError);\n return;\n }\n if (!authConfig.url) {\n this.state.next({\n route: Routes.ERROR,\n error: { message: 'url param is empty', name: 'url empty' },\n } as StateError);\n return;\n }\n\n this.auth.configure(authConfig);\n try {\n this.settings = await this.auth.api.getAppSettings(callbackUrl);\n } catch (err) {\n this.state.next({\n route: Routes.ERROR,\n error: err as ApiError,\n } as StateError);\n return;\n }\n this.settings.tfaType = Array.isArray(this.settings.tfaType) ? this.settings.tfaType : [this.settings.tfaType];\n\n // // If we have provider and state then we need to complete federated login\n const href = new URL(window.location.href);\n if (!!href.searchParams.get('provider') && !!href.searchParams.get('state')) {\n // Also we clear all url params after parsing\n const u = new URL(window.location.href);\n const sp = new URLSearchParams();\n const appId = href.searchParams.get('appId');\n if (appId === null) {\n this.state.next({\n route: Routes.ERROR,\n error: { message: 'app-id param is empty', name: 'app-id empty' },\n } as StateError);\n return;\n }\n sp.set('appId', appId);\n window.history.replaceState({}, document.title, `${u.pathname}?${sp.toString()}`);\n this.auth.api\n .federatedLoginComplete(u.searchParams)\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n }\n }\n\n login(): void {\n // check for allowed login with\n switch (true) {\n case (!this.auth.config.loginWith && this.settings.loginWith['phone']) ||\n (this.auth.config.loginWith === 'phone' && this.settings.loginWith['phone']):\n return this.loginWithPhone();\n case (!this.auth.config.loginWith && this.settings.loginWith['email']) ||\n (this.auth.config.loginWith === 'email' && this.settings.loginWith['email']):\n return this.loginWithPassword();\n case (!this.auth.config.loginWith && this.settings.loginWith['federated_oidc']) ||\n (this.auth.config.loginWith === 'federated_oidc' && this.settings.loginWith['federated_oidc']):\n return this.loginWithOIDC();\n default:\n throw 'Unsupported login way';\n }\n }\n loginWithPhone(): void {\n this.state.next({\n route: Routes.LOGIN_PHONE,\n registrationForbidden: this.settings?.registrationForbidden,\n error: this.lastError,\n federatedProviders: this.settings?.federatedProviders,\n loginTypes: this.getLoginTypes('phone'),\n requestCode: async (phone: string, remember?: boolean): Promise => {\n if (!this.validatePhone(phone)) {\n return;\n }\n const scopes = new Set(this.scopes);\n if (remember) {\n scopes.add('offline');\n }\n await this.auth.api\n .requestPhoneCode(phone)\n .then(() => this.loginWithPhoneVerify(phone, remember))\n .catch((e) => this.processError(e));\n },\n socialLogin: async (provider: FederatedLoginProvider) => {\n this.state.next({ route: Routes.LOADING });\n const federatedRedirectUrl = window.location.origin + window.location.pathname;\n return this.auth.api.federatedLogin(\n provider,\n [...Array.from(this.scopes)],\n federatedRedirectUrl,\n this.callbackUrl,\n );\n },\n } as StateLoginPhone);\n }\n loginWithPhoneVerify(phone: string, remember?: boolean): void {\n this.state.next({\n route: Routes.LOGIN_PHONE_VERIFY,\n error: this.lastError,\n phone: phone,\n resendTimeout: this.settings.tfaResendTimeout * 1000,\n resendCode: async () => {\n await this.auth.api.requestPhoneCode(phone);\n },\n login: async (code: string): Promise => {\n const scopes = new Set(this.scopes);\n if (remember) {\n scopes.add('offline');\n }\n await this.auth.api\n .phoneLogin(phone, code, [...Array.from(this.scopes)])\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n goback: async (): Promise => {\n this.login();\n },\n } as StateLoginPhoneVerify);\n }\n\n loginWithOIDC(): void {\n this.state.next({\n route: Routes.LOGIN_OIDC,\n oidcLink: this.settings.federatedOIDCInitURL,\n error: this.lastError,\n verify: async (state?: string, code?: string) => {\n if (!state || !code) {\n return;\n }\n this.auth.api\n .oidcVerify({ state, code, scopes: [...Array.from(this.scopes)] })\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n } as StateLoginOidc);\n }\n\n loginWithPassword(): void {\n this.state.next({\n route: Routes.LOGIN,\n registrationForbidden: this.settings?.registrationForbidden,\n error: this.lastError,\n federatedProviders: this.settings?.federatedProviders,\n loginTypes: this.getLoginTypes('email'),\n signup: async (): Promise => {\n this.register();\n },\n signin: async (email: string, password: string, remember?: boolean): Promise => {\n if (!this.validateEmail(email)) {\n return;\n }\n const scopes = new Set(this.scopes);\n if (remember) {\n scopes.add('offline');\n }\n await this.auth.api\n .login(email, password, '', [...Array.from(scopes)])\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n socialLogin: async (provider: FederatedLoginProvider) => {\n this.state.next({ route: Routes.LOADING });\n const federatedRedirectUrl = window.location.origin + window.location.pathname;\n return this.auth.api.federatedLogin(\n provider,\n [...Array.from(this.scopes)],\n federatedRedirectUrl,\n this.callbackUrl,\n );\n },\n passwordForgot: async () => {\n this.forgotPassword();\n },\n });\n }\n\n register(): void {\n this.state.next({\n route: Routes.REGISTER,\n signup: async (email: string, password: string, token?: string): Promise => {\n if (!this.validateEmail(email)) {\n return;\n }\n await this.auth.api\n .register(email, password, [...Array.from(this.scopes)], token)\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n\n forgotPassword(): void {\n this.state.next({\n route: Routes.PASSWORD_FORGOT,\n restorePassword: async (email: string): Promise => {\n return this.auth.api\n .requestResetPassword(email)\n .then(async (response) => {\n if (response.result === 'tfa-required') {\n await this.redirectTfaForgot(email);\n return;\n }\n if (response.result === 'ok') {\n this.forgotPasswordSuccess();\n }\n })\n .catch((e) => this.processError(e));\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n\n forgotPasswordSuccess(): void {\n this.state.next({\n route: Routes.PASSWORD_FORGOT_SUCCESS,\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n\n passwordReset(): void {\n this.state.next({\n route: Routes.PASSWORD_RESET,\n setNewPassword: async (password: string): Promise => {\n this.auth.api\n .resetPassword(password)\n .then(() => {\n this.login();\n })\n .catch((e) => this.processError(e));\n },\n });\n }\n\n callback(result: LoginResponse): void {\n this.state.next({\n route: Routes.CALLBACK,\n callbackUrl: this.callbackUrl,\n result,\n } as StateCallback);\n if (this.callbackUrl) {\n const url = new URL(this.callbackUrl);\n if (result.access_token) {\n url.searchParams.set('token', result.access_token);\n }\n if (result.refresh_token) {\n url.searchParams.set('refresh_token', result.refresh_token);\n }\n window.location.href = url.toString();\n }\n }\n\n validateEmail(email: string): boolean {\n if (!emailRegex.test(email)) {\n this.processError({\n detailedMessage: 'Email address is not valid',\n name: 'Validation error',\n message: 'Email address is not valid',\n } as ApiError);\n return false;\n }\n return true;\n }\n\n validatePhone(email: string): boolean {\n if (!phoneRegex.test(email)) {\n this.processError({\n detailedMessage: 'Phone is not valid',\n name: 'Validation error',\n message: 'Phone is not valid',\n } as ApiError);\n return false;\n }\n return true;\n }\n\n async tfaSetup(loginResponse: LoginResponse, type: TFAType): Promise {\n switch (type) {\n case TFAType.TFATypeApp: {\n this.state.next({\n route: Routes.TFA_SETUP_APP,\n provisioningURI: '',\n provisioningQR: '',\n setupTFA: async () => {},\n goback: async (): Promise => {\n this.login();\n },\n });\n const tfa = await this.auth.api.enableTFA({});\n if (tfa.provisioning_uri) {\n this.state.next({\n route: Routes.TFA_SETUP_APP,\n provisioningURI: tfa.provisioning_uri,\n provisioningQR: tfa.provisioning_qr || '',\n setupTFA: async () => this.tfaVerify(loginResponse, type),\n goback: async (): Promise => {\n this.login();\n },\n });\n }\n break;\n }\n case TFAType.TFATypeEmail: {\n this.state.next({\n route: Routes.TFA_SETUP_EMAIL,\n email: loginResponse.user.email || '',\n setupTFA: async (email: string) => {\n await this.auth.api.enableTFA({ email });\n return this.tfaVerify({ ...loginResponse, user: { ...loginResponse.user, email } }, type);\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n break;\n }\n case TFAType.TFATypeSMS: {\n this.state.next({\n route: Routes.TFA_SETUP_SMS,\n phone: loginResponse.user.phone || '',\n setupTFA: async (phone: string) => {\n await this.auth.api.enableTFA({ phone });\n return this.tfaVerify({ ...loginResponse, user: { ...loginResponse.user, phone } }, type);\n },\n goback: async (): Promise => {\n this.login();\n },\n });\n break;\n }\n default:\n }\n }\n\n async tfaVerify(loginResponse: LoginResponse, type: TFAType): Promise {\n const state = {\n route: typeToTFAVerifyRoute[type],\n email: loginResponse.user.email,\n phone: loginResponse.user.phone,\n verifyTFA: async (code: string) => {\n await this.auth.api\n .verifyTFA(code, [...Array.from(this.scopes)])\n .then(this.afterLoginRedirect)\n .catch(this.loginCatchRedirect)\n .catch((e) => this.processError(e));\n },\n };\n switch (type) {\n case TFAType.TFATypeApp: {\n this.state.next({ ...state } as StateTFAVerifyApp);\n break;\n }\n case TFAType.TFATypeEmail:\n case TFAType.TFATypeSMS: {\n this.state.next({\n ...state,\n resendTimeout: this.settings.tfaResendTimeout * 1000, // in ms\n resendTFA: async () => {\n await this.auth.api.resendTFA();\n },\n } as StateTFAVerifyEmailSms);\n break;\n }\n default:\n }\n }\n\n async passwordForgotTFAVerify(email: string, type: TFAType): Promise {\n this.state.next({\n route: typeToPasswordForgotTFAVerifyRoute[type],\n verifyTFA: async (code: string) => {\n this.auth.api\n .requestResetPassword(email, code)\n .then(() => {\n this.forgotPasswordSuccess();\n })\n .catch((e) => this.processError(e));\n },\n } as StatePasswordForgotTFAVerify);\n }\n\n async logout(): Promise {\n this.state.next({\n route: Routes.LOGOUT,\n logout: async () => this.auth.api.logout(),\n } as StateLogout);\n }\n\n // restorePassword(token: string): void {}\n\n private processError(e: ApiError) {\n e.detailedMessage = e.detailedMessage?.trim();\n e.message = e.message?.trim();\n\n this.state.next({\n ...this.state.getValue(),\n error: e,\n } as State & StateWithError);\n }\n\n private async redirectTfaSetup(loginResponse: LoginResponse): Promise {\n if (this.settings.tfaType.length === 1) {\n await this.tfaSetup(loginResponse, this.settings.tfaType[0] as TFAType);\n return;\n }\n this.tfaSetupSelect(loginResponse);\n }\n\n private tfaSetupSelect(loginResponse: LoginResponse): void {\n this.state.next({\n route: Routes.TFA_SETUP_SELECT,\n tfaStatus: this.settings.tfaStatus,\n tfaTypes: this.settings.tfaType,\n select: async (type: TFAType) => {\n await this.tfaSetup(loginResponse, type);\n },\n setupNextTime: () => {\n this.callback(loginResponse);\n },\n } as StateTFASetupSelect);\n }\n\n private async redirectTfaVerify(e: LoginResponse): Promise {\n if (this.settings.tfaType.length === 1) {\n await this.tfaVerify(e, this.settings.tfaType[0] as TFAType);\n return;\n }\n this.state.next({\n route: Routes.TFA_VERIFY_SELECT,\n tfaStatus: this.settings.tfaStatus,\n tfaTypes: this.settings.tfaType,\n select: async (type: TFAType) => {\n await this.tfaVerify(e, type);\n },\n } as StateTFAVerifySelect);\n }\n\n private async redirectTfaForgot(email: string): Promise {\n if (this.settings.tfaType.length === 1) {\n await this.passwordForgotTFAVerify(email, this.settings.tfaType[0] as TFAType);\n return;\n }\n this.state.next({\n route: Routes.PASSWORD_FORGOT_TFA_SELECT,\n tfaStatus: this.settings.tfaStatus,\n tfaTypes: this.settings.tfaType,\n select: async (type: TFAType) => {\n await this.passwordForgotTFAVerify(email, type);\n },\n } as StatePasswordForgotTFASelect);\n }\n\n // eslint-disable-next-line complexity\n private afterLoginRedirect = async (loginResponse: LoginResponse): Promise => {\n if (loginResponse.require_2fa) {\n if (!loginResponse.enabled_2fa) {\n await this.redirectTfaSetup(loginResponse);\n return;\n }\n if (loginResponse.enabled_2fa) {\n await this.redirectTfaVerify(loginResponse);\n return;\n }\n }\n // Ask about tfa on login only\n if (\n this.settings.tfaStatus === TFAStatus.OPTIONAL &&\n [Routes.LOGIN, Routes.REGISTER].includes(this.state.getValue().route)\n ) {\n this.tfaSetupSelect(loginResponse);\n return;\n }\n if (loginResponse.access_token && loginResponse.refresh_token) {\n this.callback(loginResponse);\n return;\n }\n if (loginResponse.access_token && !loginResponse.refresh_token) {\n this.callback(loginResponse);\n return;\n }\n this.login();\n };\n\n private loginCatchRedirect = (data: ApiError): void => {\n if (data.id === APIErrorCodes.PleaseEnableTFA) {\n // this.redirectTfaSetup();\n return;\n }\n throw data;\n };\n private getLoginTypes(current: keyof ServerSettingsLoginTypes): LoginTypes {\n const result: LoginTypes = {};\n Object.entries(this.settings.loginWith)\n .filter((v) => v[1] && v[0] !== current)\n .forEach((v) => {\n result[v[0] as keyof ServerSettingsLoginTypes] = {\n type: v[0] as keyof ServerSettingsLoginTypes,\n click: () => {\n this.auth.config.loginWith = v[0] as keyof ServerSettingsLoginTypes;\n this.login();\n },\n };\n });\n return result;\n }\n}\n"],"names":["__async","__spreadValues","LocalStorageManager","__spreadProps"],"mappings":"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"} \ No newline at end of file diff --git a/web_apps_src/identifo.js/package.json b/web_apps_src/identifo.js/package.json index 122ce542..d3f37270 100644 --- a/web_apps_src/identifo.js/package.json +++ b/web_apps_src/identifo.js/package.json @@ -1,6 +1,6 @@ { "name": "@identifo/identifo-auth-js", - "version": "3.3.4", + "version": "3.3.9", "description": "Library for web-auth through Identifo", "main": "./dist/identifo.js", "module": "./dist/identifo.mjs", diff --git a/web_apps_src/identifo.js/src/api/api.ts b/web_apps_src/identifo.js/src/api/api.ts index ac9e1797..070128a5 100644 --- a/web_apps_src/identifo.js/src/api/api.ts +++ b/web_apps_src/identifo.js/src/api/api.ts @@ -298,6 +298,13 @@ export class API { }); } + async oidcVerify(data: { state: string; code: string; scopes: string[] }): Promise { + const url = `/auth/federated/oidc/complete?appId=${this.appId}&state=${data.state}&code=${data.code}`; + return this.post(url, { scopes: data.scopes }, { credentials: 'include' }).then((r) => + this.storeToken(r), + ); + } + async invite(email: string, role: string, callbackUrl: string): Promise { if (!this.tokenService.getToken()?.token) { throw new Error('No token in token service.'); diff --git a/web_apps_src/identifo.js/src/api/model.ts b/web_apps_src/identifo.js/src/api/model.ts index 29fb4697..5e0df811 100644 --- a/web_apps_src/identifo.js/src/api/model.ts +++ b/web_apps_src/identifo.js/src/api/model.ts @@ -20,6 +20,7 @@ export enum TFAStatus { export interface ServerSettingsLoginTypes { email: boolean; federated: boolean; + federated_oidc: boolean; phone: boolean; username: boolean; } @@ -87,6 +88,7 @@ export interface AppSettingsResponse { tfaStatus: TFAStatus; federatedProviders: FederatedLoginProvider[]; loginWith: ServerSettingsLoginTypes; + federatedOIDCInitURL: string; } export interface User { diff --git a/web_apps_src/identifo.js/src/cdk/cdk.ts b/web_apps_src/identifo.js/src/cdk/cdk.ts index 01d99a96..e86dd2aa 100644 --- a/web_apps_src/identifo.js/src/cdk/cdk.ts +++ b/web_apps_src/identifo.js/src/cdk/cdk.ts @@ -18,6 +18,7 @@ import { State, StateCallback, StateError, + StateLoginOidc, StateLogout, StatePasswordForgotTFASelect, StatePasswordForgotTFAVerify, @@ -126,6 +127,9 @@ export class CDK { case (!this.auth.config.loginWith && this.settings.loginWith['email']) || (this.auth.config.loginWith === 'email' && this.settings.loginWith['email']): return this.loginWithPassword(); + case (!this.auth.config.loginWith && this.settings.loginWith['federated_oidc']) || + (this.auth.config.loginWith === 'federated_oidc' && this.settings.loginWith['federated_oidc']): + return this.loginWithOIDC(); default: throw 'Unsupported login way'; } @@ -187,6 +191,25 @@ export class CDK { }, } as StateLoginPhoneVerify); } + + loginWithOIDC(): void { + this.state.next({ + route: Routes.LOGIN_OIDC, + oidcLink: this.settings.federatedOIDCInitURL, + error: this.lastError, + verify: async (state?: string, code?: string) => { + if (!state || !code) { + return; + } + this.auth.api + .oidcVerify({ state, code, scopes: [...Array.from(this.scopes)] }) + .then(this.afterLoginRedirect) + .catch(this.loginCatchRedirect) + .catch((e) => this.processError(e)); + }, + } as StateLoginOidc); + } + loginWithPassword(): void { this.state.next({ route: Routes.LOGIN, diff --git a/web_apps_src/identifo.js/src/cdk/model.ts b/web_apps_src/identifo.js/src/cdk/model.ts index 1061194a..ae80490e 100644 --- a/web_apps_src/identifo.js/src/cdk/model.ts +++ b/web_apps_src/identifo.js/src/cdk/model.ts @@ -27,6 +27,7 @@ export enum Routes { 'PASSWORD_FORGOT_TFA_SELECT' = 'password/forgot/tfa/select', 'CALLBACK' = 'callback', 'LOGIN_PHONE' = 'login_phone', + 'LOGIN_OIDC' = 'login_oidc', 'LOGIN_PHONE_VERIFY' = 'login_phone_verify', 'ERROR' = 'error', 'PASSWORD_FORGOT_SUCCESS' = 'password/forgot/success', @@ -73,6 +74,12 @@ export interface StateLogin extends State, StateWithError { passwordForgot: () => Promise; } +export interface StateLoginOidc extends State, StateWithError { + route: Routes.LOGIN_OIDC; + oidcLink: string; + verify: (state?: string, code?: string) => Promise; +} + export interface StateLoginPhone extends State, StateWithError { route: Routes.LOGIN_PHONE; registrationForbidden: boolean; @@ -221,4 +228,5 @@ export type States = | StateCallback | StateLogin | StateRegister - | StateError; + | StateError + | StateLoginOidc; diff --git a/web_apps_src/web-element/package-lock.json b/web_apps_src/web-element/package-lock.json index 8091840b..c2eb271e 100644 --- a/web_apps_src/web-element/package-lock.json +++ b/web_apps_src/web-element/package-lock.json @@ -26,7 +26,7 @@ }, "../identifo.js": { "name": "@identifo/identifo-auth-js", - "version": "3.3.4", + "version": "3.3.5", "license": "MIT", "dependencies": { "axios": "^0.21.1", diff --git a/web_apps_src/web-element/src/components.d.ts b/web_apps_src/web-element/src/components.d.ts index 4e7cc3a5..de7fae22 100755 --- a/web_apps_src/web-element/src/components.d.ts +++ b/web_apps_src/web-element/src/components.d.ts @@ -34,6 +34,8 @@ export namespace Components { } interface IdentifoFormLogin { } + interface IdentifoFormLoginOidc { + } interface IdentifoFormLoginPhone { } interface IdentifoFormLoginPhoneVerify { @@ -106,6 +108,12 @@ declare global { prototype: HTMLIdentifoFormLoginElement; new (): HTMLIdentifoFormLoginElement; }; + interface HTMLIdentifoFormLoginOidcElement extends Components.IdentifoFormLoginOidc, HTMLStencilElement { + } + var HTMLIdentifoFormLoginOidcElement: { + prototype: HTMLIdentifoFormLoginOidcElement; + new (): HTMLIdentifoFormLoginOidcElement; + }; interface HTMLIdentifoFormLoginPhoneElement extends Components.IdentifoFormLoginPhone, HTMLStencilElement { } var HTMLIdentifoFormLoginPhoneElement: { @@ -181,6 +189,7 @@ declare global { "identifo-form-forgot-success": HTMLIdentifoFormForgotSuccessElement; "identifo-form-goback": HTMLIdentifoFormGobackElement; "identifo-form-login": HTMLIdentifoFormLoginElement; + "identifo-form-login-oidc": HTMLIdentifoFormLoginOidcElement; "identifo-form-login-phone": HTMLIdentifoFormLoginPhoneElement; "identifo-form-login-phone-verify": HTMLIdentifoFormLoginPhoneVerifyElement; "identifo-form-login-ways": HTMLIdentifoFormLoginWaysElement; @@ -224,6 +233,8 @@ declare namespace LocalJSX { } interface IdentifoFormLogin { } + interface IdentifoFormLoginOidc { + } interface IdentifoFormLoginPhone { } interface IdentifoFormLoginPhoneVerify { @@ -255,6 +266,7 @@ declare namespace LocalJSX { "identifo-form-forgot-success": IdentifoFormForgotSuccess; "identifo-form-goback": IdentifoFormGoback; "identifo-form-login": IdentifoFormLogin; + "identifo-form-login-oidc": IdentifoFormLoginOidc; "identifo-form-login-phone": IdentifoFormLoginPhone; "identifo-form-login-phone-verify": IdentifoFormLoginPhoneVerify; "identifo-form-login-ways": IdentifoFormLoginWays; @@ -280,6 +292,7 @@ declare module "@stencil/core" { "identifo-form-forgot-success": LocalJSX.IdentifoFormForgotSuccess & JSXBase.HTMLAttributes; "identifo-form-goback": LocalJSX.IdentifoFormGoback & JSXBase.HTMLAttributes; "identifo-form-login": LocalJSX.IdentifoFormLogin & JSXBase.HTMLAttributes; + "identifo-form-login-oidc": LocalJSX.IdentifoFormLoginOidc & JSXBase.HTMLAttributes; "identifo-form-login-phone": LocalJSX.IdentifoFormLoginPhone & JSXBase.HTMLAttributes; "identifo-form-login-phone-verify": LocalJSX.IdentifoFormLoginPhoneVerify & JSXBase.HTMLAttributes; "identifo-form-login-ways": LocalJSX.IdentifoFormLoginWays & JSXBase.HTMLAttributes; diff --git a/web_apps_src/web-element/src/components/forms/login_oidc.tsx b/web_apps_src/web-element/src/components/forms/login_oidc.tsx new file mode 100644 index 00000000..34d09ba6 --- /dev/null +++ b/web_apps_src/web-element/src/components/forms/login_oidc.tsx @@ -0,0 +1,54 @@ +import { StateLoginOidc } from '@identifo/identifo-auth-js'; +import { Component, h, State } from '@stencil/core'; +import { Subscription } from 'rxjs'; + +import { CDKService } from '../../services/cdk.service'; + +@Component({ + tag: 'identifo-form-login-oidc', + styleUrl: '../../styles/identifo-form/main.scss', + assetsDirs: ['assets'], + shadow: false, +}) +export class IdentifoFormLoginOidc { + @State() state: StateLoginOidc; + @State() isVerify = false; + + subscription: Subscription; + + connectedCallback() { + this.subscription = CDKService.cdk.state.subscribe(state => (this.state = state as StateLoginOidc)); + const search = new URLSearchParams(window.location.search); + const state = search.get('state'); + const code = search.get('code'); + if (state && code) { + this.state.verify(state, code); + this.isVerify = true; + } + } + + disconnectedCallback() { + this.subscription.unsubscribe(); + } + + login = () => { + const url = this.state.oidcLink; + window.location.href = url.toString(); + }; + + render() { + return ( + + ); + } +} diff --git a/web_apps_src/web-element/src/components/identifo-form/identifo-form.tsx b/web_apps_src/web-element/src/components/identifo-form/identifo-form.tsx index 09fc578a..f23ceadb 100755 --- a/web_apps_src/web-element/src/components/identifo-form/identifo-form.tsx +++ b/web_apps_src/web-element/src/components/identifo-form/identifo-form.tsx @@ -43,6 +43,8 @@ export class IdentifoForm { switch (route) { case Routes.LOGIN: return ; + case Routes.LOGIN_OIDC: + return ; case Routes.LOGIN_PHONE: return ; case Routes.LOGIN_PHONE_VERIFY: