@stack-spot/auth-react 1.7.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.1.0](https://github.com/stack-spot/portal-auth-js/compare/auth-react-v2.0.0...auth-react@v2.1.0) (2024-08-27)
4
+
5
+
6
+ ### Features
7
+
8
+ * @stack-spot/auth-react ([22fd98c](https://github.com/stack-spot/portal-auth-js/commit/22fd98c2f251c491d158b5014dabed7d714683ad))
9
+ * default values for url parameters ([d394d03](https://github.com/stack-spot/portal-auth-js/commit/d394d03c780a193fa6e9a656f4b7bd0e9b8b731b))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * delete dist before building ([97be04f](https://github.com/stack-spot/portal-auth-js/commit/97be04fe136b15c86e250c57c1e31006694bfce2))
15
+ * handle transition between recover session with email and tenant ([b98c396](https://github.com/stack-spot/portal-auth-js/commit/b98c396e3fd7da21dfef30b36fa0aff0be09ef19))
16
+ * Update color bg on Login Page ([12c5d09](https://github.com/stack-spot/portal-auth-js/commit/12c5d0905af6c956f41acd5d81c9950f11038e1d))
17
+
18
+ ## [2.0.0] (2024-08-26)
19
+
20
+ * Support for login using tenant instead of email ([7f2585d](https://github.com/stack-spot/portal-auth-js/pull/42/commits/7f2585dd011a80e6bca1ac31d7736e3b6cc0dc5b))
21
+
3
22
  ## [1.7.0](https://github.com/stack-spot/portal-auth-js/compare/auth-react@v1.6.0...auth-react@v1.7.0) (2024-07-19)
4
23
 
5
24
 
package/out/index.d.ts CHANGED
@@ -71,6 +71,7 @@ declare class SessionManager {
71
71
  logout(): Promise<void>;
72
72
  startThirdPartyLogin(data: ThirdPartyLoginParams): Promise<void>;
73
73
  urlHasThirdPartyLoginData(): boolean;
74
+ startThirdPartyLoginUsingTenant(data: ThirdPartyLoginParams): Promise<void>;
74
75
  completeThirdPartyLogin(): Promise<void>;
75
76
  getEmailForLogin(): string | undefined;
76
77
  switchAccount(accountId: string): Promise<void>;
package/out/index.js CHANGED
@@ -217,7 +217,7 @@ const _SessionManager = class _SessionManager {
217
217
  if (isSharedSessionTypeBlocked)
218
218
  return false;
219
219
  else if (isDifferentSessionActive || !session) {
220
- await this.startThirdPartyLogin(sharedSessionCookie);
220
+ await this.startThirdPartyLoginUsingTenant(sharedSessionCookie);
221
221
  return false;
222
222
  }
223
223
  return true;
@@ -261,6 +261,23 @@ ${error}`);
261
261
  const url = new URL(location.toString());
262
262
  return url.searchParams.has("state") && !url.searchParams.has("error");
263
263
  }
264
+ async startThirdPartyLoginUsingTenant(data) {
265
+ const params = new URLSearchParams(location.search);
266
+ const cookie = sessionCookie.get();
267
+ if (!cookie || !cookie.tenant) {
268
+ await this.logout();
269
+ return;
270
+ }
271
+ const authUrl = await this.auth.getThirdPartyLoginFromTenant(
272
+ data,
273
+ cookie.tenant,
274
+ {
275
+ from: location.href,
276
+ finalRedirect: params.get("finalRedirect")
277
+ }
278
+ );
279
+ await redirect(authUrl);
280
+ }
264
281
  async completeThirdPartyLogin() {
265
282
  var _a, _b;
266
283
  const url = new URL(location.toString());
@@ -291,14 +308,14 @@ ${error}`);
291
308
  };
292
309
  }
293
310
  setSessionCookie(session) {
294
- const { email, account_type, sub } = session.getTokenData();
295
- if (!email || !sub)
311
+ const { email, account_type, sub, tenant } = session.getTokenData();
312
+ if (!email || !sub || !tenant)
296
313
  return;
297
314
  const isFreemium = account_type == "FREEMIUM";
298
315
  if (isFreemium) {
299
- sessionCookie.set({ type: "idp", provider: "external-idp:github", sub });
316
+ sessionCookie.set({ type: "idp", provider: "external-idp:github", sub, tenant });
300
317
  } else {
301
- sessionCookie.set({ email, type: "sso", sub });
318
+ sessionCookie.set({ email, type: "sso", sub, tenant });
302
319
  }
303
320
  }
304
321
  async sendLoginEventRd(email, name) {
package/out/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/Login.tsx","../src/utils/cookies.ts","../src/utils/redirect.ts","../src/SessionManager.ts","../src/Authenticated.tsx","../src/hooks.ts"],"sourcesContent":["/* eslint-disable max-len */\nimport { Button, IconBox, Input, Text } from '@citric/core'\nimport { Github } from '@citric/icons'\nimport { LoadingCircular } from '@citric/ui'\nimport { BannerWarning } from '@stack-spot/portal-components'\nimport { MiniLogo } from '@stack-spot/portal-components/svg'\nimport { theme } from '@stack-spot/portal-theme'\nimport { Dictionary, useTranslate } from '@stack-spot/portal-translate'\nimport { useState } from 'react'\nimport { styled } from 'styled-components'\n\nexport type LoginType = 'sso' | 'idp'\n\ninterface BaseData {\n type: LoginType,\n}\n\ninterface SSOData extends BaseData {\n type: 'sso',\n email: string,\n}\n\ninterface IDPData extends BaseData {\n type: 'idp',\n provider: 'external-idp:github',\n}\n\ntype LoginData = SSOData | IDPData\n\nexport type LoginProps = {\n initialValue?: string,\n onSubmit: (data: LoginData) => Promise<void>,\n welcomeText?: string,\n removeLoadingOnSuccess?: boolean,\n className?: string,\n style?: React.CSSProperties,\n banner?: React.ReactNode,\n loginTypes?: LoginType[]\n}\n\nconst LoginBox = styled.form`\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: 24px;\n\n header {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 24px;\n }\n\n .title {\n font-size: 1rem;\n }\n\n .separator {\n padding: 0 8px;\n background-color: ${theme.color.light['300']};\n color: ${theme.color.light['700']};\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n gap: 20px;\n margin: 0;\n\n &:before, &:after {\n content: '';\n height: 1px;\n flex: 1;\n background-color: ${theme.color.light['600']};\n }\n }\n\n .error {\n color: ${theme.color.danger['500']};\n line-height: 1.5rem;\n }\n`\n\nexport const Login = ({ onSubmit, initialValue = '', welcomeText, removeLoadingOnSuccess, className, style, banner, loginTypes = ['idp', 'sso'] }: LoginProps) => {\n const t = useTranslate(dictionary)\n const searchParams = new URLSearchParams(location.search)\n const [error, setError] = useState(searchParams.get('error_description') || searchParams.get('error') || '')\n const [loading, setLoading] = useState(false)\n const [email, setEmail] = useState(initialValue)\n const disabled = !email.match(/\\w+@\\w+/)\n const idpLoginEnabled = loginTypes.includes('idp')\n const ssoLoginEnabled = loginTypes.includes('sso')\n\n async function login(type: LoginType) {\n setError('')\n setLoading(true)\n try {\n const data: LoginData = type === 'sso' ? { type: 'sso', email } : { type: 'idp', provider: 'external-idp:github' }\n await onSubmit(data)\n if (removeLoadingOnSuccess) setLoading(false)\n } catch (error: any) {\n setLoading(false)\n setError(error.message || error.toString())\n }\n }\n\n function submitForm(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault()\n if (disabled) return\n login('sso')\n }\n\n return (\n <>\n <LoginBox onSubmit={submitForm} className={className} style={style}>\n <header>\n <MiniLogo />\n <Text className=\"title\">{welcomeText || t.welcome}</Text>\n </header>\n {ssoLoginEnabled && <>\n <Input name=\"email\" value={email} onChange={e => setEmail(e.target.value)} placeholder={t.placeholder} />\n <Button colorScheme=\"primary\" disabled={disabled || loading}>\n {loading ? <LoadingCircular /> : <Text>{t.continue}</Text>}\n </Button>\n </>}\n {ssoLoginEnabled && idpLoginEnabled && <p className=\"separator\">{t.or}</p>}\n {idpLoginEnabled &&\n <Button colorScheme=\"light\" type=\"button\" onClick={() => login('idp')} disabled={loading}>\n {loading ? <LoadingCircular /> : (\n <>\n <IconBox>\n <Github />\n </IconBox>\n <Text>{t.loginWithGithub}</Text>\n </>\n )}\n </Button>}\n {error && <Text className=\"error\">{t.error}: {error}</Text>}\n </LoginBox>\n {banner ? <BannerWarning>\n {banner}\n </BannerWarning> : null}\n </>\n )\n}\n\nconst dictionary = {\n en: {\n welcome: 'Welcome to StackSpot',\n placeholder: 'your@email.com',\n continue: 'Continue',\n or: 'or',\n loginWithGithub: 'Login with Github',\n error: 'Error while attempting to login',\n },\n pt: {\n welcome: 'Bem vindo à StackSpot',\n placeholder: 'nome@email.com',\n continue: 'Continuar',\n or: 'ou',\n loginWithGithub: 'Logar com o GitHub',\n error: 'Erro ao fazer login',\n },\n} satisfies Dictionary\n","import { ThirdPartyLoginParams } from '@stack-spot/auth'\nimport { getCookie, getCookieDomain, removeCookie, setCookie } from '@stack-spot/portal-components'\n\nconst sessionKey = `stk-session${getCookieDomain()}`\n\ntype SessionCookie = ThirdPartyLoginParams & { sub: string }\n\nexport const sessionCookie = Object.freeze({\n set: (data: SessionCookie) => setCookie(sessionKey, JSON.stringify(data)),\n get: (): SessionCookie | undefined => {\n try {\n const cookie = getCookie(sessionKey)\n return cookie ? JSON.parse(cookie) : undefined\n } catch (error) {\n console.error(error)\n }\n },\n delete: () => removeCookie(sessionKey)\n})\n","export const redirect = async (url: string) => {\n window.location.href = url\n /**\n * This is intentional. The promise bellow will never be fulfilled.\n * Once the set href is not instantaneous, this will guarantee no further code is executed until the user is really redirected.\n * Particularly useful to prevent flickering page renders on scenarios with redirects.\n */\n await new Promise(() => '')\n}","import { AuthConfig, AuthManager, Session, ThirdPartyAuthType, ThirdPartyLoginParams } from '@stack-spot/auth'\nimport { sessionCookie } from './utils/cookies'\nimport { redirect } from './utils/redirect'\n\nconst sessionKey = 'session'\n\ninterface SessionManagerConfig extends Pick<AuthConfig, 'accountUrl' | 'authUrl' | 'clientId' | 'defaultTenant'> {\n /**\n * The URL to redirect to when the user logs out.\n * @default location.origin\n */\n loginUrl?: string,\n /**\n * The URL to redirect to when the login completes in the authentication app. If not provided, will be the same as `loginUrl`.\n * @default loginUrl\n */\n redirectUrl?: string,\n /**\n * Forbidden authentication types to this Session Manager.\n */\n blockedAuthTypes?: ThirdPartyAuthType[]\n /**\n * A URL to send login events to (observability).\n */\n rdUrl?: string,\n}\n\ntype AuthExtraData = { from?: string | null, finalRedirect?: string | null }\n\ntype ChangeListener = (session: Session | undefined) => void\n\n/**\n * Controls the current session in a browser.\n * \n * This should not be used under a Node.JS environment.\n * \n * This is a singleton. To create the first instance or recover the current one, use `SessionManager.create`.\n */\nexport class SessionManager {\n private current: Session | undefined\n private readonly auth: AuthManager<AuthExtraData>\n private config: SessionManagerConfig\n private changeListeners: ChangeListener[] = []\n static instance: SessionManager | undefined\n\n private constructor(config: SessionManagerConfig) {\n config.loginUrl ||= location.origin\n const redirectUrl = (config.redirectUrl || config.loginUrl).replace(/([^/])$/, '$1/') // the trailing \"/\" is required by Stackspot IAM.\n this.config = config\n this.auth = new AuthManager<AuthExtraData>({\n ...config,\n redirectUrl,\n storage: localStorage,\n sessionPersistence: {\n load: () => localStorage.getItem(sessionKey),\n save: (session) => localStorage.setItem(sessionKey, session),\n },\n })\n SessionManager.instance = this\n\n // Keep session in sync with other app's session\n addEventListener('focus', () => this.validateSharedSession())\n }\n\n static create(config: SessionManagerConfig) {\n return SessionManager.instance ?? new SessionManager(config)\n }\n\n private setSession(session: Session | undefined) {\n this.current = session\n this.changeListeners.forEach(l => l(session))\n if (session) this.setSessionCookie(session)\n }\n\n async restoreSession() {\n const session = await this.auth.restoreSession()\n const sessionValid = await this.validateSharedSession(session)\n this.setSession(sessionValid ? session : undefined)\n }\n\n async validateSharedSession(session: Session | undefined = this.current): Promise<boolean> {\n\n // skipping because authentication is in progress\n if (this.urlHasThirdPartyLoginData()) return false\n\n const sharedSessionCookie = sessionCookie.get()\n\n // It has been logged out on another portal, so logout on this one too\n if (!sharedSessionCookie) {\n session && await this.logout()\n return false\n }\n\n const isDifferentSessionActive = sharedSessionCookie.sub != session?.getTokenData().sub\n const isSharedSessionTypeBlocked = this.config.blockedAuthTypes?.includes(sharedSessionCookie.type)\n if (isSharedSessionTypeBlocked) return false\n else if (isDifferentSessionActive || !session) {\n await this.startThirdPartyLogin(sharedSessionCookie)\n return false\n }\n return true\n }\n\n hasSession() {\n return !!this.current && !this.current.isExpired()\n }\n\n getSession() {\n if (!this.hasSession()) {\n this.endSession()\n throw new Error('Session is not available, redirecting to login.')\n }\n return this.current!\n }\n\n async endSession(redirectToLogin = true) {\n this.current = undefined\n localStorage.removeItem(sessionKey)\n sessionCookie.delete()\n if (redirectToLogin && this.config.loginUrl) await redirect(this.config.loginUrl)\n }\n\n async logout() {\n try {\n await this.current?.logout()\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(`Could not logout from IDM.\\n${error}`)\n }\n await this.endSession()\n }\n\n async startThirdPartyLogin(data: ThirdPartyLoginParams) {\n const params = new URLSearchParams(location.search)\n const authUrl = await this.auth.startThirdPartyLogin(data, {\n from: location.href,\n finalRedirect: params.get('finalRedirect'),\n })\n await redirect(authUrl)\n }\n\n urlHasThirdPartyLoginData() {\n const url = new URL(location.toString())\n return url.searchParams.has('state') && !url.searchParams.has('error')\n }\n\n async completeThirdPartyLogin() {\n const url = new URL(location.toString())\n if (url.searchParams.has('error')) {\n throw new Error(`Error while signing in: ${url.searchParams.get('error_description')}`)\n }\n const { session, data: { from, finalRedirect } } = await this.auth.completeThirdPartyLogin(location.search)\n this.setSession(session)\n history.replaceState(null, '', from || location.toString().replace(/\\?.*$/, ''))\n this.sendLoginEventRd(this.current?.getTokenData().email, this.current?.getTokenData().name)\n if (finalRedirect) await redirect(finalRedirect)\n }\n\n getEmailForLogin() {\n const session = sessionCookie.get()\n return session?.type == 'sso' ? session.email : undefined\n }\n\n async switchAccount(accountId: string) {\n this.current && await this.auth.switchAccount(accountId, this.current)\n this.setSession(this.current)\n }\n\n onChange(listener: ChangeListener) {\n this.changeListeners.push(listener)\n return () => {\n const index = this.changeListeners.indexOf(listener)\n if (index != -1) this.changeListeners.splice(index, 1)\n }\n }\n\n private setSessionCookie(session: Session) {\n const { email, account_type, sub } = session.getTokenData()\n if (!email || !sub) return\n const isFreemium = account_type == 'FREEMIUM'\n if (isFreemium) {\n sessionCookie.set({ type: 'idp', provider: 'external-idp:github', sub })\n } else {\n sessionCookie.set({ email, type: 'sso', sub })\n }\n }\n\n private async sendLoginEventRd(email?: string, name?: string) {\n if (!this.config.rdUrl) return\n if (!email && !name) {\n // eslint-disable-next-line no-console\n console.error('Unable to trigger login hook. No sessionEmail or name identified.')\n return\n }\n\n const rdObject = {\n event_type: 'CONVERSION',\n event_family: 'CDP',\n payload: {\n email,\n name,\n conversion_identifier: 'login-v1',\n },\n }\n\n const response = await fetch(this.config.rdUrl, {\n method: 'POST',\n body: JSON.stringify(rdObject),\n headers: {\n 'content-type': 'application/json',\n },\n })\n const data = await response.json()\n\n if (!response.ok) {\n // eslint-disable-next-line no-console\n console.error('Error while sending event to RD Station', data)\n }\n }\n}\n","/* eslint-disable max-len */\nimport { Flex } from '@citric/core'\nimport { useEffectOnce } from '@stack-spot/portal-components'\nimport { CSSToCitricAdapter } from '@stack-spot/portal-theme'\nimport '@stack-spot/portal-theme/dist/theme.css'\nimport { useLanguage } from '@stack-spot/portal-translate'\nimport { useState } from 'react'\nimport { Login, LoginProps } from './Login'\nimport { SessionManager } from './SessionManager'\n\ntype AuthStatus = 'unknown' | 'authenticated' | 'unauthenticated'\n\ninterface Props {\n children: React.ReactElement,\n onLogin?: () => void,\n onSession?: () => void,\n onChangeStatus?: (status: AuthStatus) => void,\n customLoginProps?: Omit<LoginProps, 'onSubmit' | 'initialValue'>,\n sessionManager?: SessionManager,\n}\n\nexport const Authenticated = ({ children, onLogin, onSession, customLoginProps, sessionManager, onChangeStatus }: Props) => {\n const [authStatus, setAuthStatus] = useState<AuthStatus>('unknown')\n const language = useLanguage()\n sessionManager ??= SessionManager.instance\n if (!sessionManager) throw new Error('Please, provide a sessionManager')\n\n useEffectOnce(() => {\n async function checkAuth() {\n if (!sessionManager) throw new Error('Please, provide a sessionManager')\n await sessionManager.restoreSession()\n if (sessionManager.urlHasThirdPartyLoginData()) {\n await sessionManager.completeThirdPartyLogin()\n onLogin?.()\n }\n if (sessionManager.hasSession()) {\n setAuthStatus('authenticated')\n onSession?.()\n onChangeStatus?.('authenticated')\n } else {\n setAuthStatus('unauthenticated')\n onChangeStatus?.('unauthenticated')\n }\n }\n\n checkAuth()\n })\n\n if (authStatus === 'unknown') return null\n if (authStatus === 'authenticated') return children\n\n return (\n <CSSToCitricAdapter>\n <Flex justifyContent=\"center\" alignItems=\"center\" flex={1} style={{ height: '100%' }}>\n <Login\n style={{ width: '360px' }}\n onSubmit={data => sessionManager.startThirdPartyLogin({ ...data, locale: language })}\n initialValue={sessionManager.getEmailForLogin()}\n {...(customLoginProps || {})}\n />\n </Flex>\n </CSSToCitricAdapter>\n )\n}\n","import { Session } from '@stack-spot/auth'\nimport { useEffect, useState } from 'react'\nimport { SessionManager } from './SessionManager'\n\nexport function useSession() {\n const manager = SessionManager.instance\n const [session, setSession] = useState<Session | undefined>(manager?.hasSession() ? manager.getSession() : undefined)\n useEffect(() => {\n return manager?.onChange(setSession)\n }, [])\n return session\n}\n"],"names":["styled","theme","useTranslate","useState","error","jsxs","Fragment","jsx","MiniLogo","Text","Input","Button","LoadingCircular","IconBox","Github","BannerWarning","sessionKey","getCookieDomain","setCookie","getCookie","removeCookie","AuthManager","__spreadProps","__spreadValues","useLanguage","useEffectOnce","CSSToCitricAdapter","Flex","useEffect"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/Login.tsx","../src/utils/cookies.ts","../src/utils/redirect.ts","../src/SessionManager.ts","../src/Authenticated.tsx","../src/hooks.ts"],"sourcesContent":["/* eslint-disable max-len */\nimport { Button, IconBox, Input, Text } from '@citric/core'\nimport { Github } from '@citric/icons'\nimport { LoadingCircular } from '@citric/ui'\nimport { BannerWarning } from '@stack-spot/portal-components'\nimport { MiniLogo } from '@stack-spot/portal-components/svg'\nimport { theme } from '@stack-spot/portal-theme'\nimport { Dictionary, useTranslate } from '@stack-spot/portal-translate'\nimport { useState } from 'react'\nimport { styled } from 'styled-components'\n\nexport type LoginType = 'sso' | 'idp'\n\ninterface BaseData {\n type: LoginType,\n}\n\ninterface SSOData extends BaseData {\n type: 'sso',\n email: string,\n}\n\ninterface IDPData extends BaseData {\n type: 'idp',\n provider: 'external-idp:github',\n}\n\ntype LoginData = SSOData | IDPData\n\nexport type LoginProps = {\n initialValue?: string,\n onSubmit: (data: LoginData) => Promise<void>,\n welcomeText?: string,\n removeLoadingOnSuccess?: boolean,\n className?: string,\n style?: React.CSSProperties,\n banner?: React.ReactNode,\n loginTypes?: LoginType[]\n}\n\nconst LoginBox = styled.form`\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: 24px;\n\n header {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 24px;\n }\n\n .title {\n font-size: 1rem;\n }\n\n .separator {\n padding: 0 8px;\n background-color: ${theme.color.light['300']};\n color: ${theme.color.light['700']};\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n gap: 20px;\n margin: 0;\n\n &:before, &:after {\n content: '';\n height: 1px;\n flex: 1;\n background-color: ${theme.color.light['600']};\n }\n }\n\n .error {\n color: ${theme.color.danger['500']};\n line-height: 1.5rem;\n }\n`\n\nexport const Login = ({ onSubmit, initialValue = '', welcomeText, removeLoadingOnSuccess, className, style, banner, loginTypes = ['idp', 'sso'] }: LoginProps) => {\n const t = useTranslate(dictionary)\n const searchParams = new URLSearchParams(location.search)\n const [error, setError] = useState(searchParams.get('error_description') || searchParams.get('error') || '')\n const [loading, setLoading] = useState(false)\n const [email, setEmail] = useState(initialValue)\n const disabled = !email.match(/\\w+@\\w+/)\n const idpLoginEnabled = loginTypes.includes('idp')\n const ssoLoginEnabled = loginTypes.includes('sso')\n\n async function login(type: LoginType) {\n setError('')\n setLoading(true)\n try {\n const data: LoginData = type === 'sso' ? { type: 'sso', email } : { type: 'idp', provider: 'external-idp:github' }\n await onSubmit(data)\n if (removeLoadingOnSuccess) setLoading(false)\n } catch (error: any) {\n setLoading(false)\n setError(error.message || error.toString())\n }\n }\n\n function submitForm(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault()\n if (disabled) return\n login('sso')\n }\n\n return (\n <>\n <LoginBox onSubmit={submitForm} className={className} style={style}>\n <header>\n <MiniLogo />\n <Text className=\"title\">{welcomeText || t.welcome}</Text>\n </header>\n {ssoLoginEnabled && <>\n <Input name=\"email\" value={email} onChange={e => setEmail(e.target.value)} placeholder={t.placeholder} />\n <Button colorScheme=\"primary\" disabled={disabled || loading}>\n {loading ? <LoadingCircular /> : <Text>{t.continue}</Text>}\n </Button>\n </>}\n {ssoLoginEnabled && idpLoginEnabled && <p className=\"separator\">{t.or}</p>}\n {idpLoginEnabled &&\n <Button colorScheme=\"light\" type=\"button\" onClick={() => login('idp')} disabled={loading}>\n {loading ? <LoadingCircular /> : (\n <>\n <IconBox>\n <Github />\n </IconBox>\n <Text>{t.loginWithGithub}</Text>\n </>\n )}\n </Button>}\n {error && <Text className=\"error\">{t.error}: {error}</Text>}\n </LoginBox>\n {banner ? <BannerWarning>\n {banner}\n </BannerWarning> : null}\n </>\n )\n}\n\nconst dictionary = {\n en: {\n welcome: 'Welcome to StackSpot',\n placeholder: 'your@email.com',\n continue: 'Continue',\n or: 'or',\n loginWithGithub: 'Login with Github',\n error: 'Error while attempting to login',\n },\n pt: {\n welcome: 'Bem vindo à StackSpot',\n placeholder: 'nome@email.com',\n continue: 'Continuar',\n or: 'ou',\n loginWithGithub: 'Logar com o GitHub',\n error: 'Erro ao fazer login',\n },\n} satisfies Dictionary\n","import { ThirdPartyLoginParams } from '@stack-spot/auth'\nimport { getCookie, getCookieDomain, removeCookie, setCookie } from '@stack-spot/portal-components'\n\nconst sessionKey = `stk-session${getCookieDomain()}`\n\ntype SessionCookie = ThirdPartyLoginParams & { sub: string, tenant: string }\n\nexport const sessionCookie = Object.freeze({\n set: (data: SessionCookie) => setCookie(sessionKey, JSON.stringify(data)),\n get: (): SessionCookie | undefined => {\n try {\n const cookie = getCookie(sessionKey)\n return cookie ? JSON.parse(cookie) : undefined\n } catch (error) {\n console.error(error)\n }\n },\n delete: () => removeCookie(sessionKey)\n})\n","export const redirect = async (url: string) => {\n window.location.href = url\n /**\n * This is intentional. The promise bellow will never be fulfilled.\n * Once the set href is not instantaneous, this will guarantee no further code is executed until the user is really redirected.\n * Particularly useful to prevent flickering page renders on scenarios with redirects.\n */\n await new Promise(() => '')\n}","import { AuthConfig, AuthManager, Session, ThirdPartyAuthType, ThirdPartyLoginParams } from '@stack-spot/auth'\nimport { sessionCookie } from './utils/cookies'\nimport { redirect } from './utils/redirect'\n\nconst sessionKey = 'session'\n\ninterface SessionManagerConfig extends Pick<AuthConfig, 'accountUrl' | 'authUrl' | 'clientId' | 'defaultTenant'> {\n /**\n * The URL to redirect to when the user logs out.\n * @default location.origin\n */\n loginUrl?: string,\n /**\n * The URL to redirect to when the login completes in the authentication app. If not provided, will be the same as `loginUrl`.\n * @default loginUrl\n */\n redirectUrl?: string,\n /**\n * Forbidden authentication types to this Session Manager.\n */\n blockedAuthTypes?: ThirdPartyAuthType[]\n /**\n * A URL to send login events to (observability).\n */\n rdUrl?: string,\n}\n\ntype AuthExtraData = { from?: string | null, finalRedirect?: string | null }\n\ntype ChangeListener = (session: Session | undefined) => void\n\n/**\n * Controls the current session in a browser.\n * \n * This should not be used under a Node.JS environment.\n * \n * This is a singleton. To create the first instance or recover the current one, use `SessionManager.create`.\n */\nexport class SessionManager {\n private current: Session | undefined\n private readonly auth: AuthManager<AuthExtraData>\n private config: SessionManagerConfig\n private changeListeners: ChangeListener[] = []\n static instance: SessionManager | undefined\n\n private constructor(config: SessionManagerConfig) {\n config.loginUrl ||= location.origin\n const redirectUrl = (config.redirectUrl || config.loginUrl).replace(/([^/])$/, '$1/') // the trailing \"/\" is required by Stackspot IAM.\n this.config = config\n this.auth = new AuthManager<AuthExtraData>({\n ...config,\n redirectUrl,\n storage: localStorage,\n sessionPersistence: {\n load: () => localStorage.getItem(sessionKey),\n save: (session) => localStorage.setItem(sessionKey, session),\n },\n })\n SessionManager.instance = this\n\n // Keep session in sync with other app's session\n addEventListener('focus', () => this.validateSharedSession())\n }\n\n static create(config: SessionManagerConfig) {\n return SessionManager.instance ?? new SessionManager(config)\n }\n\n private setSession(session: Session | undefined) {\n this.current = session\n this.changeListeners.forEach(l => l(session))\n if (session) this.setSessionCookie(session)\n }\n\n async restoreSession() {\n const session = await this.auth.restoreSession()\n const sessionValid = await this.validateSharedSession(session)\n this.setSession(sessionValid ? session : undefined)\n }\n\n async validateSharedSession(session: Session | undefined = this.current): Promise<boolean> {\n\n // skipping because authentication is in progress\n if (this.urlHasThirdPartyLoginData()) return false\n\n const sharedSessionCookie = sessionCookie.get()\n\n // It has been logged out on another portal, so logout on this one too\n if (!sharedSessionCookie) {\n session && await this.logout()\n return false\n }\n\n const isDifferentSessionActive = sharedSessionCookie.sub != session?.getTokenData().sub\n const isSharedSessionTypeBlocked = this.config.blockedAuthTypes?.includes(sharedSessionCookie.type)\n if (isSharedSessionTypeBlocked) return false\n else if (isDifferentSessionActive || !session) {\n await this.startThirdPartyLoginUsingTenant(sharedSessionCookie)\n return false\n }\n return true\n }\n\n hasSession() {\n return !!this.current && !this.current.isExpired()\n }\n\n getSession() {\n if (!this.hasSession()) {\n this.endSession()\n throw new Error('Session is not available, redirecting to login.')\n }\n return this.current!\n }\n\n async endSession(redirectToLogin = true) {\n this.current = undefined\n localStorage.removeItem(sessionKey)\n sessionCookie.delete()\n if (redirectToLogin && this.config.loginUrl) await redirect(this.config.loginUrl)\n }\n\n async logout() {\n try {\n await this.current?.logout()\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(`Could not logout from IDM.\\n${error}`)\n }\n await this.endSession()\n }\n\n async startThirdPartyLogin(data: ThirdPartyLoginParams) {\n const params = new URLSearchParams(location.search)\n const authUrl = await this.auth.startThirdPartyLogin(data, {\n from: location.href,\n finalRedirect: params.get('finalRedirect'),\n })\n await redirect(authUrl)\n }\n\n urlHasThirdPartyLoginData() {\n const url = new URL(location.toString())\n return url.searchParams.has('state') && !url.searchParams.has('error')\n }\n\n async startThirdPartyLoginUsingTenant(data: ThirdPartyLoginParams) {\n const params = new URLSearchParams(location.search)\n const cookie = sessionCookie.get()\n if (!cookie || !cookie.tenant) {\n //If no tenant is available we should log out the user\n await this.logout()\n return\n }\n const authUrl = await this.auth.getThirdPartyLoginFromTenant(data, cookie.tenant, {\n from: location.href,\n finalRedirect: params.get('finalRedirect'),\n }\n )\n await redirect(authUrl)\n }\n\n async completeThirdPartyLogin() {\n const url = new URL(location.toString())\n if (url.searchParams.has('error')) {\n throw new Error(`Error while signing in: ${url.searchParams.get('error_description')}`)\n }\n const { session, data: { from, finalRedirect } } = await this.auth.completeThirdPartyLogin(location.search)\n this.setSession(session)\n history.replaceState(null, '', from || location.toString().replace(/\\?.*$/, ''))\n this.sendLoginEventRd(this.current?.getTokenData().email, this.current?.getTokenData().name)\n if (finalRedirect) await redirect(finalRedirect)\n }\n\n getEmailForLogin() {\n const session = sessionCookie.get()\n return session?.type == 'sso' ? session.email : undefined\n }\n\n async switchAccount(accountId: string) {\n this.current && await this.auth.switchAccount(accountId, this.current)\n this.setSession(this.current)\n }\n\n onChange(listener: ChangeListener) {\n this.changeListeners.push(listener)\n return () => {\n const index = this.changeListeners.indexOf(listener)\n if (index != -1) this.changeListeners.splice(index, 1)\n }\n }\n\n private setSessionCookie(session: Session) {\n const { email, account_type, sub, tenant } = session.getTokenData()\n if (!email || !sub || !tenant) return\n const isFreemium = account_type == 'FREEMIUM'\n if (isFreemium) {\n sessionCookie.set({ type: 'idp', provider: 'external-idp:github', sub, tenant })\n } else {\n sessionCookie.set({ email, type: 'sso', sub, tenant })\n }\n }\n\n private async sendLoginEventRd(email?: string, name?: string) {\n if (!this.config.rdUrl) return\n if (!email && !name) {\n // eslint-disable-next-line no-console\n console.error('Unable to trigger login hook. No sessionEmail or name identified.')\n return\n }\n\n const rdObject = {\n event_type: 'CONVERSION',\n event_family: 'CDP',\n payload: {\n email,\n name,\n conversion_identifier: 'login-v1',\n },\n }\n\n const response = await fetch(this.config.rdUrl, {\n method: 'POST',\n body: JSON.stringify(rdObject),\n headers: {\n 'content-type': 'application/json',\n },\n })\n const data = await response.json()\n\n if (!response.ok) {\n // eslint-disable-next-line no-console\n console.error('Error while sending event to RD Station', data)\n }\n }\n}\n","/* eslint-disable max-len */\nimport { Flex } from '@citric/core'\nimport { useEffectOnce } from '@stack-spot/portal-components'\nimport { CSSToCitricAdapter } from '@stack-spot/portal-theme'\nimport '@stack-spot/portal-theme/dist/theme.css'\nimport { useLanguage } from '@stack-spot/portal-translate'\nimport { useState } from 'react'\nimport { Login, LoginProps } from './Login'\nimport { SessionManager } from './SessionManager'\n\ntype AuthStatus = 'unknown' | 'authenticated' | 'unauthenticated'\n\ninterface Props {\n children: React.ReactElement,\n onLogin?: () => void,\n onSession?: () => void,\n onChangeStatus?: (status: AuthStatus) => void,\n customLoginProps?: Omit<LoginProps, 'onSubmit' | 'initialValue'>,\n sessionManager?: SessionManager,\n}\n\nexport const Authenticated = ({ children, onLogin, onSession, customLoginProps, sessionManager, onChangeStatus }: Props) => {\n const [authStatus, setAuthStatus] = useState<AuthStatus>('unknown')\n const language = useLanguage()\n sessionManager ??= SessionManager.instance\n if (!sessionManager) throw new Error('Please, provide a sessionManager')\n\n useEffectOnce(() => {\n async function checkAuth() {\n if (!sessionManager) throw new Error('Please, provide a sessionManager')\n await sessionManager.restoreSession()\n if (sessionManager.urlHasThirdPartyLoginData()) {\n await sessionManager.completeThirdPartyLogin()\n onLogin?.()\n }\n if (sessionManager.hasSession()) {\n setAuthStatus('authenticated')\n onSession?.()\n onChangeStatus?.('authenticated')\n } else {\n setAuthStatus('unauthenticated')\n onChangeStatus?.('unauthenticated')\n }\n }\n\n checkAuth()\n })\n\n if (authStatus === 'unknown') return null\n if (authStatus === 'authenticated') return children\n\n return (\n <CSSToCitricAdapter>\n <Flex justifyContent=\"center\" alignItems=\"center\" flex={1} style={{ height: '100%' }}>\n <Login\n style={{ width: '360px' }}\n onSubmit={data => sessionManager.startThirdPartyLogin({ ...data, locale: language })}\n initialValue={sessionManager.getEmailForLogin()}\n {...(customLoginProps || {})}\n />\n </Flex>\n </CSSToCitricAdapter>\n )\n}\n","import { Session } from '@stack-spot/auth'\nimport { useEffect, useState } from 'react'\nimport { SessionManager } from './SessionManager'\n\nexport function useSession() {\n const manager = SessionManager.instance\n const [session, setSession] = useState<Session | undefined>(manager?.hasSession() ? manager.getSession() : undefined)\n useEffect(() => {\n return manager?.onChange(setSession)\n }, [])\n return session\n}\n"],"names":["styled","theme","useTranslate","useState","error","jsxs","Fragment","jsx","MiniLogo","Text","Input","Button","LoadingCircular","IconBox","Github","BannerWarning","sessionKey","getCookieDomain","setCookie","getCookie","removeCookie","AuthManager","__spreadProps","__spreadValues","useLanguage","useEffectOnce","CSSToCitricAdapter","Flex","useEffect"],"mappings":"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"}
package/out/index.mjs CHANGED
@@ -215,7 +215,7 @@ const _SessionManager = class _SessionManager {
215
215
  if (isSharedSessionTypeBlocked)
216
216
  return false;
217
217
  else if (isDifferentSessionActive || !session) {
218
- await this.startThirdPartyLogin(sharedSessionCookie);
218
+ await this.startThirdPartyLoginUsingTenant(sharedSessionCookie);
219
219
  return false;
220
220
  }
221
221
  return true;
@@ -259,6 +259,23 @@ ${error}`);
259
259
  const url = new URL(location.toString());
260
260
  return url.searchParams.has("state") && !url.searchParams.has("error");
261
261
  }
262
+ async startThirdPartyLoginUsingTenant(data) {
263
+ const params = new URLSearchParams(location.search);
264
+ const cookie = sessionCookie.get();
265
+ if (!cookie || !cookie.tenant) {
266
+ await this.logout();
267
+ return;
268
+ }
269
+ const authUrl = await this.auth.getThirdPartyLoginFromTenant(
270
+ data,
271
+ cookie.tenant,
272
+ {
273
+ from: location.href,
274
+ finalRedirect: params.get("finalRedirect")
275
+ }
276
+ );
277
+ await redirect(authUrl);
278
+ }
262
279
  async completeThirdPartyLogin() {
263
280
  var _a, _b;
264
281
  const url = new URL(location.toString());
@@ -289,14 +306,14 @@ ${error}`);
289
306
  };
290
307
  }
291
308
  setSessionCookie(session) {
292
- const { email, account_type, sub } = session.getTokenData();
293
- if (!email || !sub)
309
+ const { email, account_type, sub, tenant } = session.getTokenData();
310
+ if (!email || !sub || !tenant)
294
311
  return;
295
312
  const isFreemium = account_type == "FREEMIUM";
296
313
  if (isFreemium) {
297
- sessionCookie.set({ type: "idp", provider: "external-idp:github", sub });
314
+ sessionCookie.set({ type: "idp", provider: "external-idp:github", sub, tenant });
298
315
  } else {
299
- sessionCookie.set({ email, type: "sso", sub });
316
+ sessionCookie.set({ email, type: "sso", sub, tenant });
300
317
  }
301
318
  }
302
319
  async sendLoginEventRd(email, name) {
package/out/index.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/Login.tsx","../src/utils/cookies.ts","../src/utils/redirect.ts","../src/SessionManager.ts","../src/Authenticated.tsx","../src/hooks.ts"],"sourcesContent":["/* eslint-disable max-len */\nimport { Button, IconBox, Input, Text } from '@citric/core'\nimport { Github } from '@citric/icons'\nimport { LoadingCircular } from '@citric/ui'\nimport { BannerWarning } from '@stack-spot/portal-components'\nimport { MiniLogo } from '@stack-spot/portal-components/svg'\nimport { theme } from '@stack-spot/portal-theme'\nimport { Dictionary, useTranslate } from '@stack-spot/portal-translate'\nimport { useState } from 'react'\nimport { styled } from 'styled-components'\n\nexport type LoginType = 'sso' | 'idp'\n\ninterface BaseData {\n type: LoginType,\n}\n\ninterface SSOData extends BaseData {\n type: 'sso',\n email: string,\n}\n\ninterface IDPData extends BaseData {\n type: 'idp',\n provider: 'external-idp:github',\n}\n\ntype LoginData = SSOData | IDPData\n\nexport type LoginProps = {\n initialValue?: string,\n onSubmit: (data: LoginData) => Promise<void>,\n welcomeText?: string,\n removeLoadingOnSuccess?: boolean,\n className?: string,\n style?: React.CSSProperties,\n banner?: React.ReactNode,\n loginTypes?: LoginType[]\n}\n\nconst LoginBox = styled.form`\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: 24px;\n\n header {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 24px;\n }\n\n .title {\n font-size: 1rem;\n }\n\n .separator {\n padding: 0 8px;\n background-color: ${theme.color.light['300']};\n color: ${theme.color.light['700']};\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n gap: 20px;\n margin: 0;\n\n &:before, &:after {\n content: '';\n height: 1px;\n flex: 1;\n background-color: ${theme.color.light['600']};\n }\n }\n\n .error {\n color: ${theme.color.danger['500']};\n line-height: 1.5rem;\n }\n`\n\nexport const Login = ({ onSubmit, initialValue = '', welcomeText, removeLoadingOnSuccess, className, style, banner, loginTypes = ['idp', 'sso'] }: LoginProps) => {\n const t = useTranslate(dictionary)\n const searchParams = new URLSearchParams(location.search)\n const [error, setError] = useState(searchParams.get('error_description') || searchParams.get('error') || '')\n const [loading, setLoading] = useState(false)\n const [email, setEmail] = useState(initialValue)\n const disabled = !email.match(/\\w+@\\w+/)\n const idpLoginEnabled = loginTypes.includes('idp')\n const ssoLoginEnabled = loginTypes.includes('sso')\n\n async function login(type: LoginType) {\n setError('')\n setLoading(true)\n try {\n const data: LoginData = type === 'sso' ? { type: 'sso', email } : { type: 'idp', provider: 'external-idp:github' }\n await onSubmit(data)\n if (removeLoadingOnSuccess) setLoading(false)\n } catch (error: any) {\n setLoading(false)\n setError(error.message || error.toString())\n }\n }\n\n function submitForm(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault()\n if (disabled) return\n login('sso')\n }\n\n return (\n <>\n <LoginBox onSubmit={submitForm} className={className} style={style}>\n <header>\n <MiniLogo />\n <Text className=\"title\">{welcomeText || t.welcome}</Text>\n </header>\n {ssoLoginEnabled && <>\n <Input name=\"email\" value={email} onChange={e => setEmail(e.target.value)} placeholder={t.placeholder} />\n <Button colorScheme=\"primary\" disabled={disabled || loading}>\n {loading ? <LoadingCircular /> : <Text>{t.continue}</Text>}\n </Button>\n </>}\n {ssoLoginEnabled && idpLoginEnabled && <p className=\"separator\">{t.or}</p>}\n {idpLoginEnabled &&\n <Button colorScheme=\"light\" type=\"button\" onClick={() => login('idp')} disabled={loading}>\n {loading ? <LoadingCircular /> : (\n <>\n <IconBox>\n <Github />\n </IconBox>\n <Text>{t.loginWithGithub}</Text>\n </>\n )}\n </Button>}\n {error && <Text className=\"error\">{t.error}: {error}</Text>}\n </LoginBox>\n {banner ? <BannerWarning>\n {banner}\n </BannerWarning> : null}\n </>\n )\n}\n\nconst dictionary = {\n en: {\n welcome: 'Welcome to StackSpot',\n placeholder: 'your@email.com',\n continue: 'Continue',\n or: 'or',\n loginWithGithub: 'Login with Github',\n error: 'Error while attempting to login',\n },\n pt: {\n welcome: 'Bem vindo à StackSpot',\n placeholder: 'nome@email.com',\n continue: 'Continuar',\n or: 'ou',\n loginWithGithub: 'Logar com o GitHub',\n error: 'Erro ao fazer login',\n },\n} satisfies Dictionary\n","import { ThirdPartyLoginParams } from '@stack-spot/auth'\nimport { getCookie, getCookieDomain, removeCookie, setCookie } from '@stack-spot/portal-components'\n\nconst sessionKey = `stk-session${getCookieDomain()}`\n\ntype SessionCookie = ThirdPartyLoginParams & { sub: string }\n\nexport const sessionCookie = Object.freeze({\n set: (data: SessionCookie) => setCookie(sessionKey, JSON.stringify(data)),\n get: (): SessionCookie | undefined => {\n try {\n const cookie = getCookie(sessionKey)\n return cookie ? JSON.parse(cookie) : undefined\n } catch (error) {\n console.error(error)\n }\n },\n delete: () => removeCookie(sessionKey)\n})\n","export const redirect = async (url: string) => {\n window.location.href = url\n /**\n * This is intentional. The promise bellow will never be fulfilled.\n * Once the set href is not instantaneous, this will guarantee no further code is executed until the user is really redirected.\n * Particularly useful to prevent flickering page renders on scenarios with redirects.\n */\n await new Promise(() => '')\n}","import { AuthConfig, AuthManager, Session, ThirdPartyAuthType, ThirdPartyLoginParams } from '@stack-spot/auth'\nimport { sessionCookie } from './utils/cookies'\nimport { redirect } from './utils/redirect'\n\nconst sessionKey = 'session'\n\ninterface SessionManagerConfig extends Pick<AuthConfig, 'accountUrl' | 'authUrl' | 'clientId' | 'defaultTenant'> {\n /**\n * The URL to redirect to when the user logs out.\n * @default location.origin\n */\n loginUrl?: string,\n /**\n * The URL to redirect to when the login completes in the authentication app. If not provided, will be the same as `loginUrl`.\n * @default loginUrl\n */\n redirectUrl?: string,\n /**\n * Forbidden authentication types to this Session Manager.\n */\n blockedAuthTypes?: ThirdPartyAuthType[]\n /**\n * A URL to send login events to (observability).\n */\n rdUrl?: string,\n}\n\ntype AuthExtraData = { from?: string | null, finalRedirect?: string | null }\n\ntype ChangeListener = (session: Session | undefined) => void\n\n/**\n * Controls the current session in a browser.\n * \n * This should not be used under a Node.JS environment.\n * \n * This is a singleton. To create the first instance or recover the current one, use `SessionManager.create`.\n */\nexport class SessionManager {\n private current: Session | undefined\n private readonly auth: AuthManager<AuthExtraData>\n private config: SessionManagerConfig\n private changeListeners: ChangeListener[] = []\n static instance: SessionManager | undefined\n\n private constructor(config: SessionManagerConfig) {\n config.loginUrl ||= location.origin\n const redirectUrl = (config.redirectUrl || config.loginUrl).replace(/([^/])$/, '$1/') // the trailing \"/\" is required by Stackspot IAM.\n this.config = config\n this.auth = new AuthManager<AuthExtraData>({\n ...config,\n redirectUrl,\n storage: localStorage,\n sessionPersistence: {\n load: () => localStorage.getItem(sessionKey),\n save: (session) => localStorage.setItem(sessionKey, session),\n },\n })\n SessionManager.instance = this\n\n // Keep session in sync with other app's session\n addEventListener('focus', () => this.validateSharedSession())\n }\n\n static create(config: SessionManagerConfig) {\n return SessionManager.instance ?? new SessionManager(config)\n }\n\n private setSession(session: Session | undefined) {\n this.current = session\n this.changeListeners.forEach(l => l(session))\n if (session) this.setSessionCookie(session)\n }\n\n async restoreSession() {\n const session = await this.auth.restoreSession()\n const sessionValid = await this.validateSharedSession(session)\n this.setSession(sessionValid ? session : undefined)\n }\n\n async validateSharedSession(session: Session | undefined = this.current): Promise<boolean> {\n\n // skipping because authentication is in progress\n if (this.urlHasThirdPartyLoginData()) return false\n\n const sharedSessionCookie = sessionCookie.get()\n\n // It has been logged out on another portal, so logout on this one too\n if (!sharedSessionCookie) {\n session && await this.logout()\n return false\n }\n\n const isDifferentSessionActive = sharedSessionCookie.sub != session?.getTokenData().sub\n const isSharedSessionTypeBlocked = this.config.blockedAuthTypes?.includes(sharedSessionCookie.type)\n if (isSharedSessionTypeBlocked) return false\n else if (isDifferentSessionActive || !session) {\n await this.startThirdPartyLogin(sharedSessionCookie)\n return false\n }\n return true\n }\n\n hasSession() {\n return !!this.current && !this.current.isExpired()\n }\n\n getSession() {\n if (!this.hasSession()) {\n this.endSession()\n throw new Error('Session is not available, redirecting to login.')\n }\n return this.current!\n }\n\n async endSession(redirectToLogin = true) {\n this.current = undefined\n localStorage.removeItem(sessionKey)\n sessionCookie.delete()\n if (redirectToLogin && this.config.loginUrl) await redirect(this.config.loginUrl)\n }\n\n async logout() {\n try {\n await this.current?.logout()\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(`Could not logout from IDM.\\n${error}`)\n }\n await this.endSession()\n }\n\n async startThirdPartyLogin(data: ThirdPartyLoginParams) {\n const params = new URLSearchParams(location.search)\n const authUrl = await this.auth.startThirdPartyLogin(data, {\n from: location.href,\n finalRedirect: params.get('finalRedirect'),\n })\n await redirect(authUrl)\n }\n\n urlHasThirdPartyLoginData() {\n const url = new URL(location.toString())\n return url.searchParams.has('state') && !url.searchParams.has('error')\n }\n\n async completeThirdPartyLogin() {\n const url = new URL(location.toString())\n if (url.searchParams.has('error')) {\n throw new Error(`Error while signing in: ${url.searchParams.get('error_description')}`)\n }\n const { session, data: { from, finalRedirect } } = await this.auth.completeThirdPartyLogin(location.search)\n this.setSession(session)\n history.replaceState(null, '', from || location.toString().replace(/\\?.*$/, ''))\n this.sendLoginEventRd(this.current?.getTokenData().email, this.current?.getTokenData().name)\n if (finalRedirect) await redirect(finalRedirect)\n }\n\n getEmailForLogin() {\n const session = sessionCookie.get()\n return session?.type == 'sso' ? session.email : undefined\n }\n\n async switchAccount(accountId: string) {\n this.current && await this.auth.switchAccount(accountId, this.current)\n this.setSession(this.current)\n }\n\n onChange(listener: ChangeListener) {\n this.changeListeners.push(listener)\n return () => {\n const index = this.changeListeners.indexOf(listener)\n if (index != -1) this.changeListeners.splice(index, 1)\n }\n }\n\n private setSessionCookie(session: Session) {\n const { email, account_type, sub } = session.getTokenData()\n if (!email || !sub) return\n const isFreemium = account_type == 'FREEMIUM'\n if (isFreemium) {\n sessionCookie.set({ type: 'idp', provider: 'external-idp:github', sub })\n } else {\n sessionCookie.set({ email, type: 'sso', sub })\n }\n }\n\n private async sendLoginEventRd(email?: string, name?: string) {\n if (!this.config.rdUrl) return\n if (!email && !name) {\n // eslint-disable-next-line no-console\n console.error('Unable to trigger login hook. No sessionEmail or name identified.')\n return\n }\n\n const rdObject = {\n event_type: 'CONVERSION',\n event_family: 'CDP',\n payload: {\n email,\n name,\n conversion_identifier: 'login-v1',\n },\n }\n\n const response = await fetch(this.config.rdUrl, {\n method: 'POST',\n body: JSON.stringify(rdObject),\n headers: {\n 'content-type': 'application/json',\n },\n })\n const data = await response.json()\n\n if (!response.ok) {\n // eslint-disable-next-line no-console\n console.error('Error while sending event to RD Station', data)\n }\n }\n}\n","/* eslint-disable max-len */\nimport { Flex } from '@citric/core'\nimport { useEffectOnce } from '@stack-spot/portal-components'\nimport { CSSToCitricAdapter } from '@stack-spot/portal-theme'\nimport '@stack-spot/portal-theme/dist/theme.css'\nimport { useLanguage } from '@stack-spot/portal-translate'\nimport { useState } from 'react'\nimport { Login, LoginProps } from './Login'\nimport { SessionManager } from './SessionManager'\n\ntype AuthStatus = 'unknown' | 'authenticated' | 'unauthenticated'\n\ninterface Props {\n children: React.ReactElement,\n onLogin?: () => void,\n onSession?: () => void,\n onChangeStatus?: (status: AuthStatus) => void,\n customLoginProps?: Omit<LoginProps, 'onSubmit' | 'initialValue'>,\n sessionManager?: SessionManager,\n}\n\nexport const Authenticated = ({ children, onLogin, onSession, customLoginProps, sessionManager, onChangeStatus }: Props) => {\n const [authStatus, setAuthStatus] = useState<AuthStatus>('unknown')\n const language = useLanguage()\n sessionManager ??= SessionManager.instance\n if (!sessionManager) throw new Error('Please, provide a sessionManager')\n\n useEffectOnce(() => {\n async function checkAuth() {\n if (!sessionManager) throw new Error('Please, provide a sessionManager')\n await sessionManager.restoreSession()\n if (sessionManager.urlHasThirdPartyLoginData()) {\n await sessionManager.completeThirdPartyLogin()\n onLogin?.()\n }\n if (sessionManager.hasSession()) {\n setAuthStatus('authenticated')\n onSession?.()\n onChangeStatus?.('authenticated')\n } else {\n setAuthStatus('unauthenticated')\n onChangeStatus?.('unauthenticated')\n }\n }\n\n checkAuth()\n })\n\n if (authStatus === 'unknown') return null\n if (authStatus === 'authenticated') return children\n\n return (\n <CSSToCitricAdapter>\n <Flex justifyContent=\"center\" alignItems=\"center\" flex={1} style={{ height: '100%' }}>\n <Login\n style={{ width: '360px' }}\n onSubmit={data => sessionManager.startThirdPartyLogin({ ...data, locale: language })}\n initialValue={sessionManager.getEmailForLogin()}\n {...(customLoginProps || {})}\n />\n </Flex>\n </CSSToCitricAdapter>\n )\n}\n","import { Session } from '@stack-spot/auth'\nimport { useEffect, useState } from 'react'\nimport { SessionManager } from './SessionManager'\n\nexport function useSession() {\n const manager = SessionManager.instance\n const [session, setSession] = useState<Session | undefined>(manager?.hasSession() ? manager.getSession() : undefined)\n useEffect(() => {\n return manager?.onChange(setSession)\n }, [])\n return session\n}\n"],"names":["error","sessionKey","__spreadProps","__spreadValues"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/Login.tsx","../src/utils/cookies.ts","../src/utils/redirect.ts","../src/SessionManager.ts","../src/Authenticated.tsx","../src/hooks.ts"],"sourcesContent":["/* eslint-disable max-len */\nimport { Button, IconBox, Input, Text } from '@citric/core'\nimport { Github } from '@citric/icons'\nimport { LoadingCircular } from '@citric/ui'\nimport { BannerWarning } from '@stack-spot/portal-components'\nimport { MiniLogo } from '@stack-spot/portal-components/svg'\nimport { theme } from '@stack-spot/portal-theme'\nimport { Dictionary, useTranslate } from '@stack-spot/portal-translate'\nimport { useState } from 'react'\nimport { styled } from 'styled-components'\n\nexport type LoginType = 'sso' | 'idp'\n\ninterface BaseData {\n type: LoginType,\n}\n\ninterface SSOData extends BaseData {\n type: 'sso',\n email: string,\n}\n\ninterface IDPData extends BaseData {\n type: 'idp',\n provider: 'external-idp:github',\n}\n\ntype LoginData = SSOData | IDPData\n\nexport type LoginProps = {\n initialValue?: string,\n onSubmit: (data: LoginData) => Promise<void>,\n welcomeText?: string,\n removeLoadingOnSuccess?: boolean,\n className?: string,\n style?: React.CSSProperties,\n banner?: React.ReactNode,\n loginTypes?: LoginType[]\n}\n\nconst LoginBox = styled.form`\n display: flex;\n flex-direction: column;\n justify-content: center;\n gap: 24px;\n\n header {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 24px;\n }\n\n .title {\n font-size: 1rem;\n }\n\n .separator {\n padding: 0 8px;\n background-color: ${theme.color.light['300']};\n color: ${theme.color.light['700']};\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n gap: 20px;\n margin: 0;\n\n &:before, &:after {\n content: '';\n height: 1px;\n flex: 1;\n background-color: ${theme.color.light['600']};\n }\n }\n\n .error {\n color: ${theme.color.danger['500']};\n line-height: 1.5rem;\n }\n`\n\nexport const Login = ({ onSubmit, initialValue = '', welcomeText, removeLoadingOnSuccess, className, style, banner, loginTypes = ['idp', 'sso'] }: LoginProps) => {\n const t = useTranslate(dictionary)\n const searchParams = new URLSearchParams(location.search)\n const [error, setError] = useState(searchParams.get('error_description') || searchParams.get('error') || '')\n const [loading, setLoading] = useState(false)\n const [email, setEmail] = useState(initialValue)\n const disabled = !email.match(/\\w+@\\w+/)\n const idpLoginEnabled = loginTypes.includes('idp')\n const ssoLoginEnabled = loginTypes.includes('sso')\n\n async function login(type: LoginType) {\n setError('')\n setLoading(true)\n try {\n const data: LoginData = type === 'sso' ? { type: 'sso', email } : { type: 'idp', provider: 'external-idp:github' }\n await onSubmit(data)\n if (removeLoadingOnSuccess) setLoading(false)\n } catch (error: any) {\n setLoading(false)\n setError(error.message || error.toString())\n }\n }\n\n function submitForm(e: React.FormEvent<HTMLFormElement>) {\n e.preventDefault()\n if (disabled) return\n login('sso')\n }\n\n return (\n <>\n <LoginBox onSubmit={submitForm} className={className} style={style}>\n <header>\n <MiniLogo />\n <Text className=\"title\">{welcomeText || t.welcome}</Text>\n </header>\n {ssoLoginEnabled && <>\n <Input name=\"email\" value={email} onChange={e => setEmail(e.target.value)} placeholder={t.placeholder} />\n <Button colorScheme=\"primary\" disabled={disabled || loading}>\n {loading ? <LoadingCircular /> : <Text>{t.continue}</Text>}\n </Button>\n </>}\n {ssoLoginEnabled && idpLoginEnabled && <p className=\"separator\">{t.or}</p>}\n {idpLoginEnabled &&\n <Button colorScheme=\"light\" type=\"button\" onClick={() => login('idp')} disabled={loading}>\n {loading ? <LoadingCircular /> : (\n <>\n <IconBox>\n <Github />\n </IconBox>\n <Text>{t.loginWithGithub}</Text>\n </>\n )}\n </Button>}\n {error && <Text className=\"error\">{t.error}: {error}</Text>}\n </LoginBox>\n {banner ? <BannerWarning>\n {banner}\n </BannerWarning> : null}\n </>\n )\n}\n\nconst dictionary = {\n en: {\n welcome: 'Welcome to StackSpot',\n placeholder: 'your@email.com',\n continue: 'Continue',\n or: 'or',\n loginWithGithub: 'Login with Github',\n error: 'Error while attempting to login',\n },\n pt: {\n welcome: 'Bem vindo à StackSpot',\n placeholder: 'nome@email.com',\n continue: 'Continuar',\n or: 'ou',\n loginWithGithub: 'Logar com o GitHub',\n error: 'Erro ao fazer login',\n },\n} satisfies Dictionary\n","import { ThirdPartyLoginParams } from '@stack-spot/auth'\nimport { getCookie, getCookieDomain, removeCookie, setCookie } from '@stack-spot/portal-components'\n\nconst sessionKey = `stk-session${getCookieDomain()}`\n\ntype SessionCookie = ThirdPartyLoginParams & { sub: string, tenant: string }\n\nexport const sessionCookie = Object.freeze({\n set: (data: SessionCookie) => setCookie(sessionKey, JSON.stringify(data)),\n get: (): SessionCookie | undefined => {\n try {\n const cookie = getCookie(sessionKey)\n return cookie ? JSON.parse(cookie) : undefined\n } catch (error) {\n console.error(error)\n }\n },\n delete: () => removeCookie(sessionKey)\n})\n","export const redirect = async (url: string) => {\n window.location.href = url\n /**\n * This is intentional. The promise bellow will never be fulfilled.\n * Once the set href is not instantaneous, this will guarantee no further code is executed until the user is really redirected.\n * Particularly useful to prevent flickering page renders on scenarios with redirects.\n */\n await new Promise(() => '')\n}","import { AuthConfig, AuthManager, Session, ThirdPartyAuthType, ThirdPartyLoginParams } from '@stack-spot/auth'\nimport { sessionCookie } from './utils/cookies'\nimport { redirect } from './utils/redirect'\n\nconst sessionKey = 'session'\n\ninterface SessionManagerConfig extends Pick<AuthConfig, 'accountUrl' | 'authUrl' | 'clientId' | 'defaultTenant'> {\n /**\n * The URL to redirect to when the user logs out.\n * @default location.origin\n */\n loginUrl?: string,\n /**\n * The URL to redirect to when the login completes in the authentication app. If not provided, will be the same as `loginUrl`.\n * @default loginUrl\n */\n redirectUrl?: string,\n /**\n * Forbidden authentication types to this Session Manager.\n */\n blockedAuthTypes?: ThirdPartyAuthType[]\n /**\n * A URL to send login events to (observability).\n */\n rdUrl?: string,\n}\n\ntype AuthExtraData = { from?: string | null, finalRedirect?: string | null }\n\ntype ChangeListener = (session: Session | undefined) => void\n\n/**\n * Controls the current session in a browser.\n * \n * This should not be used under a Node.JS environment.\n * \n * This is a singleton. To create the first instance or recover the current one, use `SessionManager.create`.\n */\nexport class SessionManager {\n private current: Session | undefined\n private readonly auth: AuthManager<AuthExtraData>\n private config: SessionManagerConfig\n private changeListeners: ChangeListener[] = []\n static instance: SessionManager | undefined\n\n private constructor(config: SessionManagerConfig) {\n config.loginUrl ||= location.origin\n const redirectUrl = (config.redirectUrl || config.loginUrl).replace(/([^/])$/, '$1/') // the trailing \"/\" is required by Stackspot IAM.\n this.config = config\n this.auth = new AuthManager<AuthExtraData>({\n ...config,\n redirectUrl,\n storage: localStorage,\n sessionPersistence: {\n load: () => localStorage.getItem(sessionKey),\n save: (session) => localStorage.setItem(sessionKey, session),\n },\n })\n SessionManager.instance = this\n\n // Keep session in sync with other app's session\n addEventListener('focus', () => this.validateSharedSession())\n }\n\n static create(config: SessionManagerConfig) {\n return SessionManager.instance ?? new SessionManager(config)\n }\n\n private setSession(session: Session | undefined) {\n this.current = session\n this.changeListeners.forEach(l => l(session))\n if (session) this.setSessionCookie(session)\n }\n\n async restoreSession() {\n const session = await this.auth.restoreSession()\n const sessionValid = await this.validateSharedSession(session)\n this.setSession(sessionValid ? session : undefined)\n }\n\n async validateSharedSession(session: Session | undefined = this.current): Promise<boolean> {\n\n // skipping because authentication is in progress\n if (this.urlHasThirdPartyLoginData()) return false\n\n const sharedSessionCookie = sessionCookie.get()\n\n // It has been logged out on another portal, so logout on this one too\n if (!sharedSessionCookie) {\n session && await this.logout()\n return false\n }\n\n const isDifferentSessionActive = sharedSessionCookie.sub != session?.getTokenData().sub\n const isSharedSessionTypeBlocked = this.config.blockedAuthTypes?.includes(sharedSessionCookie.type)\n if (isSharedSessionTypeBlocked) return false\n else if (isDifferentSessionActive || !session) {\n await this.startThirdPartyLoginUsingTenant(sharedSessionCookie)\n return false\n }\n return true\n }\n\n hasSession() {\n return !!this.current && !this.current.isExpired()\n }\n\n getSession() {\n if (!this.hasSession()) {\n this.endSession()\n throw new Error('Session is not available, redirecting to login.')\n }\n return this.current!\n }\n\n async endSession(redirectToLogin = true) {\n this.current = undefined\n localStorage.removeItem(sessionKey)\n sessionCookie.delete()\n if (redirectToLogin && this.config.loginUrl) await redirect(this.config.loginUrl)\n }\n\n async logout() {\n try {\n await this.current?.logout()\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(`Could not logout from IDM.\\n${error}`)\n }\n await this.endSession()\n }\n\n async startThirdPartyLogin(data: ThirdPartyLoginParams) {\n const params = new URLSearchParams(location.search)\n const authUrl = await this.auth.startThirdPartyLogin(data, {\n from: location.href,\n finalRedirect: params.get('finalRedirect'),\n })\n await redirect(authUrl)\n }\n\n urlHasThirdPartyLoginData() {\n const url = new URL(location.toString())\n return url.searchParams.has('state') && !url.searchParams.has('error')\n }\n\n async startThirdPartyLoginUsingTenant(data: ThirdPartyLoginParams) {\n const params = new URLSearchParams(location.search)\n const cookie = sessionCookie.get()\n if (!cookie || !cookie.tenant) {\n //If no tenant is available we should log out the user\n await this.logout()\n return\n }\n const authUrl = await this.auth.getThirdPartyLoginFromTenant(data, cookie.tenant, {\n from: location.href,\n finalRedirect: params.get('finalRedirect'),\n }\n )\n await redirect(authUrl)\n }\n\n async completeThirdPartyLogin() {\n const url = new URL(location.toString())\n if (url.searchParams.has('error')) {\n throw new Error(`Error while signing in: ${url.searchParams.get('error_description')}`)\n }\n const { session, data: { from, finalRedirect } } = await this.auth.completeThirdPartyLogin(location.search)\n this.setSession(session)\n history.replaceState(null, '', from || location.toString().replace(/\\?.*$/, ''))\n this.sendLoginEventRd(this.current?.getTokenData().email, this.current?.getTokenData().name)\n if (finalRedirect) await redirect(finalRedirect)\n }\n\n getEmailForLogin() {\n const session = sessionCookie.get()\n return session?.type == 'sso' ? session.email : undefined\n }\n\n async switchAccount(accountId: string) {\n this.current && await this.auth.switchAccount(accountId, this.current)\n this.setSession(this.current)\n }\n\n onChange(listener: ChangeListener) {\n this.changeListeners.push(listener)\n return () => {\n const index = this.changeListeners.indexOf(listener)\n if (index != -1) this.changeListeners.splice(index, 1)\n }\n }\n\n private setSessionCookie(session: Session) {\n const { email, account_type, sub, tenant } = session.getTokenData()\n if (!email || !sub || !tenant) return\n const isFreemium = account_type == 'FREEMIUM'\n if (isFreemium) {\n sessionCookie.set({ type: 'idp', provider: 'external-idp:github', sub, tenant })\n } else {\n sessionCookie.set({ email, type: 'sso', sub, tenant })\n }\n }\n\n private async sendLoginEventRd(email?: string, name?: string) {\n if (!this.config.rdUrl) return\n if (!email && !name) {\n // eslint-disable-next-line no-console\n console.error('Unable to trigger login hook. No sessionEmail or name identified.')\n return\n }\n\n const rdObject = {\n event_type: 'CONVERSION',\n event_family: 'CDP',\n payload: {\n email,\n name,\n conversion_identifier: 'login-v1',\n },\n }\n\n const response = await fetch(this.config.rdUrl, {\n method: 'POST',\n body: JSON.stringify(rdObject),\n headers: {\n 'content-type': 'application/json',\n },\n })\n const data = await response.json()\n\n if (!response.ok) {\n // eslint-disable-next-line no-console\n console.error('Error while sending event to RD Station', data)\n }\n }\n}\n","/* eslint-disable max-len */\nimport { Flex } from '@citric/core'\nimport { useEffectOnce } from '@stack-spot/portal-components'\nimport { CSSToCitricAdapter } from '@stack-spot/portal-theme'\nimport '@stack-spot/portal-theme/dist/theme.css'\nimport { useLanguage } from '@stack-spot/portal-translate'\nimport { useState } from 'react'\nimport { Login, LoginProps } from './Login'\nimport { SessionManager } from './SessionManager'\n\ntype AuthStatus = 'unknown' | 'authenticated' | 'unauthenticated'\n\ninterface Props {\n children: React.ReactElement,\n onLogin?: () => void,\n onSession?: () => void,\n onChangeStatus?: (status: AuthStatus) => void,\n customLoginProps?: Omit<LoginProps, 'onSubmit' | 'initialValue'>,\n sessionManager?: SessionManager,\n}\n\nexport const Authenticated = ({ children, onLogin, onSession, customLoginProps, sessionManager, onChangeStatus }: Props) => {\n const [authStatus, setAuthStatus] = useState<AuthStatus>('unknown')\n const language = useLanguage()\n sessionManager ??= SessionManager.instance\n if (!sessionManager) throw new Error('Please, provide a sessionManager')\n\n useEffectOnce(() => {\n async function checkAuth() {\n if (!sessionManager) throw new Error('Please, provide a sessionManager')\n await sessionManager.restoreSession()\n if (sessionManager.urlHasThirdPartyLoginData()) {\n await sessionManager.completeThirdPartyLogin()\n onLogin?.()\n }\n if (sessionManager.hasSession()) {\n setAuthStatus('authenticated')\n onSession?.()\n onChangeStatus?.('authenticated')\n } else {\n setAuthStatus('unauthenticated')\n onChangeStatus?.('unauthenticated')\n }\n }\n\n checkAuth()\n })\n\n if (authStatus === 'unknown') return null\n if (authStatus === 'authenticated') return children\n\n return (\n <CSSToCitricAdapter>\n <Flex justifyContent=\"center\" alignItems=\"center\" flex={1} style={{ height: '100%' }}>\n <Login\n style={{ width: '360px' }}\n onSubmit={data => sessionManager.startThirdPartyLogin({ ...data, locale: language })}\n initialValue={sessionManager.getEmailForLogin()}\n {...(customLoginProps || {})}\n />\n </Flex>\n </CSSToCitricAdapter>\n )\n}\n","import { Session } from '@stack-spot/auth'\nimport { useEffect, useState } from 'react'\nimport { SessionManager } from './SessionManager'\n\nexport function useSession() {\n const manager = SessionManager.instance\n const [session, setSession] = useState<Session | undefined>(manager?.hasSession() ? manager.getSession() : undefined)\n useEffect(() => {\n return manager?.onChange(setSession)\n }, [])\n return session\n}\n"],"names":["error","sessionKey","__spreadProps","__spreadValues"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stack-spot/auth-react",
3
- "version": "1.7.0",
3
+ "version": "2.1.0",
4
4
  "main": "out/index.js",
5
5
  "module": "out/index.mjs",
6
6
  "typings": "out/index.d.ts",
@@ -29,7 +29,7 @@
29
29
  "@citric/core": "^5.0.0 || ^6.0.0",
30
30
  "@citric/icons": "^5.0.0",
31
31
  "@citric/ui": "^5.0.0 || ^6.0.0",
32
- "@stack-spot/auth": "^5.0.0",
32
+ "@stack-spot/auth": "^5.3.0",
33
33
  "@stack-spot/portal-theme": "^1.0.0",
34
34
  "@stack-spot/portal-components": "^1.0.0 || ^2.0.0",
35
35
  "@stack-spot/portal-translate": "^1.0.0",
@@ -95,7 +95,7 @@ export class SessionManager {
95
95
  const isSharedSessionTypeBlocked = this.config.blockedAuthTypes?.includes(sharedSessionCookie.type)
96
96
  if (isSharedSessionTypeBlocked) return false
97
97
  else if (isDifferentSessionActive || !session) {
98
- await this.startThirdPartyLogin(sharedSessionCookie)
98
+ await this.startThirdPartyLoginUsingTenant(sharedSessionCookie)
99
99
  return false
100
100
  }
101
101
  return true
@@ -144,6 +144,22 @@ export class SessionManager {
144
144
  return url.searchParams.has('state') && !url.searchParams.has('error')
145
145
  }
146
146
 
147
+ async startThirdPartyLoginUsingTenant(data: ThirdPartyLoginParams) {
148
+ const params = new URLSearchParams(location.search)
149
+ const cookie = sessionCookie.get()
150
+ if (!cookie || !cookie.tenant) {
151
+ //If no tenant is available we should log out the user
152
+ await this.logout()
153
+ return
154
+ }
155
+ const authUrl = await this.auth.getThirdPartyLoginFromTenant(data, cookie.tenant, {
156
+ from: location.href,
157
+ finalRedirect: params.get('finalRedirect'),
158
+ }
159
+ )
160
+ await redirect(authUrl)
161
+ }
162
+
147
163
  async completeThirdPartyLogin() {
148
164
  const url = new URL(location.toString())
149
165
  if (url.searchParams.has('error')) {
@@ -175,13 +191,13 @@ export class SessionManager {
175
191
  }
176
192
 
177
193
  private setSessionCookie(session: Session) {
178
- const { email, account_type, sub } = session.getTokenData()
179
- if (!email || !sub) return
194
+ const { email, account_type, sub, tenant } = session.getTokenData()
195
+ if (!email || !sub || !tenant) return
180
196
  const isFreemium = account_type == 'FREEMIUM'
181
197
  if (isFreemium) {
182
- sessionCookie.set({ type: 'idp', provider: 'external-idp:github', sub })
198
+ sessionCookie.set({ type: 'idp', provider: 'external-idp:github', sub, tenant })
183
199
  } else {
184
- sessionCookie.set({ email, type: 'sso', sub })
200
+ sessionCookie.set({ email, type: 'sso', sub, tenant })
185
201
  }
186
202
  }
187
203
 
@@ -3,7 +3,7 @@ import { getCookie, getCookieDomain, removeCookie, setCookie } from '@stack-spot
3
3
 
4
4
  const sessionKey = `stk-session${getCookieDomain()}`
5
5
 
6
- type SessionCookie = ThirdPartyLoginParams & { sub: string }
6
+ type SessionCookie = ThirdPartyLoginParams & { sub: string, tenant: string }
7
7
 
8
8
  export const sessionCookie = Object.freeze({
9
9
  set: (data: SessionCookie) => setCookie(sessionKey, JSON.stringify(data)),