Skip to content

Prototype silent authentication #992

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft

Conversation

lebaudantoine
Copy link
Contributor

@lebaudantoine lebaudantoine commented May 21, 2025

This contribution is totally draft, and waiting for peer-programming with @AntoLC .
Requested by @virgile-dev, I propose a prototype of the silent login authentication implemented in La Suite Django package.

@virgile-dev
Copy link
Collaborator

Nice thank you @lebaudantoine !
@AntoLC this is a huge win for users, let's get to it when you or @lunika get a bit of bandwith

@lebaudantoine lebaudantoine force-pushed the poc-silent-login branch 5 times, most recently from 0498ae1 to 53796bc Compare May 24, 2025 21:49
@lebaudantoine
Copy link
Contributor Author

current UX (insufficient RAM on my computer are negatively impacting the current UX.)

wip.mov

@lebaudantoine
Copy link
Contributor Author

While reducing the number of requests to the /me endpoint, I discovered a race condition. React Query is designed to execute a single /me query, from my understanding, but there's a race condition occurring between the Auth component and the Language Picker component, which triggers two simultaneous requests.

Stop retry attempts when receiving 401 Unauthorized from /me endpoint since
this clearly indicates authentication status. The original purpose of the /me
call is simply to determine if user is authenticated, and a 401 provides
sufficient information.

Prevents unnecessary network requests caused by React Query's automatic retry
behavior when re-raising exceptions, which was hiding the 401 status. Improves
performance and reduces server load during authentication failures.
Use returnTo capability to pass target URL during authentication, eliminating
redundant renders when returning to app. Work around Next.js router limitations
(can't pass data when replacing URL) by adding temporary target parameter.

Discovered issue: 401 responses on document fetch trigger retry loop instead
of redirecting to login. Will address in subsequent commits.
Remove variable that is no longer referenced in the codebase to improve
code cleanliness and reduce potential confusion.
Reduce unnecessary fetch requests when retrieving documents with permission
or authentication issues. Previous implementation was triggering multiple
document requests despite having sufficient error information from initial
attempt to determine appropriate user redirection.

Additionally, fix issue where resetting the auth cache was triggering redundant
authentication verification requests. The responsibility for checking auth
status should belong to the 401 page component on mount, rather than being
triggered by cache resets during error handling.

Known limitations:
- Not waiting for async  function completion makes code harder to
 maintain
- Added loading spinner as temporary solution to prevent UI flicker
- Future improvement should implement consistent error-based redirects rather
 than rendering error messages directly on document page
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.
Update APIError message that incorrectly mentioned document when
configuration fetching fails.
@lebaudantoine
Copy link
Contributor Author

lebaudantoine commented May 24, 2025

We should add a configuration, I propose IS_SILENT_LOGIN_ENABLED. People self-hosting docs could enable the silent login, if their OIDC provider supports the prompt parameter.

@lebaudantoine
Copy link
Contributor Author

To avoid spamming the user with too many redirections, in my code, the default retry silent login is every hour.

@virgile-dev
Copy link
Collaborator

current UX (insufficient RAM on my computer are negatively impacting the current UX.)
wip.mov

Hey @lebaudantoine thanks for the video.
Ideally if a user is loggued in he should see his documents and not the landing page. Is that something we can acheive with the right callback maybe ?

@lebaudantoine
Copy link
Contributor Author

lebaudantoine commented May 25, 2025

@virgile-dev I've not modified this behavior, it should be still functional. In the video, I'm logged out. The video illustrates that silent login is tried once per 1hour

@@ -38,7 +38,10 @@ export const getConfig = async (): Promise<ConfigResponse> => {
const response = await fetchAPI(`config/`);

if (!response.ok) {
throw new APIError('Failed to get the doc', await errorCauses(response));
throw new APIError(
'Failed to get the configurations',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'Failed to get the configurations',
'Failed to get the configuration',

Comment on lines +27 to +31
attemptSilentLogin(3600);

while (window.location.href === currentLocation) {
await new Promise((resolve) => setTimeout(resolve, 100));
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If attemptSilentLogin fails, it seems to stay blocked in the loop.

Copy link
Collaborator

@AntoLC AntoLC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a problem with the redirection after being login again, maybe I missed something ?

scrnli_MH6SMWOL44sxmh.webm

Actually I can see the test e2e got the problem as well:
image

Comment on lines +470 to +471
OIDC_AUTHENTICATE_CLASS = "lasuite.oidc_login.views.OIDCAuthenticationRequestView"
OIDC_CALLBACK_CLASS = "lasuite.oidc_login.views.OIDCAuthenticationCallbackView"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add them in /docs/env.md.

Comment on lines +556 to +558
OIDC_REDIRECT_FIELD_NAME = values.Value(
"returnTo", environ_name="OIDC_REDIRECT_FIELD_NAME", environ_prefix=None
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, should be added in /docs/env.md.


if (!response.ok && response.status == 401 && canAttemptSilentLogin()) {
const currentLocation = window.location.href;
attemptSilentLogin(3600);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be in const in the conf I think, for everybody to know that it is something that we could configure, wdyt?

export const gotoLogin = (returnTo = '/', isSilent = false) => {
const authenticateUrl =
LOGIN_URL +
`?silent=${encodeURIComponent(isSilent)}&returnTo=${window.location.origin + returnTo}`;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The redirection does not seems to work, returnTo seems to be set though.

@lunika lunika self-requested a review June 5, 2025 07:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants