Skip to content

General: Keep the passkey prompt closed after choosing "Set up later"#13121

Open
az108 wants to merge 1 commit into
developfrom
bugfix/general/passkey-setup-prompt-reappears
Open

General: Keep the passkey prompt closed after choosing "Set up later"#13121
az108 wants to merge 1 commit into
developfrom
bugfix/general/passkey-setup-prompt-reappears

Conversation

@az108

@az108 az108 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Summary

After choosing Set up later on the "Stay Secure with Passkeys" prompt, the prompt reappeared shortly after — e.g. when selecting the AI experience in the profile settings. The setup-passkey modal is a singleton in the app shell (app.component) that opens on every authentication-state emission. Set up later only hid the dialog (visible = false) without recording that the user dismissed it, so the next authentication-state re-emission reopened it. This PR remembers the dismissal for the current session so the prompt no longer re-appears.

Checklist

General

Client

Motivation and Context

Closes #13074.

Being re-prompted to set up a passkey immediately after explicitly declining ("Set up later") is confusing and annoying. The two dismissal actions have distinct intents:

  • Remind Me in 30 Days — persisted across sessions via localStorage (already worked).
  • Set Up Later — dismiss for the current session; it should not re-appear again until the next login/session.

Only the first was actually being honored; Set up later recorded nothing.

Description

  • Added a dismissedForCurrentSession flag to SetupPasskeyModalComponent, set in closeModal() and checked first in openIfNeeded(). Because the modal is a singleton in the app shell, the flag persists across navigation and intercepts any later authentication-state re-emission, so the prompt is not shown again during the session. It is reset naturally on a full page reload / new login (a new component instance).
  • Remind Me in 30 Days (persisted 30-day suppression) is unchanged.
  • Added a Vitest regression test that opens the prompt via an authentication emission, dismisses it via closeModal(), emits the authentication state again, and asserts the prompt stays closed.

Steps for Testing

Prerequisites:

  • 1 User without a passkey configured (passkey feature enabled), fresh browser session (no earliestSetupPasskeyReminderDate in local storage)
  1. Log in as the user — the "Stay Secure with Passkeys" prompt appears.
  2. Click Set Up Later.
  3. Go to Settings → AI Experience and select an option (e.g. No AI).
  4. Confirm the passkey prompt does not reappear.
  5. Reload the page / log in again and confirm the prompt appears again as expected (session-scoped dismissal, not permanent).
  6. Regression: repeat but click Remind Me in 30 Days in step 2; confirm it does not reappear now, nor after a reload (30-day suppression still works).

Screenshots

To be added.

Summary by CodeRabbit

  • Bug Fixes
    • Prevented the passkey setup modal from reopening after a user chooses “Set up later” during the same session.
    • Authentication updates now respect the user’s dismissal, avoiding repeated prompts once the modal has been closed.
    • Added test coverage for this behavior to help ensure it remains fixed.

The setup-passkey prompt is a singleton in the app shell that opens on
every authentication-state emission. "Set up later" only hid it without
recording the dismissal, so a later re-emission (e.g. after changing the
AI experience) reopened it. Remember the dismissal for the current session
and skip reopening.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@az108 az108 requested a review from krusche as a code owner July 5, 2026 08:33
@github-project-automation github-project-automation Bot moved this to Work In Progress in Artemis Development Jul 5, 2026
@github-actions github-actions Bot added client Pull requests that update TypeScript code. (Added Automatically!) course labels Jul 5, 2026
@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The setup-passkey-modal component now tracks a dismissedForCurrentSession flag, set when the modal is closed, which prevents openIfNeeded() from reopening the modal after dismissal despite further authentication-state emissions. A corresponding unit test was added to verify this behavior.

Changes

Passkey Modal Dismissal

Layer / File(s) Summary
Session dismissal flag
src/main/webapp/app/course/overview/setup-passkey-modal/setup-passkey-modal.component.ts
Adds a dismissedForCurrentSession boolean set in closeModal() and checked in openIfNeeded() to prevent the modal from reopening after being dismissed within the session.
Dismissal behavior test
src/main/webapp/app/course/overview/setup-passkey-modal/setup-passkey-modal.component.spec.ts
Adds an rxjs Subject import and a test emitting authentication states before/after closing the modal to confirm it stays closed.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Suggested labels: tests, ready for review

