Sometimes, I found myself discussing security with other developers, specifically client-side security vs server-side security. In particular, there is a question of whether client-side development is secure, since you cannot store secret keys or access tokens without making them public.
The point is that security is never binary. In fact, nothing is really secure or insecure in absolute terms, but rather secure enough, or potentially insecure. It's all about the use case, and security is always compromised for ease of use.
Passwords are a good example. A string of 20 random characters that includes capital letters, digits, and symbols is more secure than "password", "123456", or your birthdate, but it is much harder to remember and type. Furthermore, a password with 20 random characters is weaker than a password with 30 characters from the same alphabet, and a password with 30 characters is weaker than a password with 40 characters. No matter what your level of security is, there is always a higher level that grants you more protection, but the higher the level of protection, the greater the complexity. In a zero-sum game, you have to figure out what's an acceptable trade-off between security and complexity for your specific need.
In the context of API authentication, the OAuth2 protocol defines two types of clients: confidential and public. Confidential clients are applications that can securely authenticate with the authorization server, keeping their registered client secret hidden. Public clients, instead, are applications running in a browser or on a mobile device that cannot use client secrets, as they'd be exposed publicly.
It goes without saying that confidential clients are more secure than public clients. However, developing a confidential client is more complex, as it requires creating a server-side component or a BFF that stores the secret key to communicate with the API. In contrast, a public client can be developed directly on a web page, without the need for any server-side components. Client authorization is controlled by the API, which limits the public client's capabilities at the application level. Development is much easier in this case.
So what's the best approach? Choosing the right type of client depends on what you need to build. As with passwords, you have to decide the right balance between security and simplicity and the most modern platforms are designed to support both options.
Stripe, for example, provides two types of API keys: one secret key for server-to-server communication and one publishable key, for inclusion in client-side code. Stripe is so popular among developers because of its publishable keys and client-side APIs that make embedding Stripe in your application a breeze using "elements" or no-code tools.
Similarly, Shopify provides both private and public access tokens for its Storefront API. It is also in this case that private tokens tend to be more secure but also more complicated to work with than public ones, so it is up to the developer to decide what is the best approach for their use case.
Commerce Layer also offers two different kinds of API credentials: a confidential client used to build server-side integrations, and a public client for sales channel applications. The integration application grants you more permissions. The sales channel API lets you build a shopping cart on your website or app in no time. Again, different levels of security but also complexity.
Security should never be compromised, particularly when building e-commerce applications. However, make sure you do not overcomplicate your stack unless you have a valid reason to do so. Use good common sense, trust your providers' security, don't really choose "password" as your password, and you'll be fine.