Skip to content

Commit de8c4bb

Browse files
committed
Merge branch 'hotfix/1.4.5'
2 parents 5d05d54 + 93732f9 commit de8c4bb

File tree

6 files changed

+58
-20
lines changed

6 files changed

+58
-20
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.4.5](https://github.com/cryptomator/hub/compare/1.4.4...1.4.5)
9+
10+
### Fixed
11+
12+
- Fix Session Expiration Not Enforced in Cryptomator Hub Web Client (GHSA-69fp-wc9g-5778)
13+
814
## [1.4.4](https://github.com/cryptomator/hub/compare/1.4.3...1.4.4)
915

1016
### Added

backend/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>org.cryptomator</groupId>
66
<artifactId>hub-backend</artifactId>
7-
<version>1.4.4</version>
7+
<version>1.4.5</version>
88

99
<properties>
1010
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

frontend/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"type": "module",
33
"name": "cryptomator-hub",
4-
"version": "1.4.4",
4+
"version": "1.4.5",
55
"description": "Web-Frontend for Cryptomator Hub",
66
"author": "Skymatic GmbH",
77
"license": "AGPL-3.0-or-later",

frontend/src/common/auth.ts

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Keycloak from 'keycloak-js';
2+
import { buildRedirectSyncMeUri } from '../router';
23
import config, { ConfigDto } from './config';
34

45
class Auth {
@@ -10,14 +11,19 @@ class Auth {
1011
realm: cfg.keycloakRealm,
1112
clientId: cfg.keycloakClientIdHub
1213
});
14+
15+
const auth = new Auth(keycloak);
16+
1317
keycloak.onTokenExpired = () => {
14-
keycloak.updateToken(30);
15-
}; // TODO: show notification with .catch(() => notify-user-somehow);
18+
auth.refreshToken(30);
19+
};
20+
1621
await keycloak.init({
1722
checkLoginIframe: false,
1823
pkceMethod: 'S256',
1924
});
20-
return new Auth(keycloak);
25+
26+
return auth;
2127
}
2228

2329
private constructor(keycloak: Keycloak) {
@@ -29,25 +35,42 @@ class Auth {
2935
}
3036

3137
public async login(redirectUri: string): Promise<void> {
32-
await this.keycloak.login({
33-
redirectUri: (redirectUri)
34-
});
38+
await this.keycloak.login({ redirectUri });
3539
}
3640

3741
public async logout(redirectUri?: string): Promise<void> {
38-
return this.keycloak.logout({
39-
redirectUri: redirectUri
40-
});
42+
await this.keycloak.logout({ redirectUri });
4143
}
4244

4345
public async bearerToken(): Promise<string | undefined> {
44-
await this.keycloak.updateToken(10);
46+
await this.refreshToken(10);
4547
return this.keycloak.token;
4648
}
4749

4850
public hasRole(role: string): boolean {
4951
return this.keycloak.tokenParsed?.realm_access?.roles.includes(role) ?? false;
5052
}
53+
54+
private async refreshToken(minValidity?: number, delay: number = 500): Promise<void> {
55+
if (delay > 16000) { // max wait time of 16 seconds before giving up
56+
console.error('Auth Token refresh failed after maximum retries. Clearing tokens & logging out.');
57+
this.keycloak.clearToken();
58+
return this.logout();
59+
}
60+
try {
61+
await this.keycloak.updateToken(minValidity);
62+
return; // success
63+
} catch (err) {
64+
if (!this.isAuthenticated()) {
65+
const redirectUrl = buildRedirectSyncMeUri();
66+
return this.login(redirectUrl);
67+
} else {
68+
console.warn(`Auth Token refresh failed, retrying in ${delay}ms`, err);
69+
await new Promise(res => setTimeout(res, delay));
70+
return this.refreshToken(minValidity, delay * 2); // exponential backoff
71+
}
72+
}
73+
}
5174
}
5275

5376
// this is a lazy singleton:

frontend/src/router/index.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createRouter, createWebHistory, NavigationGuardWithThis, RouteLocationRaw, RouteRecordRaw } from 'vue-router';
1+
import { createRouter, createWebHistory, NavigationGuardWithThis, RouteLocationNormalized, RouteLocationRaw, RouteRecordRaw } from 'vue-router';
22
import authPromise from '../common/auth';
33
import backend from '../common/backend';
44
import { baseURL } from '../common/config';
@@ -149,11 +149,7 @@ router.beforeEach((to, from, next) => {
149149
if (auth.isAuthenticated()) {
150150
next();
151151
} else {
152-
// secondsSinceEpoch is required for legacy reasons, as caching headers were only introduced in #255
153-
// as result, the redirect URI changes and caching does not break updates anymore
154-
const secondsSinceEpoch = Math.round(new Date().getTime() / 1000);
155-
const redirect: RouteLocationRaw = { query: { ...to.query, 'sync_me': secondsSinceEpoch } };
156-
const redirectUri = `${location.origin}${router.resolve(redirect, to).href}`;
152+
const redirectUri = buildRedirectSyncMeUri(to);
157153
auth.login(redirectUri);
158154
}
159155
});
@@ -205,4 +201,17 @@ router.beforeEach(async (to) => {
205201
}
206202
});
207203

204+
export function buildRedirectSyncMeUri(route?: RouteLocationNormalized): string {
205+
const targetRoute = route ?? router.currentRoute.value;
206+
// secondsSinceEpoch is required for legacy reasons, as caching headers were only introduced in #255
207+
const secondsSinceEpoch = Math.round(Date.now() / 1000);
208+
const redirect: RouteLocationRaw = {
209+
query: {
210+
...targetRoute.query,
211+
sync_me: secondsSinceEpoch,
212+
}
213+
};
214+
return `${location.origin}${router.resolve(redirect, targetRoute).href}`;
215+
}
216+
208217
export default router;

0 commit comments

Comments
 (0)