Suggested reviewers: krusche

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: keeping the passkey prompt closed after "Set up later".
Linked Issues check ✅ Passed The change stores a session dismissal and prevents reopenings within the same session, matching issue #13074.
Out of Scope Changes check ✅ Passed The edits stay focused on the passkey modal behavior and its regression test, with no unrelated changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bugfix/general/passkey-setup-prompt-reappears

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/webapp/app/course/overview/setup-passkey-modal/setup-passkey-modal.component.ts`:
- Around line 28-34: The session dismissal flag in
setup-passkey-modal.component.ts is not being cleared when the user logs out, so
a later login in the same SPA session can incorrectly skip the passkey prompt.
Update the logic around dismissedForCurrentSession in SetupPasskeyModalComponent
so it is reset when getAuthenticationState() emits undefined (logout), while
still preserving the current-session dismissal behavior for normal re-emissions
after a login.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c8f310f6-9455-4ff6-bf23-d278c1222870

📥 Commits

Reviewing files that changed from the base of the PR and between 1cc9fac and 84f2ad2.

📒 Files selected for processing (2)
  • src/main/webapp/app/course/overview/setup-passkey-modal/setup-passkey-modal.component.spec.ts
  • src/main/webapp/app/course/overview/setup-passkey-modal/setup-passkey-modal.component.ts

Comment on lines +28 to +34
/**
* Set once the user dismisses the prompt during the current session (e.g. via "Set up later").
* The modal is a singleton in the app shell, so this prevents it from reopening when the
* authentication state re-emits (e.g. after changing the AI experience). Reset on a full reload.
*/
private dismissedForCurrentSession = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Look for logout implementation to check if it triggers a full page reload
rg -n -A10 -B2 'logout\s*\(' src/main/webapp/app/core/auth --type=ts
rg -n 'window.location' src/main/webapp/app/core/auth --type=ts

Repository: ls1intum/Artemis

Length of output: 2563


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== logout usages =='
rg -n -A4 -B4 '\.logout\(\)' src/main/webapp/app --type=ts

echo '== auth state sources =='
rg -n -A6 -B4 'getAuthenticationState\(' src/main/webapp/app --type=ts
rg -n -A6 -B4 'authenticationState|authenticationStateSubject|authState' src/main/webapp/app/core/auth --type=ts

echo '== any reload or location change around logout =='
rg -n -A4 -B4 'window\.location|location\.reload|document\.location|reload\(' src/main/webapp/app --type=ts

Repository: ls1intum/Artemis

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find the concrete logout flow and whether a reload is involved.
rg -n -A8 -B4 'logout\(' src/main/webapp/app --type=ts
rg -n -A6 -B4 'api/core/public/logout|clearCaches\(' src/main/webapp/app --type=ts
rg -n -A6 -B4 'navigate\(|navigateByUrl\(|window\.location|location\.reload|document\.location' src/main/webapp/app --type=ts

Repository: ls1intum/Artemis

Length of output: 50373


🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -a 'account.service.ts|authentication.*service.ts|auth.*service.ts' src/main/webapp/app/core/auth src/main/webapp/app/core -t f

Repository: ls1intum/Artemis

Length of output: 428


Reset dismissedForCurrentSession on logout Logout keeps the SPA mounted, and getAuthenticationState() emits undefined on logout. Without clearing this flag here, a later login in the same session inherits the dismissal and suppresses the passkey prompt.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/webapp/app/course/overview/setup-passkey-modal/setup-passkey-modal.component.ts`
around lines 28 - 34, The session dismissal flag in
setup-passkey-modal.component.ts is not being cleared when the user logs out, so
a later login in the same SPA session can incorrectly skip the passkey prompt.
Update the logic around dismissedForCurrentSession in SetupPasskeyModalComponent
so it is reset when getAuthenticationState() emits undefined (logout), while
still preserving the current-session dismissal behavior for normal re-emissions
after a login.

@github-project-automation github-project-automation Bot moved this from Work In Progress to Ready For Review in Artemis Development Jul 5, 2026
@az108 az108 temporarily deployed to playwright-e2e-tests July 5, 2026 08:40 — with GitHub Actions Inactive
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

