@functionalcms/svelte-components 2.35.0 → 2.35.2

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.
@@ -1,14 +1,12 @@
1
1
  import {} from '@sveltejs/kit';
2
2
  const authSessionCookieName = `auth_session`;
3
- const returnPageCookieName = `returnTo`;
4
- const logout = async (cookies, token, provider, sessionProvider, afterLogoutPath = '/') => {
3
+ const logout = async (cookies, sessionProvider, afterLogoutPath = '/') => {
5
4
  const headers = new Headers();
6
5
  const state = cookies.get(authSessionCookieName);
7
6
  if (state) {
8
7
  cookies.delete('auth_session', { path: '/' });
9
8
  const sid = cookies.get('auth_session');
10
9
  await sessionProvider.deleteSession(sid);
11
- await provider.logout(token);
12
10
  headers.append('Set-Cookie', `${authSessionCookieName}=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT;`);
13
11
  headers.append('Location', afterLogoutPath);
14
12
  }
@@ -26,10 +24,11 @@ const createUserSession = async (provider, event, sessionProvider) => {
26
24
  event.locals.session = session;
27
25
  event.locals.accessToken = token.access_token;
28
26
  const sessionId = await sessionProvider.createSession({ session, token }, token.expires_in);
29
- const retrunToAddress = event.cookies.get("lastPage");
30
- headers.append('Location', lastPage != '' ? retrunToAddress : provider.redirectPath);
31
- headers.append('Set-Cookie', `${authSessionCookieName}=${sessionId}; HttpOnly; Secure; SameSite=Lax; Max-Age=3600; Path=/`);
32
- headers.append('Set-Cookie', `${returnPageCookieName}=; HttpOnly; Secure; SameSite=Lax; Max-Age=${token.expires_in + 120}; Path=/`);
27
+ const retrunToAddress = event.cookies.get("retrunToAddress");
28
+ headers.append('Location', retrunToAddress != '' ? retrunToAddress : provider.redirectPath);
29
+ headers.append('Set-Cookie', `${authSessionCookieName}=${sessionId}; HttpOnly; Secure; SameSite=Lax; Max-Age=${token.expires_in + 120}; Path=/`);
30
+ headers.append('Set-Cookie', `retrunToAddress=; HttpOnly; Secure; SameSite=Lax; Max-Age=${token.expires_in + 120}; Path=/`);
31
+ // `${authSessionCookieName}=${sessionId}; HttpOnly; Secure; SameSite=Lax; Max-Age=${token.expires_in}; Path=/`);
33
32
  }
34
33
  else {
35
34
  headers.append('Location', '/');
@@ -56,7 +55,7 @@ export const authenticationHandle = (provider, sessionProvider) => {
56
55
  //logout
57
56
  if (event.url.pathname === '/auth/logout') {
58
57
  // await provider.logout();
59
- const headers = await logout(event.cookies, event.locals.token, provider, sessionProvider);
58
+ const headers = await logout(event.cookies, sessionProvider);
60
59
  return new Response('Logging Out...', { status: 303, headers });
61
60
  }
62
61
  // login
@@ -1,3 +1,3 @@
1
1
  import { type Handle } from '@sveltejs/kit';
2
- declare const authorizationHandle: () => Handle;
2
+ declare const authorizationHandle: (protectedPaths: Array<string>) => Handle;
3
3
  export default authorizationHandle;
@@ -1,21 +1,22 @@
1
1
  import { redirect } from '@sveltejs/kit';
2
- const authorizationHandle = () => {
2
+ const authorizationHandle = (protectedPaths) => {
3
3
  return async ({ event, resolve }) => {
4
4
  const path = event.url.pathname;
5
5
  if (path.startsWith('/auth/') === false) {
6
- const route = event.route;
7
- if (route.id.includes('/(protect)/')) {
8
- const session = event?.locals?.session;
9
- if (!session) {
10
- const cookieHeader = `lastPage=${event.url.toString()}; HttpOnly; Secure; SameSite=Lax; Max-Age=3600; Path=/`;
11
- return new Response('Login user', {
12
- status: 303,
13
- headers: {
14
- location: '/auth/validate',
15
- 'set-cookie': cookieHeader,
16
- referrer: event.url.toString()
17
- }
18
- });
6
+ for (let protectedPath of protectedPaths) {
7
+ if (path.match(protectedPath)) {
8
+ const session = event?.locals?.session;
9
+ if (!session) {
10
+ const cookieHeader = `retrunToAddress=${event.url.toString()}; HttpOnly; Secure; SameSite=Lax; Max-Age=3600; Path=/`;
11
+ return new Response('Login user', {
12
+ status: 303,
13
+ headers: {
14
+ location: '/auth/validate',
15
+ 'set-cookie': cookieHeader,
16
+ referrer: event.url.toString()
17
+ }
18
+ });
19
+ }
19
20
  }
20
21
  }
21
22
  }
@@ -3,6 +3,5 @@ export declare const machineAuthenticationProvider: (scope?: string, redirectPat
3
3
  getAuthIdentity: (domain: string) => Promise<any>;
4
4
  getValidation: (event: any) => Promise<Token>;
5
5
  getUser: (token: Token) => Promise<any>;
6
- logout: (token: Token) => Promise<void>;
7
6
  redirectPath: string;
8
7
  };
@@ -3,19 +3,7 @@ const authStateCookieName = 'auth_state';
3
3
  const stateIdGenerator = () => crypto.randomUUID();
4
4
  const getKeycloakIdentity = async (issuer, client_id, scope, redirectUrl) => {
5
5
  const state = stateIdGenerator();
6
- const cookieHeader = `${authStateCookieName}=${state}; HttpOnly; Secure; SameSite=Lax; Max-Age=3600; Path=/`;
7
- // const code_challenge = await o.calculatePKCECodeChallenge(state);
8
- // const authorizationUrlSearchParams = new URLSearchParams({
9
- // client_id: client_id,
10
- // redirect_uri: redirectUrl,
11
- // response_type: 'code',
12
- // state,
13
- // scope,
14
- // code_challenge
15
- // });
16
- // const authorizationUrl = `${issuer}/protocol/openid-connect/auth?${authorizationUrlSearchParams}`;
17
6
  const headers = new Headers();
18
- // headers.append('Set-Cookie', cookieHeader);
19
7
  headers.append('Location', '/auth/validate');
20
8
  return headers;
21
9
  };
@@ -63,23 +51,6 @@ const getUser = async (issuer, token) => {
63
51
  });
64
52
  }
65
53
  };
66
- const logout = async (issuer, clientId, token) => {
67
- const response = await fetch(`${issuer}/protocol/openid-connect/logout`, {
68
- method: "POST",
69
- body: new URLSearchParams({
70
- client_id: clientId,
71
- access_token: token.access_token,
72
- }),
73
- headers: {
74
- "Content-Type": "application/x-www-form-urlencoded",
75
- Accept: "application/json"
76
- }
77
- });
78
- if (!response.ok) {
79
- console.log('Response was NOT okay');
80
- throw new Error('Token not validated.');
81
- }
82
- };
83
54
  export const machineAuthenticationProvider = (scope = '', redirectPath = '/') => {
84
55
  const extendedScope = `openid profile offline_access ${scope}`;
85
56
  const redirectUrl = "/auth/validate";
@@ -97,9 +68,6 @@ export const machineAuthenticationProvider = (scope = '', redirectPath = '/') =>
97
68
  const user = await getUser(AUTH_KEYCLOAK_ISSUER, token);
98
69
  return user;
99
70
  },
100
- logout: async (token) => {
101
- await logout(AUTH_KEYCLOAK_ISSUER, AUTH_KEYCLOAK_ID, token);
102
- },
103
71
  redirectPath
104
72
  };
105
73
  };
@@ -1,6 +1,7 @@
1
1
  import type { ISession, Sid } from './types.js';
2
2
  declare function clean(): Promise<void>;
3
3
  declare function createSession(session: ISession, maxAge: number): Promise<string>;
4
+ declare function updateSession(sid: string, session: ISession, maxAge: number): Promise<void>;
4
5
  declare function getSession(sid: Sid): Promise<any>;
5
6
  declare function deleteSession(sid: string): Promise<void>;
6
7
  export declare const redisSessionProvider: {
@@ -8,5 +9,6 @@ export declare const redisSessionProvider: {
8
9
  createSession: typeof createSession;
9
10
  getSession: typeof getSession;
10
11
  deleteSession: typeof deleteSession;
12
+ updateSession: typeof updateSession;
11
13
  };
12
14
  export {};
@@ -12,11 +12,19 @@ async function createSession(session, maxAge) {
12
12
  const sid = getSid();
13
13
  const sessionObject = {
14
14
  data: session,
15
- invalidAt: Date.now() + maxAge
15
+ invalidAt: Date.now() + maxAge + 3600
16
16
  };
17
17
  await redis.set(sid, JSON.stringify(sessionObject), "EX", maxAge);
18
18
  return sid;
19
19
  }
20
+ async function updateSession(sid, session, maxAge) {
21
+ await redis.del(sid);
22
+ const sessionObject = {
23
+ data: session,
24
+ invalidAt: Date.now() + maxAge + 3600
25
+ };
26
+ await redis.set(sid, JSON.stringify(sessionObject), "EX", maxAge);
27
+ }
20
28
  async function getSession(sid) {
21
29
  const savedSession = await redis.get(sid);
22
30
  if (savedSession) {
@@ -33,4 +41,5 @@ export const redisSessionProvider = {
33
41
  createSession: createSession,
34
42
  getSession: getSession,
35
43
  deleteSession: deleteSession,
44
+ updateSession: updateSession
36
45
  };
@@ -1,5 +1,5 @@
1
1
  import {} from '@sveltejs/kit';
2
- import { AUTH_KEYCLOAK_ID, AUTH_KEYCLOAK_ISSUER } from '$env/static/private';
2
+ import { AUTH_KEYCLOAK_ID, AUTH_KEYCLOAK_SECRET, AUTH_KEYCLOAK_ISSUER } from '$env/static/private';
3
3
  const authSessionCookieName = `auth_session`;
4
4
  function isTokenExpired(token) {
5
5
  const base64Url = token.split(".")[1];
@@ -14,12 +14,13 @@ function isTokenExpired(token) {
14
14
  const expired = Date.now() >= exp * 1000;
15
15
  return expired;
16
16
  }
17
- async function refreshToken(clientId, refresh_token) {
17
+ async function refreshToken(clientId, clientSecret, refresh_token) {
18
18
  const response = await fetch(`${AUTH_KEYCLOAK_ISSUER}/protocol/openid-connect/token`, {
19
19
  method: "POST",
20
20
  body: new URLSearchParams({
21
21
  grant_type: "refresh_token",
22
22
  client_id: clientId,
23
+ client_secret: clientSecret,
23
24
  refresh_token: refresh_token,
24
25
  }),
25
26
  headers: {
@@ -33,19 +34,15 @@ async function refreshToken(clientId, refresh_token) {
33
34
  export const tokenRefreshHandle = (sessionProvider) => {
34
35
  return async ({ event, resolve }) => {
35
36
  const locals = event.locals;
36
- try {
37
- if (locals?.token?.refresh_token) {
38
- const isExpired = isTokenExpired(locals.token.access_token);
39
- if (isExpired) {
40
- const newToken = await refreshToken(AUTH_KEYCLOAK_ID, locals.token.refresh_token);
41
- locals.token = newToken;
42
- const sid = event.cookies.get(authSessionCookieName);
43
- sessionProvider.updateSession(sid, locals, newToken.expires_in);
44
- }
37
+ if (locals?.token?.refresh_token) {
38
+ const isExpired = isTokenExpired(locals.token.access_token);
39
+ if (isExpired) {
40
+ const newToken = await refreshToken(AUTH_KEYCLOAK_ID, AUTH_KEYCLOAK_SECRET, locals.token.refresh_token);
41
+ locals.token = newToken;
42
+ const sid = event.cookies.get(authSessionCookieName);
43
+ sessionProvider.updateSession(sid, locals, newToken.expires_in);
45
44
  }
46
45
  }
47
- catch {
48
- }
49
46
  return await resolve(event);
50
47
  };
51
48
  };
@@ -22,11 +22,11 @@ export interface IProvider {
22
22
  getAuthIdentity(domain: string): Promise<any>;
23
23
  getValidation(event: any): Promise<Token>;
24
24
  getUser(token: Token): any;
25
- logout(token: Token): Promise<any>;
26
25
  }
27
26
  export interface ISessionStorage {
28
27
  clean(): Promise<void>;
29
28
  createSession(session: ISession, maxAge: number): Promise<Sid>;
30
29
  getSession(sid: Sid): Promise<ISession | undefined>;
31
30
  deleteSession(sid: Sid): Promise<void>;
31
+ updateSession(sid: Sid, session: ISession, maxAge: number): Promise<void>;
32
32
  }
@@ -3,6 +3,5 @@ export declare const userAuthenticationProvider: (scope?: string, redirectPath?:
3
3
  getAuthIdentity: (domain: string) => Promise<any>;
4
4
  getValidation: (event: any) => Promise<Token>;
5
5
  getUser: (token: Token) => Promise<any>;
6
- logout: (token: Token) => Promise<void>;
7
6
  redirectPath: string;
8
7
  };
@@ -76,23 +76,6 @@ const getUser = async (issuer, token) => {
76
76
  });
77
77
  }
78
78
  };
79
- const logout = async (issuer, clientId, token) => {
80
- const response = await fetch(`${issuer}/protocol/openid-connect/logout`, {
81
- method: "POST",
82
- body: new URLSearchParams({
83
- client_id: clientId,
84
- access_token: token.access_token,
85
- }),
86
- headers: {
87
- "Content-Type": "application/x-www-form-urlencoded",
88
- Accept: "application/json"
89
- }
90
- });
91
- if (!response.ok) {
92
- console.log('Response was NOT okay');
93
- throw new Error('Token not validated.');
94
- }
95
- };
96
79
  export const userAuthenticationProvider = (scope = '', redirectPath = '/') => {
97
80
  const extendedScope = `openid profile offline_access ${scope}`;
98
81
  const redirectUrl = "/auth/validate";
@@ -110,9 +93,6 @@ export const userAuthenticationProvider = (scope = '', redirectPath = '/') => {
110
93
  const user = await getUser(AUTH_KEYCLOAK_ISSUER, token);
111
94
  return user;
112
95
  },
113
- logout: async (token) => {
114
- await logout(AUTH_KEYCLOAK_ISSUER, AUTH_KEYCLOAK_ID, token);
115
- },
116
96
  redirectPath
117
97
  };
118
98
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@functionalcms/svelte-components",
3
- "version": "2.35.0",
3
+ "version": "2.35.2",
4
4
  "watch": {
5
5
  "build": {
6
6
  "patterns": [
@@ -1,12 +0,0 @@
1
- import type { ISession, Sid } from './types.js';
2
- declare function clean(): Promise<void>;
3
- declare function createSession(session: ISession, maxAge: number): Promise<string>;
4
- declare function getSession(sid: Sid): Promise<ISession | undefined>;
5
- declare function deleteSession(sid: string): Promise<void>;
6
- export declare const inMemorySessionProvider: {
7
- clean: typeof clean;
8
- createSession: typeof createSession;
9
- getSession: typeof getSession;
10
- deleteSession: typeof deleteSession;
11
- };
12
- export {};
@@ -1,46 +0,0 @@
1
- import { getSid } from './sessionIdGenerator.js';
2
- const sessionStore = new Map();
3
- let nextClean = Date.now() + 1000 * 60 * 60; // 1 hour
4
- async function clean() {
5
- const now = Date.now();
6
- for (const [sid, session] of sessionStore) {
7
- if (session.invalidAt < now) {
8
- sessionStore.delete(sid);
9
- }
10
- }
11
- // // TODO: delete session from browser storage
12
- nextClean = Date.now() + 1000 * 60 * 60; // 1 hour
13
- }
14
- if (Date.now() > nextClean) {
15
- //call in setTimeout to not block the server
16
- setTimeout(() => {
17
- clean();
18
- }, 5000);
19
- }
20
- async function createSession(session, maxAge) {
21
- let sid = '';
22
- do {
23
- sid = getSid();
24
- } while (sessionStore.has(sid));
25
- sessionStore.set(sid, {
26
- data: session,
27
- invalidAt: Date.now() + maxAge
28
- });
29
- return sid;
30
- }
31
- async function getSession(sid) {
32
- if (sessionStore.has(sid)) {
33
- const cache = sessionStore.get(sid);
34
- return cache?.data;
35
- }
36
- return undefined;
37
- }
38
- async function deleteSession(sid) {
39
- sessionStore.delete(sid);
40
- }
41
- export const inMemorySessionProvider = {
42
- clean: clean,
43
- createSession: createSession,
44
- getSession: getSession,
45
- deleteSession: deleteSession,
46
- };
@@ -1,14 +0,0 @@
1
- import type { ISession, Sid } from './types.js';
2
- declare function clean(): Promise<void>;
3
- declare function createSession(session: ISession, maxAge: number): Promise<string>;
4
- declare function updateSession(sid: string, session: ISession, maxAge: number): Promise<void>;
5
- declare function getSession(sid: Sid): Promise<any>;
6
- declare function deleteSession(sid: string): Promise<void>;
7
- export declare const redisSessionProvider: {
8
- clean: typeof clean;
9
- createSession: typeof createSession;
10
- getSession: typeof getSession;
11
- deleteSession: typeof deleteSession;
12
- updateSession: typeof updateSession;
13
- };
14
- export {};
@@ -1,45 +0,0 @@
1
- import { getSid } from './sessionIdGenerator.js';
2
- import Redis from "ioredis";
3
- import { CACHE_SECRET } from '$env/static/private';
4
- const url = "functional.redis.cache.windows.net:6380,password=cfENm4qUceDQ2lE8tl5LFLjg4IVx3F4mIAzCaA12xtg=,ssl=True,abortConnect=False";
5
- const redis = new Redis(6380, "functional.redis.cache.windows.net", {
6
- password: CACHE_SECRET,
7
- tls: true
8
- });
9
- async function clean() {
10
- }
11
- async function createSession(session, maxAge) {
12
- const sid = getSid();
13
- const sessionObject = {
14
- data: session,
15
- invalidAt: Date.now() + maxAge + 3600
16
- };
17
- await redis.set(sid, JSON.stringify(sessionObject), "EX", maxAge);
18
- return sid;
19
- }
20
- async function updateSession(sid, session, maxAge) {
21
- await redis.del(sid);
22
- const sessionObject = {
23
- data: session,
24
- invalidAt: Date.now() + maxAge + 3600
25
- };
26
- await redis.set(sid, JSON.stringify(sessionObject), "EX", maxAge);
27
- }
28
- async function getSession(sid) {
29
- const savedSession = await redis.get(sid);
30
- if (savedSession) {
31
- const session = JSON.parse(savedSession);
32
- return session.data;
33
- }
34
- return null;
35
- }
36
- async function deleteSession(sid) {
37
- await redis.del(sid);
38
- }
39
- export const redisSessionProvider = {
40
- clean: clean,
41
- createSession: createSession,
42
- getSession: getSession,
43
- deleteSession: deleteSession,
44
- updateSession: updateSession
45
- };
@@ -1,2 +0,0 @@
1
- import type { IProvider } from "./types.js";
2
- export declare const getStandardHandle: (authProvider: IProvider) => import("@sveltejs/kit").Handle;
@@ -1,7 +0,0 @@
1
- import { sequence } from "@sveltejs/kit/hooks";
2
- import errorHandler from "./errorHandle.js";
3
- import { tokenRefreshHandle } from "./tokenRefreshHandle.js";
4
- import authorizationHandle from "./authorizationHandle.js";
5
- import { authenticationHandle } from "./authenticationHandle.js";
6
- import { redisSessionProvider } from "./redisSessionProvider.js";
7
- export const getStandardHandle = (authProvider) => sequence(errorHandler, authenticationHandle(authProvider, redisSessionProvider), tokenRefreshHandle(redisSessionProvider), authorizationHandle(['/.+']));