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

OAuth draft for browser based apps and Access Tokens in JavaScript #514

Open
obfuscoder opened this issue Nov 16, 2023 · 13 comments
Open

OAuth draft for browser based apps and Access Tokens in JavaScript #514

obfuscoder opened this issue Nov 16, 2023 · 13 comments

Comments

@obfuscoder
Copy link
Contributor

The recent OAuth draft for browser based apps (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps) focuses on the threat of malicious JavaScript. There is always the risk of XSS or injected code and the draft seemingly argues towards not having Access Tokens (AT) in the JS client, but rather have the BFF take care of the AT and bind the JS client with a session cookie. As far as I can see that, the discussed JS attack threats also apply to FedCM. At its current state, FedCM only works with a JS client. There cannot be a BFF or any other backend in between client app and IdP to avoid having the Tokens in the JS part. Are there any plans to have a flow which allows the client to initiate FedCM, but essentially the Tokens are transfered from IdP to a backend-system of the RP?

@npm1
Copy link
Collaborator

npm1 commented Nov 16, 2023

I don't follow why there cannot be any other backend between the client app and the IdP. If the RP wanted to create a BFF they could do so, have it be 'the IdP' for the FedCM API, and interact with the actual IdP server-side.

@obfuscoder
Copy link
Contributor Author

Well in this case, neither the client/RP nor the IdP would need to use FedCM, as the BFF and client are usually on the same site and can use first party context. However the login session cookie set at the IdP domain in the browser of the user is not available when doing a B2B communication between BFF and IdP. It would require a redirect request instead of a simple call.

@achimschloss
Copy link
Contributor

For my understanding, the security concerns revolve around that the FedCM API today will always return the opaque token issued by the IDP (as received by the browser from the the id-assertion-endpoint) when resolving the promise to the navigator.credentials.get call. Which makes to token available client side an thus susceptible of malicious JS on the RP side.

@aaronpk
Copy link

aaronpk commented May 17, 2024

A pattern I've implemented is to have the IDP return an authorization code in the FedCM response, and the JavaScript sends that to its backend which completes the OAuth flow so that the access token is only ever on the server, never in the browser.

Once the JavaScript is able to pass arbitrary parameters to the assertion endpoint (#556), we can even add PKCE support for even better security of the flow.

@obfuscoder
Copy link
Contributor Author

@aaronpk That sounds reasonable and it is quite similar to what we came up with.

We don't return an Access Token with the FedCM id_assertion_endpoint, but something (we call itt FedCM token) containing the authorization code which can then be used to obtain Access Token, Refresh Token and Id Token at the Token endpoint of the IdP. The request to the Token endpoint could be done by the JS running iin the browser (with its inherant vulnerability to XSS) or by a BFF which the JS part passes to the BFF. In tthe second case, client credentialls can be used as well as proper Token binding.

I'm looking forward for the arbitrary input paramters to the id assertion endpoint for that PKCE support.

I wonder if we should add this pattern in some BCP (probably too early) or security consideration section in the FedCM spec.

@brockallen
Copy link

@aaronpk and @obfuscoder, I've not looked at details, but I wanted to ask if there was some nonce-like protection in your approaches to validate correlation from the request and response when you are using a back-end/BFF that ultimately issues a cookie in the RP for the user's authentication session?

For example, I was imagining something in the JS before the FedCM flow begins that pings a backend/BFF to initiate the workflow. That response issues some correlation cookie and returns a nonce value. This nonce is then used in the FedCM workflow. Once the JS gets the FedCM response, it would send it to the backend and the backend would need to validate that nonce along with the response (like the code or this FedCM token).

So again, apologies for not having looked into the details yet, but I wanted to ensure there was something like this (much like how nonce is used in OIDC). I guess if PKCE was somehow also worked into this, then it would serve a similar purpose.

Thanks in advance.

@aaronpk
Copy link

aaronpk commented May 17, 2024

Yes, I sent the PKCE code challenge in the FedCM "nonce" field. Once we can pass arbitrary parameters this will get cleaned up.

@obfuscoder
Copy link
Contributor Author

In our implementation we allow the client to specify a nonce and return it in the ID token which the client should validate afterwards. Whether the client generates tthe nonce in the JS client or the BFF can be decided by the client. We do not use the nonce as PKCE, though. The purpose is different, but I can see why @aaronpk used it that way as that is currently the only way to pass any parameter like a required PKCE code challenge to the IdP.

@aaronpk
Copy link

aaronpk commented May 17, 2024

Yep, and I don't use ID tokens so there's no need for the OpenID Connect nonce.

and fwiw I did implement it by having the frontend ping the backend when starting the flow and the backend generates the PKCE code verifier and sends the challenge to the frontend to include in the FedCM call.

@brockallen
Copy link

and fwiw I did implement it by having the frontend ping the backend when starting the flow and the backend generates the PKCE code verifier and sends the challenge to the frontend to include in the FedCM call.

Yes, I see this as the safe approach since a backend can't ever trust what's happening in the JS.

@aaronpk
Copy link

aaronpk commented Jun 25, 2024

Can this issue be closed? I believe we've demonstrated that it is possible to accomplish the original goals in the issue with the current spec, and will be even better with the final resolution of w3c-fedid/custom-requests#2

If you haven't seen it yet, here's my notes on implementing OAuth on top of FedCM, keeping the access token entirely out of the JavaScript layer: https://github.com/aaronpk/oauth-fedcm-profile

@obfuscoder
Copy link
Contributor Author

The new FedCM API definitly enables such a flow. However, my original question was about whether the FedCM spec should at least mention (security considerations) that using only browser-based JS to obtain and use security tokens is prone to XSS attacks.

@npm1
Copy link
Collaborator

npm1 commented Jun 26, 2024

Do you mind taking a stab at adding a "Note: " to the spec? I think you understand the issue better than anyone and can probably write it best. Happy to review and get it merged.

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

5 participants