End-to-End Test Results

Phase Status Details
Phase 1 (Relevant) ❌ Failed
TestsPassedSkippedFailed ❌️Time ⏱
Phase 1: E2E Test Report14 ran0 passed0 skipped14 failed9m 40s
Phase 2 (Remaining) ⏭ Skipped (no remaining tests)
❌ Failed Tests (Phase 1)
  • Login page tests › Logs in via the UI (2m 28s)
  • Login page tests › Logs in programmatically and logs out via the UI (2m 20s)
  • Login page tests › Displays error messages on wrong password (2m 27s)
  • Login page tests › Fails to access protected resource without login (2m 28s)
  • Login page tests › Verify footer content (24s)
  • Logout tests › Logs out after confirmation of dialog for unsaved changes on exercise mode (1m 42s)
  • Logout tests › Stays logged in after dismissal of dialog for unsaved changes on exercise mode (1m 42s)
  • Check artemis system health › Checks continuous integration server health (13s)
  • Check artemis system health › Checks db health (12s)
  • Check artemis system health › Checks hazelcast health (12s)
  • Check artemis system health › Checks ping health (13s)
  • Check artemis system health › Checks readiness state health (13s)
  • Check artemis system health › Checks websocket broker health (11s)
  • Check artemis system health › Checks websocket connection health (2m 17s)

Flakiness Scores for Failed Tests

Test Flakiness Score Default Branch Failure Rate Combined Failure Rate
e2e/Login.spec.ts#Login page tests › Logs in via the UI 0% 0.6% 0.2%
e2e/Login.spec.ts#Login page tests › Logs in programmatically and logs out via the UI 0% 0.4% 0.2%
e2e/Login.spec.ts#Login page tests › Displays error messages on wrong password 0% 0.4% 0.2%
e2e/Login.spec.ts#Login page tests › Fails to access protected resource without login 68.27160493827161% 1.2% 0.3%
e2e/Login.spec.ts#Login page tests › Verify footer content 0% 0.3% 0.2%
e2e/Logout.spec.ts#Logout tests › Logs out after confirmation of dialog for unsaved changes on exercise mode 68.4045584045584% 1.1% 0.5%
e2e/Logout.spec.ts#Logout tests › Stays logged in after dismissal of dialog for unsaved changes on exercise mode 68.4045584045584% 1.1% 0.5%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks continuous integration server health 0% 0.3% 0.4%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks db health 0% 0.2% 0.4%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks hazelcast health 0% 0.3% 0.4%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks ping health 0% 0.2% 0.4%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks readiness state health 0% 0.3% 0.4%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks websocket broker health 0% 0.2% 0.4%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks websocket connection health 0% 0.3% 0.8%

Test Strategy: Two-phase execution

  • Phase 1: e2e/Login.spec.ts e2e/Logout.spec.ts e2e/SystemHealth.spec.ts
  • Phase 2: e2e/Passkey.spec.ts e2e/PasskeyReminderPersistence.spec.ts e2e/admin/ e2e/atlas/ e2e/course/ e2e/exam/ExamAssessment.spec.ts e2e/exam/ExamChecklists.spec.ts e2e/exam/ExamCreationDeletion.spec.ts e2e/exam/ExamDateVerification.spec.ts e2e/exam/ExamManagement.spec.ts e2e/exam/ExamParticipation.spec.ts e2e/exam/ExamResults.spec.ts e2e/exam/ExamTestRun.spec.ts e2e/exam/test-exam/ e2e/exercise/ExerciseImport.spec.ts e2e/exercise/file-upload/ e2e/exercise/modeling/ e2e/exercise/programming/ e2e/exercise/quiz-exercise/ e2e/exercise/text/ e2e/iris/ e2e/lecture/ e2e/shared/

Overall: ❌ E2E tests failed

🔗 Workflow Run · 📊 Test Report Phase 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

client Pull requests that update TypeScript code. (Added Automatically!) course

Projects

Status: Ready For Review

Development

Successfully merging this pull request may close these issues.

General: Passkey setup prompt reappears when selecting the AI experience after choosing "Set up later"

1 participant