Application Secrets - The Achilles heel of security
When we write an application we often want to integrate multiple services together. For example, if you were creating a chat bot, you may want to integrate OpenAI's GPT into your application instead of building your own AI.
For good reasons OpenAI limits the usage of it's AI models, and because it costs money to run huge racks of servers, they charge for usage. So we need an account to access their products. This means we need to somehow handle authentication between our application and OpenAI's.
Although it may seem like a simple task to set up, this functionality introduces a whole new world of security implications and potential pitfalls.
The common approach
Although for some applications you can authenticate using a username and password, the most common approach (which appears to be 99.9% of the solutions you will find online) is to use a Personal Access Token (PAT).
There is rarely a good reason to use an account username/password approach to authenticate within your application. If it is breached:
- Whoever has the username/password has full access to your account.
- Anywhere you used this password is also potentially breached.
- You will have to change all instances of this password.
PATs are just a randomly generated token provided by the application, they provide the following benefit over using a username and password:
- They allow you to avoid putting your "master" account password in your application.
- They allow you to remove access without deleting the account.
- They (often) allow you to limit the access to functionality in your application.
- They (often) allow you to set an expiration date on the password.
This solves a couple of problems with the username/password approach:
- You can reduce your exposure if the secret gets leaked
- You can delete just the token, and no other accounts using your actual password will be breached.
Which is considerably better practice than sharing your account password with the development team and hoping that no one does anything dumb.
What do developers then do?
So once you have this "considerably more secure" authentication token, developers then decide to do one of the following:
- (Unbelievably bad) Hard-code the token right into your app.
- (Different but not great) Store the token in a
.env
file and access it via your application. - (Seems better, but is still a problem) Try to do some swanky encryption locally on the values when they're not in use, then decrypt them when they're being used.
All of these fail because:
- Anyone who has access to the code has access to your tokens. This means customers, hackers, team-members all have complete access.
- You can accidentally commit these credentials to your code-base.
- You have to share the raw secret values with any team member who wants to use the application.
- Anyone who has access to the production environment can view the secrets.
- You've got a file full of your passwords on the server, and you'll need to store the master password somewhere which still has all the issues from above.
There are also the following to consider:
- You should be rotating tokens.
- You should be setting access control on tokens.
- No one should really need to see the tokens once created.
None of these scale nicely.
What are our alternative then?
Most people have become accustom to the usage of single sign on (SSO) through providers like Azure or Okta, where a user logs into a centralized
Federated identity provides a way for users or services to authenticate across different domains or organizations without needing to manage separate credentials for each. Instead of creating and storing multiple usernames and passwords, users can authenticate using a trusted identity provider (IdP).
Benefits of Federated Identity Credentials (FIC)
- Security: We can now centralize the tokens, users log in and they get access to tokens they have permissions to have. They can be added, rotated, revoked with ease. They also can be consumed by the application without needing to be stored locally.
- Scalability: Simplifies identity management across organizations and cloud platforms. You have "one source of truth" and no variation between how each one of your apps work.
- Automation: Ideal for CI/CD pipelines and workloads needing short-lived access tokens. You can assign and refresh tokens with ease, removing the manual steps normally required for refreshing tokens.
How do I choose?
This is depending on many factors including size and scale. Are you a one-man team? Or do you find yourself waking up in a sweat because you don't know how many engineers have your password?
Do you find yourself emailing your GitHub PAT token to your colleagues? Got an AWS bill 100x the regular size, because your intern accidentally published your secrets on GitHub?
It's best to reach out to the experts if you are unsure about any portion of the process. Security is a pillar in the core of the development process, and should be treated as a high priority in every project.