Skip to content

Commit 376e054

Browse files
ZsailerGitHub Enterprise
authored and
GitHub Enterprise
committed
Address inaccurate calculation of session expiration time (jupyter-server#408)
* fix bug to compute login time correctly * Bump to 0.21.2 * address code review
1 parent 6309798 commit 376e054

File tree

6 files changed

+54
-29
lines changed

6 files changed

+54
-29
lines changed
+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.21.1" # pragma: no cover
1+
__version__ = "0.21.2" # pragma: no cover

data_studio_jupyter_extensions/auth/login.py

+11-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import time
21
import uuid
32

43
import tornado
@@ -52,22 +51,19 @@ def post(self):
5251
self, self.datastudio_secure_cookie_name.lower(), data_studio_jwt
5352
)
5453
cookie_options = self.settings.get("cookie_options", {})
55-
cookie_expiry_days = cookie_options["expires_days"]
5654
if hasattr(self.authenticator, "get_expiration"):
57-
exp = self.authenticator.get_expiration(data_studio_jwt)
58-
exp_sec = exp - time.time()
59-
cookie_expiry_days = exp_sec / 60 / 60 / 24
55+
# Expiration date from epoch (converted from seconds to milliseconds)
56+
exp = self.authenticator.get_expiration(data_studio_jwt) * 1000
6057

61-
# This sets an insecure cookie. This is required to track if session expired through javascript.
62-
# No secure information should be set
63-
self.set_cookie(
64-
self.datastudio_cookie_name,
65-
str(cookie_expiry_days),
66-
domain=self.request.host_name,
67-
expires_days=cookie_expiry_days,
68-
httponly=False,
69-
path=self.base_url,
70-
)
58+
# This sets an insecure cookie. This is required to track if session expired through javascript.
59+
# No secure information should be set
60+
self.set_cookie(
61+
self.datastudio_cookie_name,
62+
str(exp),
63+
domain=self.request.host_name,
64+
httponly=False,
65+
path=self.base_url,
66+
)
7167
# Configure the notebook service to use the JWT.
7268
if not self.nbservice_client.local_mode:
7369
self.nbservice_client.request_token = data_studio_jwt

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ testpaths = [
2323
]
2424

2525
[tool.tbump.version]
26-
current = "0.21.1"
26+
current = "0.21.2"
2727
regex = '''
2828
(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)
2929
((?P<channel>a|b|rc|.dev)(?P<release>\d+))?

src/sessionexp.tsx

+39-10
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
JupyterFrontEndPlugin
66
} from '@jupyterlab/application';
77

8-
import { showDialog } from '@jupyterlab/apputils';
8+
import { showDialog, Dialog } from '@jupyterlab/apputils';
99

1010
import { DocumentWidget } from '@jupyterlab/docregistry';
1111

@@ -17,7 +17,16 @@ import { PageConfig, URLExt } from '@jupyterlab/coreutils';
1717
* A session expiration body
1818
*/
1919
export const SessionExpBody = () => {
20-
return <>{'Session is expiring, click OK to refresh login'}</>;
20+
return (
21+
<div>
22+
<p>
23+
Your session is about to expire. We saved your notebooks, so your work
24+
won't be lost.
25+
</p>
26+
<br></br>
27+
<p>Please re-login to continue using Data Studio Notebooks.</p>
28+
</div>
29+
);
2130
};
2231

2332
function readCookie(name: string) {
@@ -56,6 +65,7 @@ export const SessionExpPlugin: JupyterFrontEndPlugin<void> = {
5665

5766
// Get the expiration from the login cookie.
5867
let obj = readCookie(loginCookie);
68+
5969
let expires: number;
6070
if (!obj) {
6171
console.log(`Login cookie ${loginCookie} not found`);
@@ -64,13 +74,26 @@ export const SessionExpPlugin: JupyterFrontEndPlugin<void> = {
6474
expires = parseFloat(obj);
6575
}
6676

67-
// Set the callback time to "sessionWarningMinutes" before expiration, all times are in msec.
68-
let callbackTime =
69-
expires * 24 * 60 * 60 * 1000 - sessionWarningMinutes * 60 * 1000;
77+
// Time since Epoch (in milliseconds).
78+
let currentTime = Date.now();
79+
let secondsUntilExpiration = expires - currentTime;
80+
let twentyMinutesAsMilliseconds = sessionWarningMinutes * 60 * 1000;
81+
let reloginTimeout = secondsUntilExpiration - twentyMinutesAsMilliseconds;
82+
let reloginMinutes = reloginTimeout / 1000 / 60;
83+
let reloginSeconds = ((reloginTimeout / 1000 / 60) % 1) * 60;
84+
85+
// Write a human-readable statement about the expiration time to the console.
86+
console.log(
87+
'This Data Studio Notebooks Session expires in: ' +
88+
Math.trunc(reloginMinutes) +
89+
' minutes and ' +
90+
Math.round(reloginSeconds) +
91+
' seconds'
92+
);
7093

71-
callbackTime = Math.max(callbackTime, 1000);
94+
reloginTimeout = Math.max(reloginTimeout, 1000);
7295
if (PageConfig.getOption('sessionWarningOverride') === 'true') {
73-
callbackTime = 0;
96+
reloginTimeout = 0;
7497
}
7598

7699
setTimeout(async () => {
@@ -87,8 +110,14 @@ export const SessionExpPlugin: JupyterFrontEndPlugin<void> = {
87110

88111
// Prompt the user to login.
89112
const result = await showDialog({
90-
title: 'Session Expiring',
91-
body: SessionExpBody()
113+
title: 'Session is expiring.',
114+
body: SessionExpBody(),
115+
buttons: [
116+
Dialog.okButton({
117+
label: 'Re-login',
118+
displayType: 'default'
119+
})
120+
]
92121
});
93122
if (!result.button.accept) {
94123
return;
@@ -99,6 +128,6 @@ export const SessionExpPlugin: JupyterFrontEndPlugin<void> = {
99128
await fetch(URLExt.join(baseUrl, 'logout'));
100129
const url = URLExt.join(baseUrl, 'login');
101130
window.location.replace(url);
102-
}, callbackTime);
131+
}, reloginTimeout);
103132
}
104133
};

src/status.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { ISessionContext, ReactWidget } from '@jupyterlab/apputils';
3131
import { EventListener } from './eventlistener';
3232

3333
// This is managed by tbump config in pyproject.toml
34-
const VERSION = '0.21.1';
34+
const VERSION = '0.21.2';
3535

3636
// Define the error states
3737
// https://github.pie.apple.com/pie-data-studio/notebook-service/blob/761d63604966db5918d2e491c0f89cce454b7f67/app/com/apple/datastudio/model/ResourceState.scala#L20

version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.21.1
1+
0.21.2

0 commit comments

Comments
 (0)