Skip to content

Commit 53796bc

Browse files
committed
🚧(auth) implement first draft of silent login with prompt=None
Add initial naive implementation of silent login functionality using prompt=None parameter to request OIDC provider to skip login screen and return proper HTTP error response instead.
1 parent 9344e00 commit 53796bc

File tree

4 files changed

+54
-3
lines changed

4 files changed

+54
-3
lines changed

src/backend/impress/settings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,8 @@ class Base(Configuration):
467467
)
468468

469469
# OIDC - Authorization Code Flow
470+
OIDC_AUTHENTICATE_CLASS = "lasuite.oidc_login.views.OIDCAuthenticationRequestView"
471+
OIDC_CALLBACK_CLASS = "lasuite.oidc_login.views.OIDCAuthenticationCallbackView"
470472
OIDC_CREATE_USER = values.BooleanValue(
471473
default=True,
472474
environ_name="OIDC_CREATE_USER",

src/frontend/apps/impress/src/features/auth/api/useAuthQuery.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query';
22

33
import { APIError, errorCauses, fetchAPI } from '@/api';
44
import { DEFAULT_QUERY_RETRY } from '@/core';
5+
import {
6+
attemptSilentLogin,
7+
canAttemptSilentLogin,
8+
} from '@/features/auth/silentLogin';
59

610
import { User } from './types';
711

@@ -18,6 +22,15 @@ import { User } from './types';
1822
export const getMe = async (): Promise<User> => {
1923
const response = await fetchAPI(`users/me/`);
2024

25+
if (!response.ok && response.status == 401 && canAttemptSilentLogin()) {
26+
const currentLocation = window.location.href;
27+
attemptSilentLogin(30);
28+
29+
while (window.location.href === currentLocation) {
30+
await new Promise((resolve) => setTimeout(resolve, 100));
31+
}
32+
}
33+
2134
if (!response.ok) {
2235
throw new APIError(
2336
`Couldn't fetch user data: ${response.statusText}`,
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { gotoLogin } from '@/features/auth';
2+
3+
const SILENT_LOGIN_RETRY_KEY = 'silent-login-retry';
4+
5+
const isRetryAllowed = () => {
6+
const lastRetryDate = localStorage.getItem(SILENT_LOGIN_RETRY_KEY);
7+
if (!lastRetryDate) {
8+
return true;
9+
}
10+
const now = new Date();
11+
return now.getTime() > Number(lastRetryDate);
12+
};
13+
14+
const setNextRetryTime = (retryIntervalInSeconds: number) => {
15+
const now = new Date();
16+
const nextRetryTime = now.getTime() + retryIntervalInSeconds * 1000;
17+
localStorage.setItem(SILENT_LOGIN_RETRY_KEY, String(nextRetryTime));
18+
};
19+
20+
const initiateSilentLogin = () => {
21+
const currentPath = window.location.pathname;
22+
gotoLogin(currentPath, true);
23+
};
24+
25+
export const canAttemptSilentLogin = () => {
26+
return isRetryAllowed();
27+
};
28+
29+
export const attemptSilentLogin = (retryIntervalInSeconds: number) => {
30+
if (!isRetryAllowed()) {
31+
return;
32+
}
33+
setNextRetryTime(retryIntervalInSeconds);
34+
initiateSilentLogin();
35+
};

src/frontend/apps/impress/src/features/auth/utils.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { backendUrl } from '@/api';
21
import { terminateCrispSession } from '@/services/Crisp';
32

43
import { LOGIN_URL, LOGOUT_URL } from './conf';
54

6-
export const gotoLogin = (returnTo = '/') => {
7-
const authenticateUrl = LOGIN_URL + `?returnTo=${backendUrl() + returnTo}`;
5+
export const gotoLogin = (returnTo = '/', isSilent = false) => {
6+
const authenticateUrl =
7+
LOGIN_URL +
8+
`?silent=${encodeURIComponent(isSilent)}&returnTo=${window.location.origin + returnTo}`;
89
window.location.replace(authenticateUrl);
910
};
1011

0 commit comments

Comments
 (0)