Skip to content

Make login flow v2 more phishing proof #26944

Open

Description

@LukasReschke

Ref #26943

The problem

Login Flow v2 has the same weakness that OAuth "device code" phishing campaigns exploit. An attacker starts a login flow and sends the victim the link. The victim logs in and clicks "Grant access", and the attacker receives an app password.

What exists today

The grant page (core/src/views/LoginFlowGrant.vue) shows only a client name, which the attacker controls because it comes from the User-Agent, plus a generic warning.

TODO

  • Threat modelling: what an attacker can control in the flow, and what the user can actually check.
  • Countermeasures, for example:
    • showing where the flow was started (IP and user agent?) next to the user's current browser, and warning when they differ
    • number matching between the client and the browser, as an opt-in protocol extension that stays backward compatible
  • Building it in PHP (the core controllers) and Vue/TypeScript, with tests.

Activity

  1. added
    0. Needs triagePending check for reproducibility or if it fits our roadmap
    on May 20, 2021
  2. added
    1. to developAccepted and waiting to be taken care of
    and removed
    0. Needs triagePending check for reproducibility or if it fits our roadmap
    on Jul 6, 2021
  3. jospoortvliet commented on Jan 6, 2026

    @jospoortvliet
    Member

    2 things done, anything else planned?

  4. moved this from To triage to Triaged in 🧑‍🤝‍🧑 Community triageon Oct 29, 2026
  5. fput commented on Nov 3, 2026

    @fput

    I did some threat modelling to better understand the phishing risks in the current login flow v2:

    Assumptions and attacker capabilites:

    Assuming a standard Nextcloud installation, where the attacker can reach the Nextcloud server and can send the user a link. The attacker has not compromised Nextcloud, TLS, the browser, the Nextcloud client, or the user's device.

    The attacker can do the following during the login flow:

    • Start a request (unauthenticated POST /index.php/login/v2)
    • Change the displayed client name (User-Agent). The attacker could impersonate an official client
    • Obtain the login URL and poll token for their request. The attacker could give the login URL to the victim while polling the server for the app password
    • Control the link delivery and presentation, by setting up a a convincing phishing website or a chat message to manipulate the victim into clicking the link and granting access. The attacker could frame this as an expected setup/administration/support task
    • Control the timing when to create and present the request. The attacker could present it when the victim expects to connect a device or application

    I see two kinds of phishing attacks:

    • Basic phishing attack where the attacker supplies convincing framing to trick the user into approving a malicious login request.
    • Timed phishing attack where the attacker times the attack such that it happens when the user intends to setup up a new device or client. The attacker can choose the same user agent, then the victim cannot differentiate these requests in the current login flow.

    The main vulnerability is that in the current design, the user is responsible for detecting phishing attacks, by verifying the login request.

    There are several problems in the current design:

    1. The current design relies exclusively on the user to detect phishing attacks. But many users are vulnerable to social engineering and phishing. Also, rushing users will not read warnings and instead approve malicious login requests.
    2. The current design does not provide meaningful context for the user to make an informed decision whether to accept the request. It only shows the attacker-controlled label.
    3. Even for legitimate requests, the user agent is confusing and difficult to verify. For example, it's not obvious that this is the official Nextcloud Desktop client: Mozilla/5.0 (Macintosh) mirall/35.0.1 (Nextcloud, macos-24.6.0 ClientArchitecture: arm64 OsArchitecture: arm64). It starts with "Mozilla" for technical reasons, but users will not understand this and will likely get used to seemingly invalid labels on these requests.
    4. The user experience is cumbersome as users currently see two similar approval screens back to back.
    5. There is no explicit option do decline a request, nudging users to accept malicious requests.

    I have some ideas to properly mitigate these issues, but doing so requires changing the login protocol and thus requires modifying the clients.

    For now, I recommend addressing problems 2, 4, and 5, which can be done entirely on the server without changing the clients. I have implemented this in PR #66223 by redesigning the UI to make the approval decision more explicit and providing better context to allow users to make more informed decisions. I also added verification that the client and browser IP matches and display a warning if it differs.

    This is how my proposed redesign looks like:

    Redesign
  6. fput commented on Nov 3, 2026

    @fput

    I can think of further countermeasures, but they require changes to the protocol and thus also change the existing clients. So I did not implement this for now. Here are some ideas, though, depending on whether we need to only support same-device use cases or also cross-device use cases.

    Same-device (i.e., when the new client runs on the same device as the browser/existing session that approves the new client, e.g. the desktop or mobile Nextcloud clients): This is easier to secure, e.g., using a local return channel as in RFC 8252. Desktop clients would open a desktop browser. Mobile clients would open a mobile browser. Both Android and iOS support local return channels. The browser redirects using some local-only scheme (loopback redirect, custom URI, verified app link), which prevents remote phishing attackers from accessing the login secret.

    Cross-device (i.e., when the new client runs on a different device as the browser/existing session that approves the new client): This is much more complex. RFC 10027 provides some recommendations. Essentially, we need some other way to establish proximity between both devices if we want to automatically detect a remote phishing attacker. E.g., FIDO2 does this using BLE to establish proximity, but this requires two client devices with BLE support.

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions