You reached the right conclusions; the use of the token endpoint either for client credentials grants or resource owner password grant (ROPC) is not recommended for a SPA. The client credentials grant is outright not possible because the client application (SPA) is unable to maintain a client secret without disclosing it to anyone interested in obtaining it.
This means that if you want a SPA to access an API without the notion of a user, then that API needs to be public. The approach available for a SPA would be to include the notion of user credentials, because with users the credentials would be stored by the user and not the SPA. You can make this as simple as a common set of user credentials used by everyone that needs access, but you would have to have users involved so that the credentials can be stored by the users themselves and not the SPA.
For a user based flow although ROPC is possible, is not recommended given the availability of other options. The recommended approach would be indeed to use the implicit grant. In general, with the implicit grant you could implement something like the following:
- The user accesses your SPA application.
- The SPA application redirects the user to Auth0 so that they can authenticate and provide consent for your application to access the API in question.
- I mention consent, but this may be implicit consent and such transparent to the end-user; it’s dependent on your exact configuration.
- The user completes the authentication and authorization procedure.
- The Auth0 identity provider redirects back the user to your client application with the issued tokens.
- The issued tokens will likely contain an ID token and an access token, but this depends on you performed your request.
- Your client application, as part of the response to triggered callback URL, processes the tokens.
- You use the ID token to know who the user is (get some information about them) and the access token to call your API.
The above assumes that you correctly configure your SPA to make an initial request for user authentication and API authorization; this generally boils down to including the
openid scope to signal that you’re making an OpenID Connect request, requesting a response type that includes both an
id_token and an access token (
token) and finally including an
audience parameter to indicate which API is the target of your API authorization request.
You can achieve this by making use of Auth0.js v8 and not having to deal with making the raw requests to the underlying authorization endpoint. In particular, check the webAuth.authorize() method available in this library.
If you have a specific issue with the above process then please create a new question that focuses on that issue and contains all the information you think may be relevant to it.