IPC authentication
the concept of 'client secrets' for desktop apps (anything that uses the named pipe) is pretty nonsensical; it's easy to impersonate any of these - if it's absolutely necessary, there are better ways to do it.
For example, Logitech hides the app secret by having an AWS lambda that takes a code, talks to Discord's API, and returns an access token. I could trivially impersonate logitech's app by calling their AWS endpoint. This is not an implementation problem, this architecture is inappropriate for desktop apps.
Suggestions:
(1) ideally remove the whole concept of client secrets from IPC. AUTHORIZE could return a directly usable token
(2) if you absolutely want this for some reason, you could identify the program on the other end of the pipe (e.g. via GetNamedPipeClientProcessId on Windows, getsockopt with SO_PEERCRED on linux, and LOCAL_PEERCRED on macos), and require that it be signed with a public key listed on the developer portal.
(2) doesn't help against actively malicious programs, given that they could interfere with the main discord process instead of using the API
-
It could be made optional - e.g. AUTHORIZE could return both a code and an access_token; in which case, existing clients could continue to work; alternatively, AUTHENTICATE could be modified to accept either a code or an access token.
0 -
> Not to mention that 99.99% of token related attacks are either the user extracting the token and leaking it or giving away login credentials.
The current system doesn't help:- if a client secret is in a desktop app, it's leaked.
- if you do something like logitech do, there effectively is no client secret - it's just a different API I have to call. While Discord gets given a client secret, it can't reasonably any more faith that it is that app.
With the current model, if a desktop app can authenticate as a given discord app, anyone can make another, different app that authenticates as the same discord app. Ultimately /someone/ has to be trusting a remote client is a specific application, even if that is Logitech instead of Discord, and that is fundamentally impossible without requiring secure boot and TPM attestation (and most consumer desktops don't have TPMs).0 -
Suggestion (2) would help here (as long as the software doesn't decide to just directly manipulate the Discord app, which it can easily do, as, it's desktop software)
(1) wouldn't help, but it also would not have any concrete negative effect. There is no 'weaker of the two' - going via the web API is just an extra step with no real benefit.
For the IPC protocol to work at all, there must be some local app that has all the information it needs to convert a code to an oauth token. If there is a local app, the information can be extracted from it pretty easily. There is no real difference in security between 'no client secret', 'local app has a client secret', and 'local app knows someone else who has the secret, and knows how to ask them to use it'.0 -
This just seems over the top, the current system works fine. One cannot obtain others token without trying to scam the user which is pretty difficult considering your authToken is no longer displayed in developer options & the developer options display multiple warnings about how scammers can steal your account.
Tokens are not easily bruteforcable as well, while it would be ideal to have some sort of rate limit on authentication requests to make bruteforce attacks near impossible they're already difficult enough you probably don't need to worry about it, the chances of you or anyone getting their token bruteforced is very low.
-1 -
> One cannot obtain others token without trying to scam the user
This is simply not true for local apps (as opposed to web apps), which are all that is relevant for the named pipe/Unix socket RPC.
For web apps using HTTP APIs, the current flow makes sense.
0 -
Ultimately, once you have local apps like phone/windows/Mac apps, it is impossible to securely answer “what application is calling my API?” without TPM-based approaches that are not at all practical on average consumer systems, or even possible on most consumer desktop PCs.
I don’t just mean the current approach doesn’t do this (it doesn’t). No one does this effectively, because it is literally impossible.
0 -
So, there's a specification for this, that Discord isn't following: https://tools.ietf.org/html/rfc8252
This basically recommends:
- not trusting client secrets (8.5 and 8.6)- not requiring client secrets (8.5)
- API clients claiming URIs or URI schemes, and those being used by the main app (Discord itself) for the redirects
The last point is helpful on platforms such as iOS, where registering a domain or protocol is relatively locked down, but does not provide meaningful security benefits on Windows, macOS, or Linux, where any application (including malicious applications) can override a URI scheme to intercept.
It may also be useful to read through https://tools.ietf.org/html/rfc6819 (the OAuth thread model), especially every usage of the phrase 'public clients'.
Based on that, another suggestion: (3) provide a way to explicitly mark an app as a 'public client'. These would not require client secrets, and potentially could be restricted to the named pipe/unix socket. This should also mean that abuse tied to the app ID should not be assumed to be related to the discord user that created the app ID - this should already be the case for local clients, given how easy it is to impersonate them, as described above and in the oauth RFCs, but I'm assuming it isn't true given the need for a 'secret'.
For this reason, https://github.com/fredemmott/StreamDeck-Discord currently asks every user to create their own Discord app.0 -
Google's approach to this problem is to use local sockets to deliver the code without a client_secret, effectively option (1): https://developers.google.com/identity/protocols/OAuth2InstalledApp#creatingcred
https://tools.ietf.org/html/draft-ietf-oauth-native-apps-12#section-7.3 proposes this as a standard0
Please sign in to leave a comment.
Comments
8 comments