Skip to content
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

Document how redirectUrl can be used to do session binding if necessary #56

Open
dlongley opened this issue Dec 7, 2023 · 5 comments
Open

Comments

@dlongley
Copy link
Member

dlongley commented Dec 7, 2023

In some scenarios, polling isn't used to obtain completed exchange information, but rather, the RP will not act on an exchange until it is redirected by the user to a particular URL. This URL is returned via redirectUrl in the completed exchange response to the wallet (which is responsible for enabling the user to then navigate in their browser to the URL). Only once the RP is redirected to this URL (note: the redirect URL is kept secret from the wallet until the exchange completes successfully) will the RP get the completed state of the exchange and act accordingly.

This pattern requires the user to navigate away from the page where the exchange started, but offers the benefit of enabling the RP to ensure that when the user visits the redirection page -- that it is the same user (the same "session"). This can be done by having the RP make the redirect URL a capability URL and storing an association between it and the user's current session. For example, the user's browser can store a session cookie (e.g., a cookie value with a session ID) and the RP's backend can store the redirect capability URL in that session information. An RP can check this value against the URL when the user returns to ensure that the user that completed the exchange is the same one that started the exchange, mitigating a variety of phishing threats.

This should also be documented as a useful pattern in the VC API spec.

@dlongley
Copy link
Member Author

dlongley commented Jan 5, 2024

An additional pattern could be for implementations that serve the response to a redirect URL to show a code if a different device is detected (i.e., the user did a cross device flow). The web page can direct the user to enter the code on their own device at the page where the exchange began, also causing binding that way.

In other words there are two flows supported here. The first two steps are the same:

  1. User uses their desktop to start an exchange.
  2. The web server stores a cookie on the desktop browser to be read later if the user's desktop browser navigates to redirectUrl at the end of the exchange.

Then, the next few steps can vary, either:

  1. User completes the exchange using their desktop browser.
  2. User's desktop browser goes to redirectUrl and the web server detects the cookie and considers the exchange to have involved the same user.

OR:

  1. User completes the exchange on their phone's browser.
  2. User's phone browser goes to redirectUrl and the web server detects no cookie and instead renders a short code and instructs for the user to enter it into their original device's browser.
  3. The user switches to their desktop, clicks a "I used another device to complete this flow" button which causes a form to be rendered where the user enters the code into the form to signal to the server that the exchange is complete and involved the same user.

@msporny
Copy link
Member

msporny commented Jan 23, 2024

instead renders a short code and instructs for the user to enter it into their original device's browser.

Wouldn't the desktop just poll in the background and detect when /something/ went to the redirectUrl and can thus conclude that the flow is complete?

@dlongley
Copy link
Member Author

dlongley commented Jan 23, 2024

@msporny,

Wouldn't the desktop just poll in the background and detect when /something/ went to the redirectUrl and can thus conclude that the flow is complete?

First, note that a requirement here is that polling isn't being used to begin with in this scenario. But, more importantly, the purpose of this flow is to ensure that the user that completed the exchange is / was the same user. Polling and allowing the flow to complete if anyone (or "something" as you say) used the redirect URL without reestablishing some binding with the original channel / browser would not provide what's required: to establish the binding between the user that completed the exchange and the original channel in which it was initiated.

@msporny
Copy link
Member

msporny commented Jan 24, 2024

First, note that a requirement here is that polling isn't being used to begin with in this scenario. But, more importantly, the purpose of this flow is to ensure that the user that completed the exchange is / was the same user. Polling and allowing the flow to complete if anyone (or "something" as you say) used the redirect URL without reestablishing some binding with the original channel / browser would not provide what's required: to establish the binding between the user that completed the exchange and the original channel in which it was initiated.

Sure, but I guess my point is, there is no guarantee that the person entering the code is actually the one that completed the flow. An attacker working in conjunction w/ the real holder of the VC can always just pay someone for their code... this is the same issue as relay proxies, which I would imagine /every/ solution that attempts to do channel binding in this way has.

@dlongley
Copy link
Member Author

dlongley commented Jan 24, 2024

Sure, but I guess my point is, there is no guarantee that the person entering the code is actually the one that completed the flow.

To clarify, the aim is not that it's the same person, but that that same user sanctioned the completion of the flow. They could have delegated to / involved another person, but only with their consent.

An attacker working in conjunction w/ the real holder of the VC can always just pay someone for their code... this is the same issue as relay proxies, which I would imagine /every/ solution that attempts to do channel binding in this way has.

Yes, this flow does not prevent collusion (nor does it aim to). It aims to stop an attacker that is working against the user, not an attacker that is working with them.

And, yes, I agree that no "channel binding" scheme will prevent collusion (and it doesn't aim to).

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

No branches or pull requests

2 participants