There are quite a few stackoverflow questions out there asking how to secure an OAuth2 client ID + secret in a pure-Angular SPA (eg. here, here or here) A lot of the answers eventually aim at changing the givens:
- pure client-side Angular application
- use OAuth2
- want to secure client ID + secret
by suggesting to encrypt the client ID, or maybe add a server-part.
From what I’ve learned so far, the short answer is: it cannot be done, and you’re probably asking the wrong question.
OAuth2 links client IDs with certain privileges, eg. what grant flows are allowed. Separating an application into server-side and client-side SPA is a classic example of where a Password Credentials grant flow actually makes sense. However, you don’t want to allow any client that grant flow, just your own. But why?
The restriction does not aim at preventing brute-force password attacks. Any attacker can run that directly against the server component, getting the required information from the server redirect page during a normal Authorization Code grant flow. The restriction does aim at preventing another client at posing as fully trusted “part of our application” client, and thus getting users to provide username/password (read: phishing). However, this would not be a cURL request, but would have to originate from a browser.
My suggestion in this scenario is to map the Origin (HTTP Header) to an internal client ID on the server side. Of course the Origin header can be forged, but then – again – we’re talking about forged attacks, and not phishing. The latter would run in a normal browser, sending the normal Origin header (which is controlled by the browser, and cannot be spoofed within the browser).