@stack-spot/auth-react 1.1.1 → 1.2.1

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/out/index.d.ts CHANGED
@@ -1,13 +1,10 @@
1
- import { AuthManager, Session, ThirdPartyLoginParams, AuthConfig } from '@stack-spot/auth';
1
+ import { Session, ThirdPartyLoginParams, AuthConfig, ThirdPartyAuthType } from '@stack-spot/auth';
2
2
 
3
3
  interface SessionManagerConfig extends Pick<AuthConfig, 'accountUrl' | 'authUrl' | 'clientId' | 'defaultTenant' | 'redirectUrl'> {
4
4
  loginUrl: string;
5
+ blockedAuthTypes?: ThirdPartyAuthType[];
5
6
  rdUrl?: string;
6
7
  }
7
- type AuthExtraData = {
8
- from?: string | null;
9
- finalRedirect?: string | null;
10
- };
11
8
  type ChangeListener = (session: Session | undefined) => void;
12
9
  /**
13
10
  * Controls the current session in a browser.
@@ -18,7 +15,7 @@ type ChangeListener = (session: Session | undefined) => void;
18
15
  */
19
16
  declare class SessionManager {
20
17
  private current;
21
- readonly auth: AuthManager<AuthExtraData>;
18
+ private readonly auth;
22
19
  private config;
23
20
  private changeListeners;
24
21
  static instance: SessionManager;
@@ -26,7 +23,7 @@ declare class SessionManager {
26
23
  static create(config: SessionManagerConfig): SessionManager;
27
24
  private setSession;
28
25
  restoreSession(): Promise<void>;
29
- validateSharedSession(session?: Session | undefined): Promise<void>;
26
+ validateSharedSession(session?: Session | undefined): Promise<boolean>;
30
27
  hasSession(): boolean;
31
28
  getSession(): Session;
32
29
  endSession(redirectToLogin?: boolean): void;
@@ -35,7 +32,9 @@ declare class SessionManager {
35
32
  urlHasThirdPartyLoginData(): boolean;
36
33
  completeThirdPartyLogin(): Promise<void>;
37
34
  getEmailForLogin(): string | undefined;
35
+ switchAccount(accountId: string): Promise<void>;
38
36
  onChange(listener: ChangeListener): () => void;
37
+ private redirectToLoginUrl;
39
38
  private setSessionCookie;
40
39
  private sendLoginEventRd;
41
40
  }
package/out/index.js CHANGED
@@ -81,29 +81,33 @@ const _SessionManager = class _SessionManager {
81
81
  }
82
82
  setSession(session) {
83
83
  this.current = session;
84
+ this.changeListeners.forEach((l) => l(session));
84
85
  if (session)
85
86
  this.setSessionCookie(session);
86
- else {
87
- localStorage.removeItem(sessionKey);
88
- sessionCookie.delete();
89
- }
90
- this.changeListeners.forEach((l) => l(session));
91
87
  }
92
88
  async restoreSession() {
93
89
  const session = await this.auth.restoreSession();
94
- await this.validateSharedSession(session);
95
- if (session)
96
- this.setSession(session);
90
+ const sessionValid = await this.validateSharedSession(session);
91
+ this.setSession(sessionValid ? session : void 0);
97
92
  }
98
93
  async validateSharedSession(session = this.current) {
94
+ var _a;
95
+ if (this.urlHasThirdPartyLoginData())
96
+ return false;
99
97
  const sharedSessionCookie = sessionCookie.get();
100
- if (sharedSessionCookie) {
101
- const isDifferentSessionActive = sharedSessionCookie.sub != (session == null ? void 0 : session.getTokenData().sub);
102
- const noSessionActive = !session && !this.urlHasThirdPartyLoginData();
103
- if (isDifferentSessionActive || noSessionActive)
104
- this.startThirdPartyLogin(sharedSessionCookie);
105
- } else if (session)
106
- await this.logout();
98
+ if (!sharedSessionCookie) {
99
+ session && await this.logout();
100
+ return false;
101
+ }
102
+ const isDifferentSessionActive = sharedSessionCookie.sub != (session == null ? void 0 : session.getTokenData().sub);
103
+ const isSharedSessionTypeBlocked = (_a = this.config.blockedAuthTypes) == null ? void 0 : _a.includes(sharedSessionCookie.type);
104
+ if (isSharedSessionTypeBlocked)
105
+ return false;
106
+ else if (isDifferentSessionActive || !session) {
107
+ this.startThirdPartyLogin(sharedSessionCookie);
108
+ return false;
109
+ }
110
+ return true;
107
111
  }
108
112
  hasSession() {
109
113
  return !!this.current && !this.current.isExpired();
@@ -117,8 +121,10 @@ const _SessionManager = class _SessionManager {
117
121
  }
118
122
  endSession(redirectToLogin = true) {
119
123
  this.setSession(void 0);
124
+ localStorage.removeItem(sessionKey);
125
+ sessionCookie.delete();
120
126
  if (redirectToLogin)
121
- window.location.href = this.config.loginUrl;
127
+ this.redirectToLoginUrl();
122
128
  }
123
129
  async logout() {
124
130
  var _a;
@@ -159,6 +165,10 @@ ${error}`);
159
165
  const session = sessionCookie.get();
160
166
  return (session == null ? void 0 : session.type) == "sso" ? session.email : void 0;
161
167
  }
168
+ async switchAccount(accountId) {
169
+ this.current && await this.auth.switchAccount(accountId, this.current);
170
+ this.setSession(this.current);
171
+ }
162
172
  onChange(listener) {
163
173
  this.changeListeners.push(listener);
164
174
  return () => {
@@ -167,6 +177,9 @@ ${error}`);
167
177
  this.changeListeners.splice(index, 1);
168
178
  };
169
179
  }
180
+ redirectToLoginUrl() {
181
+ window.location.href = this.config.loginUrl;
182
+ }
170
183
  setSessionCookie(session) {
171
184
  const { email, account_type, sub } = session.getTokenData();
172
185
  if (!email || !sub)
package/out/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/utils/cookies.ts","../src/SessionManager.ts","../src/hooks.ts"],"sourcesContent":["import { ThirdPartyLoginParams } from \"@stack-spot/auth\"\n\nconst sessionKey = 'stk-session'\nconst portalUrl = new URL(location.href)\nconst domainRegex = new RegExp(/(\\.*(prd|stg|dev)*.stackspot.com)|localhost/)\nconst cookieDomain = domainRegex.exec(portalUrl.host)?.[0]\nconst defaultCookieAttributes = `domain=${cookieDomain}; SameSite=Strict;`\n\nconst setCookie = (key: string, value: string) => {\n document.cookie = `${key}=${value}; ${defaultCookieAttributes}`\n}\n\nconst removeCookie = (key: string) => {\n document.cookie = `${key}=; max-age=0; ${defaultCookieAttributes}`\n}\n\nconst getCookie = (key: string) => getCookies()[key]\n\nconst getCookies = (): Record<string, string> => document.cookie.split('; ').reduce((prev, current) => {\n const [name, ...value] = current.split('=')\n prev[name] = value.join('=')\n return prev\n}, {} as Record<string, string>)\n\n\ntype SessionCookie = ThirdPartyLoginParams & { sub: string }\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})","import { AuthConfig, AuthManager, Session, ThirdPartyLoginParams } from '@stack-spot/auth'\nimport { sessionCookie } from './utils/cookies'\n\nconst sessionKey = 'session'\n\ninterface SessionManagerConfig extends Pick<AuthConfig, 'accountUrl' | 'authUrl' | 'clientId' | 'defaultTenant' | 'redirectUrl'> {\n loginUrl: string,\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 readonly auth: AuthManager<AuthExtraData>\n private config: SessionManagerConfig\n private changeListeners: ChangeListener[] = []\n static instance: SessionManager\n\n private constructor(config: SessionManagerConfig) {\n this.config = config\n this.auth = new AuthManager<AuthExtraData>({\n ...config,\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 if (session) this.setSessionCookie(session)\n else {\n localStorage.removeItem(sessionKey)\n sessionCookie.delete()\n }\n this.changeListeners.forEach(l => l(session))\n }\n\n async restoreSession() {\n const session = await this.auth.restoreSession()\n await this.validateSharedSession(session)\n if (session) this.setSession(session)\n }\n\n async validateSharedSession(session: Session | undefined = this.current) {\n const sharedSessionCookie = sessionCookie.get()\n if (sharedSessionCookie) {\n const isDifferentSessionActive = sharedSessionCookie.sub != session?.getTokenData().sub\n const noSessionActive = !session && !this.urlHasThirdPartyLoginData()\n if (isDifferentSessionActive || noSessionActive) this.startThirdPartyLogin(sharedSessionCookie)\n }\n else if (session) await this.logout()\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 endSession(redirectToLogin = true) {\n this.setSession(undefined)\n if (redirectToLogin) window.location.href = 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 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 location.href = 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 if (finalRedirect) location.href = finalRedirect\n history.replaceState(null, '', from || location.toString().replace(/\\?.*$/, ''))\n this.sendLoginEventRd(this.current?.getTokenData().email, this.current?.getTokenData().name)\n }\n\n getEmailForLogin() {\n const session = sessionCookie.get()\n return session?.type == 'sso' ? session.email : undefined\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","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":["sessionKey","AuthManager","useState","useEffect"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/utils/cookies.ts","../src/SessionManager.ts","../src/hooks.ts"],"sourcesContent":["import { ThirdPartyLoginParams } from \"@stack-spot/auth\"\n\nconst sessionKey = 'stk-session'\nconst portalUrl = new URL(location.href)\nconst domainRegex = new RegExp(/(\\.*(prd|stg|dev)*.stackspot.com)|localhost/)\nconst cookieDomain = domainRegex.exec(portalUrl.host)?.[0]\nconst defaultCookieAttributes = `domain=${cookieDomain}; SameSite=Strict;`\n\nconst setCookie = (key: string, value: string) => {\n document.cookie = `${key}=${value}; ${defaultCookieAttributes}`\n}\n\nconst removeCookie = (key: string) => {\n document.cookie = `${key}=; max-age=0; ${defaultCookieAttributes}`\n}\n\nconst getCookie = (key: string) => getCookies()[key]\n\nconst getCookies = (): Record<string, string> => document.cookie.split('; ').reduce((prev, current) => {\n const [name, ...value] = current.split('=')\n prev[name] = value.join('=')\n return prev\n}, {} as Record<string, string>)\n\n\ntype SessionCookie = ThirdPartyLoginParams & { sub: string }\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})","import { AuthConfig, AuthManager, Session, ThirdPartyAuthType, ThirdPartyLoginParams } from '@stack-spot/auth'\nimport { sessionCookie } from './utils/cookies'\n\nconst sessionKey = 'session'\n\ninterface SessionManagerConfig extends Pick<AuthConfig, 'accountUrl' | 'authUrl' | 'clientId' | 'defaultTenant' | 'redirectUrl'> {\n loginUrl: string,\n blockedAuthTypes?: ThirdPartyAuthType[]\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\n\n private constructor(config: SessionManagerConfig) {\n this.config = config\n this.auth = new AuthManager<AuthExtraData>({\n ...config,\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 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 endSession(redirectToLogin = true) {\n this.setSession(undefined)\n localStorage.removeItem(sessionKey)\n sessionCookie.delete()\n if (redirectToLogin) this.redirectToLoginUrl()\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 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 location.href = 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 if (finalRedirect) location.href = finalRedirect\n history.replaceState(null, '', from || location.toString().replace(/\\?.*$/, ''))\n this.sendLoginEventRd(this.current?.getTokenData().email, this.current?.getTokenData().name)\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 redirectToLoginUrl() {\n window.location.href = this.config.loginUrl\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","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":["sessionKey","AuthManager","useState","useEffect"],"mappings":"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"}
package/out/index.mjs CHANGED
@@ -79,29 +79,33 @@ const _SessionManager = class _SessionManager {
79
79
  }
80
80
  setSession(session) {
81
81
  this.current = session;
82
+ this.changeListeners.forEach((l) => l(session));
82
83
  if (session)
83
84
  this.setSessionCookie(session);
84
- else {
85
- localStorage.removeItem(sessionKey);
86
- sessionCookie.delete();
87
- }
88
- this.changeListeners.forEach((l) => l(session));
89
85
  }
90
86
  async restoreSession() {
91
87
  const session = await this.auth.restoreSession();
92
- await this.validateSharedSession(session);
93
- if (session)
94
- this.setSession(session);
88
+ const sessionValid = await this.validateSharedSession(session);
89
+ this.setSession(sessionValid ? session : void 0);
95
90
  }
96
91
  async validateSharedSession(session = this.current) {
92
+ var _a;
93
+ if (this.urlHasThirdPartyLoginData())
94
+ return false;
97
95
  const sharedSessionCookie = sessionCookie.get();
98
- if (sharedSessionCookie) {
99
- const isDifferentSessionActive = sharedSessionCookie.sub != (session == null ? void 0 : session.getTokenData().sub);
100
- const noSessionActive = !session && !this.urlHasThirdPartyLoginData();
101
- if (isDifferentSessionActive || noSessionActive)
102
- this.startThirdPartyLogin(sharedSessionCookie);
103
- } else if (session)
104
- await this.logout();
96
+ if (!sharedSessionCookie) {
97
+ session && await this.logout();
98
+ return false;
99
+ }
100
+ const isDifferentSessionActive = sharedSessionCookie.sub != (session == null ? void 0 : session.getTokenData().sub);
101
+ const isSharedSessionTypeBlocked = (_a = this.config.blockedAuthTypes) == null ? void 0 : _a.includes(sharedSessionCookie.type);
102
+ if (isSharedSessionTypeBlocked)
103
+ return false;
104
+ else if (isDifferentSessionActive || !session) {
105
+ this.startThirdPartyLogin(sharedSessionCookie);
106
+ return false;
107
+ }
108
+ return true;
105
109
  }
106
110
  hasSession() {
107
111
  return !!this.current && !this.current.isExpired();
@@ -115,8 +119,10 @@ const _SessionManager = class _SessionManager {
115
119
  }
116
120
  endSession(redirectToLogin = true) {
117
121
  this.setSession(void 0);
122
+ localStorage.removeItem(sessionKey);
123
+ sessionCookie.delete();
118
124
  if (redirectToLogin)
119
- window.location.href = this.config.loginUrl;
125
+ this.redirectToLoginUrl();
120
126
  }
121
127
  async logout() {
122
128
  var _a;
@@ -157,6 +163,10 @@ ${error}`);
157
163
  const session = sessionCookie.get();
158
164
  return (session == null ? void 0 : session.type) == "sso" ? session.email : void 0;
159
165
  }
166
+ async switchAccount(accountId) {
167
+ this.current && await this.auth.switchAccount(accountId, this.current);
168
+ this.setSession(this.current);
169
+ }
160
170
  onChange(listener) {
161
171
  this.changeListeners.push(listener);
162
172
  return () => {
@@ -165,6 +175,9 @@ ${error}`);
165
175
  this.changeListeners.splice(index, 1);
166
176
  };
167
177
  }
178
+ redirectToLoginUrl() {
179
+ window.location.href = this.config.loginUrl;
180
+ }
168
181
  setSessionCookie(session) {
169
182
  const { email, account_type, sub } = session.getTokenData();
170
183
  if (!email || !sub)
package/out/index.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/utils/cookies.ts","../src/SessionManager.ts","../src/hooks.ts"],"sourcesContent":["import { ThirdPartyLoginParams } from \"@stack-spot/auth\"\n\nconst sessionKey = 'stk-session'\nconst portalUrl = new URL(location.href)\nconst domainRegex = new RegExp(/(\\.*(prd|stg|dev)*.stackspot.com)|localhost/)\nconst cookieDomain = domainRegex.exec(portalUrl.host)?.[0]\nconst defaultCookieAttributes = `domain=${cookieDomain}; SameSite=Strict;`\n\nconst setCookie = (key: string, value: string) => {\n document.cookie = `${key}=${value}; ${defaultCookieAttributes}`\n}\n\nconst removeCookie = (key: string) => {\n document.cookie = `${key}=; max-age=0; ${defaultCookieAttributes}`\n}\n\nconst getCookie = (key: string) => getCookies()[key]\n\nconst getCookies = (): Record<string, string> => document.cookie.split('; ').reduce((prev, current) => {\n const [name, ...value] = current.split('=')\n prev[name] = value.join('=')\n return prev\n}, {} as Record<string, string>)\n\n\ntype SessionCookie = ThirdPartyLoginParams & { sub: string }\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})","import { AuthConfig, AuthManager, Session, ThirdPartyLoginParams } from '@stack-spot/auth'\nimport { sessionCookie } from './utils/cookies'\n\nconst sessionKey = 'session'\n\ninterface SessionManagerConfig extends Pick<AuthConfig, 'accountUrl' | 'authUrl' | 'clientId' | 'defaultTenant' | 'redirectUrl'> {\n loginUrl: string,\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 readonly auth: AuthManager<AuthExtraData>\n private config: SessionManagerConfig\n private changeListeners: ChangeListener[] = []\n static instance: SessionManager\n\n private constructor(config: SessionManagerConfig) {\n this.config = config\n this.auth = new AuthManager<AuthExtraData>({\n ...config,\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 if (session) this.setSessionCookie(session)\n else {\n localStorage.removeItem(sessionKey)\n sessionCookie.delete()\n }\n this.changeListeners.forEach(l => l(session))\n }\n\n async restoreSession() {\n const session = await this.auth.restoreSession()\n await this.validateSharedSession(session)\n if (session) this.setSession(session)\n }\n\n async validateSharedSession(session: Session | undefined = this.current) {\n const sharedSessionCookie = sessionCookie.get()\n if (sharedSessionCookie) {\n const isDifferentSessionActive = sharedSessionCookie.sub != session?.getTokenData().sub\n const noSessionActive = !session && !this.urlHasThirdPartyLoginData()\n if (isDifferentSessionActive || noSessionActive) this.startThirdPartyLogin(sharedSessionCookie)\n }\n else if (session) await this.logout()\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 endSession(redirectToLogin = true) {\n this.setSession(undefined)\n if (redirectToLogin) window.location.href = 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 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 location.href = 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 if (finalRedirect) location.href = finalRedirect\n history.replaceState(null, '', from || location.toString().replace(/\\?.*$/, ''))\n this.sendLoginEventRd(this.current?.getTokenData().email, this.current?.getTokenData().name)\n }\n\n getEmailForLogin() {\n const session = sessionCookie.get()\n return session?.type == 'sso' ? session.email : undefined\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","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":["sessionKey"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/utils/cookies.ts","../src/SessionManager.ts","../src/hooks.ts"],"sourcesContent":["import { ThirdPartyLoginParams } from \"@stack-spot/auth\"\n\nconst sessionKey = 'stk-session'\nconst portalUrl = new URL(location.href)\nconst domainRegex = new RegExp(/(\\.*(prd|stg|dev)*.stackspot.com)|localhost/)\nconst cookieDomain = domainRegex.exec(portalUrl.host)?.[0]\nconst defaultCookieAttributes = `domain=${cookieDomain}; SameSite=Strict;`\n\nconst setCookie = (key: string, value: string) => {\n document.cookie = `${key}=${value}; ${defaultCookieAttributes}`\n}\n\nconst removeCookie = (key: string) => {\n document.cookie = `${key}=; max-age=0; ${defaultCookieAttributes}`\n}\n\nconst getCookie = (key: string) => getCookies()[key]\n\nconst getCookies = (): Record<string, string> => document.cookie.split('; ').reduce((prev, current) => {\n const [name, ...value] = current.split('=')\n prev[name] = value.join('=')\n return prev\n}, {} as Record<string, string>)\n\n\ntype SessionCookie = ThirdPartyLoginParams & { sub: string }\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})","import { AuthConfig, AuthManager, Session, ThirdPartyAuthType, ThirdPartyLoginParams } from '@stack-spot/auth'\nimport { sessionCookie } from './utils/cookies'\n\nconst sessionKey = 'session'\n\ninterface SessionManagerConfig extends Pick<AuthConfig, 'accountUrl' | 'authUrl' | 'clientId' | 'defaultTenant' | 'redirectUrl'> {\n loginUrl: string,\n blockedAuthTypes?: ThirdPartyAuthType[]\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\n\n private constructor(config: SessionManagerConfig) {\n this.config = config\n this.auth = new AuthManager<AuthExtraData>({\n ...config,\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 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 endSession(redirectToLogin = true) {\n this.setSession(undefined)\n localStorage.removeItem(sessionKey)\n sessionCookie.delete()\n if (redirectToLogin) this.redirectToLoginUrl()\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 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 location.href = 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 if (finalRedirect) location.href = finalRedirect\n history.replaceState(null, '', from || location.toString().replace(/\\?.*$/, ''))\n this.sendLoginEventRd(this.current?.getTokenData().email, this.current?.getTokenData().name)\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 redirectToLoginUrl() {\n window.location.href = this.config.loginUrl\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","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":["sessionKey"],"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.1.1",
3
+ "version": "1.2.1",
4
4
  "main": "out/index.js",
5
5
  "module": "out/index.mjs",
6
6
  "typings": "out/index.d.ts",
@@ -1,10 +1,11 @@
1
- import { AuthConfig, AuthManager, Session, ThirdPartyLoginParams } from '@stack-spot/auth'
1
+ import { AuthConfig, AuthManager, Session, ThirdPartyAuthType, ThirdPartyLoginParams } from '@stack-spot/auth'
2
2
  import { sessionCookie } from './utils/cookies'
3
3
 
4
4
  const sessionKey = 'session'
5
5
 
6
6
  interface SessionManagerConfig extends Pick<AuthConfig, 'accountUrl' | 'authUrl' | 'clientId' | 'defaultTenant' | 'redirectUrl'> {
7
7
  loginUrl: string,
8
+ blockedAuthTypes?: ThirdPartyAuthType[]
8
9
  rdUrl?: string,
9
10
  }
10
11
 
@@ -21,7 +22,7 @@ type ChangeListener = (session: Session | undefined) => void
21
22
  */
22
23
  export class SessionManager {
23
24
  private current: Session | undefined
24
- readonly auth: AuthManager<AuthExtraData>
25
+ private readonly auth: AuthManager<AuthExtraData>
25
26
  private config: SessionManagerConfig
26
27
  private changeListeners: ChangeListener[] = []
27
28
  static instance: SessionManager
@@ -48,28 +49,37 @@ export class SessionManager {
48
49
 
49
50
  private setSession(session: Session | undefined) {
50
51
  this.current = session
51
- if (session) this.setSessionCookie(session)
52
- else {
53
- localStorage.removeItem(sessionKey)
54
- sessionCookie.delete()
55
- }
56
52
  this.changeListeners.forEach(l => l(session))
53
+ if (session) this.setSessionCookie(session)
57
54
  }
58
55
 
59
56
  async restoreSession() {
60
57
  const session = await this.auth.restoreSession()
61
- await this.validateSharedSession(session)
62
- if (session) this.setSession(session)
58
+ const sessionValid = await this.validateSharedSession(session)
59
+ this.setSession(sessionValid ? session : undefined)
63
60
  }
64
61
 
65
- async validateSharedSession(session: Session | undefined = this.current) {
62
+ async validateSharedSession(session: Session | undefined = this.current): Promise<boolean> {
63
+
64
+ // skipping because authentication is in progress
65
+ if (this.urlHasThirdPartyLoginData()) return false
66
+
66
67
  const sharedSessionCookie = sessionCookie.get()
67
- if (sharedSessionCookie) {
68
- const isDifferentSessionActive = sharedSessionCookie.sub != session?.getTokenData().sub
69
- const noSessionActive = !session && !this.urlHasThirdPartyLoginData()
70
- if (isDifferentSessionActive || noSessionActive) this.startThirdPartyLogin(sharedSessionCookie)
68
+
69
+ // It has been logged out on another portal, so logout on this one too
70
+ if (!sharedSessionCookie) {
71
+ session && await this.logout()
72
+ return false
71
73
  }
72
- else if (session) await this.logout()
74
+
75
+ const isDifferentSessionActive = sharedSessionCookie.sub != session?.getTokenData().sub
76
+ const isSharedSessionTypeBlocked = this.config.blockedAuthTypes?.includes(sharedSessionCookie.type)
77
+ if (isSharedSessionTypeBlocked) return false
78
+ else if (isDifferentSessionActive || !session) {
79
+ this.startThirdPartyLogin(sharedSessionCookie)
80
+ return false
81
+ }
82
+ return true
73
83
  }
74
84
 
75
85
  hasSession() {
@@ -86,7 +96,9 @@ export class SessionManager {
86
96
 
87
97
  endSession(redirectToLogin = true) {
88
98
  this.setSession(undefined)
89
- if (redirectToLogin) window.location.href = this.config.loginUrl
99
+ localStorage.removeItem(sessionKey)
100
+ sessionCookie.delete()
101
+ if (redirectToLogin) this.redirectToLoginUrl()
90
102
  }
91
103
 
92
104
  async logout() {
@@ -130,6 +142,11 @@ export class SessionManager {
130
142
  return session?.type == 'sso' ? session.email : undefined
131
143
  }
132
144
 
145
+ async switchAccount(accountId: string) {
146
+ this.current && await this.auth.switchAccount(accountId, this.current)
147
+ this.setSession(this.current)
148
+ }
149
+
133
150
  onChange(listener: ChangeListener) {
134
151
  this.changeListeners.push(listener)
135
152
  return () => {
@@ -138,6 +155,10 @@ export class SessionManager {
138
155
  }
139
156
  }
140
157
 
158
+ private redirectToLoginUrl() {
159
+ window.location.href = this.config.loginUrl
160
+ }
161
+
141
162
  private setSessionCookie(session: Session) {
142
163
  const { email, account_type, sub } = session.getTokenData()
143
164
  if (!email || !sub) return