Client credentials for a browser application

I have a use case of providing a “public preview” through a browser application - a Single Page Application needs to access a protected resource without requiring the user to login.

This really seems to fit the client_credentials grant, except the grant should be only done on the server.

Is there a standard pattern for making this happen? Is there an acceptable way to authorize the single page application with the token obtained at the server through client-credentials?

This is a good reference for the client credentials grant:

It’s really for the case where an application needs a token to act on behalf of themselves rather than a user.

If the resource is accessible via a public preview and no login is required, is it really a protected resource?

With other user oriented flows, where the SPA doesn’t have any tokens - like the authorization code flow, there would be some sort of session between then SPA and a server app. The server app has the tokens and can make API requests on behalf of the user.

So, unless you are using the implicit flow, you would not want to pass back an access token to the SPA app. It would be especially unsafe to pass back a token obtained via client credentials grant as that token isn’t associated with a user (by design). That token, if leaked “into the wild” could then be used by anyone until its expiration.

Thanks for your reply.

“is it really a protected resource?”
Access to the resource is protected for the typical use case, and we are trying to enable this special “preview” functionality within a limited context. So we were trying to avoid devising an elaborate workaround to enable this with no access token – instead come up with a valid AccessToken that can be accepted by our existing APIs and services.

This is likely a naive question, but why is the accessToken obtained by implicit flow in a SPA app any more secure than that SPA app obtaining an accessToken from the server through the client credentials workflow? Wouldn’t the concern of the token being leaked into the wild be applicable for implicit flows as well?

From the perspective of the resource owner, the client has afterall been authorized just like any other user.

Leaking access tokens is always a concern because of them being “bearer” tokens.

The type of access token you get back as the result of an implicit grant flow is bound to a user and is limited to the access that that user would have (usually driven by scopes related to the token). If this token is leaked, you at least know that “John’s” account has been compromised (or John himself is trying to abuse the app)

Since the access token coming back from the client credentials flow is not bound to a user, you would have no way of knowing who (or what) was responsible in its use.

Thanks again for your insight. In our case it seems the best we can do is hold the preview application responsible - we are after all allowing all users unfettered access to the application.

Our SPA uses the implicit flow, and passes the accessToken to various services. One option to solve this could be to introduce a “proxy server” in between (it’s a fair bit of refactor to do this) - like you mention, there can be a session between the SPA and this proxy server, and the proxy server can in-turn make API requests on behalf of the SPA. Should this proxy server then use client-credentials? The token is itself then hidden from the SPA with this approach, but the API can still be misused. However, the misuse will be restricted to whatever the proxy server exposes, and the registered (preview) application can be held responsible. Like was mentioned earlier, we are after all allowing all users unfettered access to this preview application - so we are accepting the possibility that the API (exposed by this proxy server) can be misused.

However, does this option sound all that much better than just “leaking” the access token? In both cases, we can hold the application responsible - just that in the first case, we also limit the possibility of misuse to the API exposed by the proxy server.

Is there a better pattern for solving this preview use case?