We currently use Auth0 to secure out B2B SaaS platform. One of our needs is the ability to provide our customers with API key authentication to allow other system to ingest the APIs we provide.
We referenced a few other threads in this community and our flow is something similar to:
A user requests a new API key to be generated.
System generated an Auth0 Machine to Machine application which is stored internally.
When a user authenticates via an API key, the system exchanges the API key for a token generated by the Machine to Machine client & secret.
Remainder of services are authenticated via the JWT that is generated in step 3.
This system works very well, except for one limitation. In the self service plans, Auth0 has a limit of 100 applications and since we utilize machine to machine applications for each of the API Keys, we are running into a limit of the number of API keys that we are able to provision.
Are we solving the API Key problem in the correct way?
Is there something we can be doing to avoid having to upgrade to an enterprise plan?
Thank you in advanced for your advice. We have tried to reach out to Auth0 support for reference architectures or examples, but simply haven’t received much help.
Thanks for sharing the flow diagram. My couple of observations/questions:
Security risk: You are storing client IDs and secrets for all of your clients in your database which can be grab all for anyone breaching your systems.
Risk of hitting Rate limits if for every call you need to exchange tokens.
Are these apps background processes apps that do not require user contexts?
What is the purpose of creating M2M application in Auth0 if you are identifying apps via API Keys?
what the Service is going to do with your M2M tokens? Is this your service or 3rd party ?
Following on to @jeff0 's thoughts:
Your API key is functionally the same as a client secret. You can simplify your architecture by having one M2M app for each of your clients, and giving them the client secret.
I don’t see the purpose of the added layer of complexity (exchanging the API key for a client secret then a token).
@jeff0 - Thanks for the response. I truly appreciate the observations.
I am certainly aware of the security implications of this
One item that we have in the storage mechanism is actually a cache of tokens, in order to avoid rate limiting. We will only generate a new token when the token is expired.
Yes. Most of these apps are background process apps that do not require user contexts. Either that or the user contexts are for different organizations that don’t utilize the same authorization mechanisms.
The purpose is to create a system that still provides OAuth tokens in order to authenticate with other internal services in the system.
The service is an internal service that is not aware of the the M2M token, but rather uses OAuth tokens to authenticate.
@john.gateley
Thank you for the response. That is actually a great point. The original idea was to create a system that allows for a single call to authenticate API requests. I suppose that is a double edge sword.
I think I know what you’re asking here, and I’ve seen this same ask appear in many different places across the Auth0 community forums. Many people seem to be asking for a user-based API key system - which Auth0 does not currently have.
They have made a public issue to vote on for this feature, but honestly, I’m really wanting to build this myself as a marketplace integration for Auth0. If you’re interested, would you mind giving my landing page a look as well and dropping your email? I’m trying to get my own sense on who all wants this before building. Thanks! https://www.keysync.io
Special thanks to Jeff and John for the architectural analysis and suggestions, however,
voting sounds more like a political issue and customers usually need a solution NOW.
So, sorry about jumping in late in the game. However, here is what you can do, and please, let me know if you want me to do it for you under a consulting contract LinkedIn:
Create an M2M app in Auth0 - I wanted to create one via Terraform, but sadly, there are no master keys as with an AWS account, so you need to create it manually via the Auth0 dashboard. After that things become a lot easier for Terraform :).
Deploy Hashicorp Vault - the community version will do. You can use Terraform for that and you can use Ansible or puppet for Vault’s internal “decoration”
Enable Vault’s OIDC method and configure it to work with the Auth0 provider. The OIDC method needs to be configured with AUTH0_DOMAIN, AUTH0_CLIENT_ID, and AUTH0_CLIENT_SECRET of the M2M app in Auth0 (grab the values from the settings of that app). This is needed for Vault to be able to talk to Auth0.
You can create credentials within Vault for accessing it. The “userpass” authentication method will do for this (nothing external to install). Of course, it really depends on how many people and with level of access you want to have. With Vault, the sky is the limit, because you have super fine-grained control via Vault policies over who can access what secrets (stored under a specific Vault path). See " Determine necessary ACL policy from Vault commands" in Vault’s documentation.
If you plan to consume the Autho tokens stored in Vault in your customer’s apps (not user credentials, so more like a machine-to-machine scenario), then take advantage of Vault client. It will renew the Vault tokens for accessing Vault (not Auth0) auto magically for your app, thereby avoiding the need to implement that logic in the apps themselves and polluting the app code with unnecessary Vault calls.
Best of luck. If you need my services, please, connect with me via LinkedIn first. We can jump on Zoom and Teams call to hash this out.