citizenfx / fivem

The source code for the Cfx.re modification frameworks, such as FiveM, RedM and LibertyM, as well as FXServer.
https://cfx.re/
3.57k stars 2.11k forks source link

Issue with Content Security Policy on forums #2303

Open JLFSL opened 11 months ago

JLFSL commented 11 months ago

What happened?

I have a webproject created for my community. They can login using the Discourse user API with their FiveM credentials. This project is necessary for an in-game MDT and thus me wanting to show it in-game.

Where it goes wrong is when I try to use the same website using NUI, both directly referencing the URL in the fxmanifest and an attempt to use an iframe unfortunately don't work.

As soon as the request is made to https://forum.cfx.re the following error appears in the NUI DevTools: Refused to frame 'https://forum.cfx.re/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self'".

I'm certain that this policy is necessary to prevent any attempts of malicious activity, but I'm really curious if there is a better way of handling this? I know for a fact that it works with txAdmin for example, but unfortunately I haven't found what I need to accomplish my wished result.

Expected result

The user would've been able to authenticate with their cfx account and be redirected back to the website.

Reproduction steps

Use NUI to show a page to challenge the Discourse user API at https://forum.cfx.re/user-api-key/new with the right parameters.

Importancy

Slight inconvenience

Area(s)

FiveM

Specific version(s)

CFX Discourse Forum

Additional information

My authentication is almost the same as the one from https://github.com/citizenfx/fivem/tree/master/ext/webadmin with some slight changes to fix and prevent issues.

matthias18771 commented 11 months ago

Instead of using external authentication, you could just use the fivem: identifier which exists when a user logged into his Cfx.re Account in the client

JLFSL commented 11 months ago

Instead of using external authentication, you could just use the fivem: identifier which exists when a user logged into his Cfx.re Account in the client

Good point, definitely worth the attempt. But couldn't someone then spoof their identifier?

Zydson commented 11 months ago

Instead of using external authentication, you could just use the fivem: identifier which exists when a user logged into his Cfx.re Account in the client

Good point, definitely worth the attempt. But couldn't someone then spoof their identifier?

Why someone would do it? Also I dont see what do you want to do, how do you want to identify user by api-key. Since you can only create new key (its encrypted with node-forge, and only way to decrypt it is knowing what the priv and pub key was, its pretty easy if you know how to do it), it means that there is no static id that user can be identified with. The best way to do it is fivem identifier.

JLFSL commented 11 months ago

I have added an additional authentication method for in-game players, so that has resolved the issue on my end. It would still be great to have a way to authenticate players with their CFX.re account in an iframe. If there's no plans or point of it happening in the near future then this issue can be closed.

TheIndra55 commented 11 months ago

Good point, definitely worth the attempt. But couldn't someone then spoof their identifier?

Identifiers can't be spoofed, they come from the Cfx.re services.

Tynopia commented 11 months ago

Instead of using external authentication, you could just use the fivem: identifier which exists when a user logged into his Cfx.re Account in the client

Sure, but the data retrievable from the public API endpoint of Discourse provides only limited information about the user. For the user, it is harder to log in with their CFX.re account in an NUI because they must enter all credentials anew (The NUI has no access to data like a Google account, as the browser does). You can create a REST with Express directly in a resource. As an example, when a user wants to log in, you can open a new browser tab with the following code. You can create a URL inside the resource and forward the player to that. After logging in, the user should be redirected back to the HTTP service of the resource with the token. As the resource is written inside the fivem process, you can use natives after the login.

JLFSL commented 11 months ago

Instead of using external authentication, you could just use the fivem: identifier which exists when a user logged into his Cfx.re Account in the client

Sure, but the data retrievable from the public API endpoint of Discourse provides only limited information about the user. For the user, it is harder to log in with their CFX.re account in an NUI because they must enter all credentials anew (The NUI has no access to data like a Google account, as the browser does). You can create a REST with Express directly in a resource. As an example, when a user wants to log in, you can open a new browser tab with the following code. You can create a URL inside the resource and forward the player to that. After logging in, the user should be redirected back to the HTTP service of the resource with the token. As the resource is written inside the fivem process, you can use natives after the login.

Very clever idea and had no idea this would work with NUI. I'll attempt an implementation of this with the given information, thank you.