Master Auth0 with Vue3 & FastAPI: Your 2024 Guide!
When building prototypes or new tools, the question of authentication and authorization often boils down to a decision between build vs…
Master Auth0 with Vue3 & FastAPI: Your 2024 Guide!

When building prototypes or new tools, the question of authentication and authorization often boils down to a decision between build vs buy. Especially in light of the newly required features such as 2FA, OAuth with different providers, passkeys for macOS, passwordless authentication, etc., it can be daunting to determine which ones to implement and which ones to skip.
For me, at least, these points lead me to reconsider. Up until last year, I mainly used Django as a backend, where solid authentication and authorization, as well as user management, were built-in. Password hashing, validation, and resetting were tasks I didn’t need to handle, thereby avoiding the introduction of unstable or insecure methodologies. However, when I switched to FastAPI, most of these features were no longer available, and as I started several projects since then, I found myself needing to implement custom OAuth providers and user management repeatedly.
In one past Django project, I actually implemented custom OAuth, which functioned adequately, albeit with considerable time investment for both initial implementation and adding subsequent options. In essence, I looked for libraries and tools to simplify this process, especially given the number of projects I intended to start. I aimed to avoid reinventing the wheel each time.
After some research (i.e. comparing Auth0 and supertokens, supabase authentication and many more), I discovered that Auth0 is free to use under a certain monthly active user threshold, although I’ve been informed that costs can escalate rapidly beyond that point. Since then, I’ve integrated it into my FastAPI projects and encountered similar issues frequently. So, I’ve gone ahead and documented how to set up Auth0 in FastAPI and Vue now that I’m using it for frontend development too. Even though backend developers can skip this (just like I did before), knowing about these issues might come in handy down the line.
Let’s start with the actual setup. We will use token authentication for FastAPI, meaning there will not be an authentication endpoint or similar in our backend, the backend will simply get a JWT generated by Auth0 and validate it. The frontend will be a minimal app with a login and logout button and showing the user information. Furthermore, we will get one of the JWTs from Auth0 in the frontend, to make a backend request. There are a lot of good guides to continue from there with routerguards or other more advanced concepts, which I will not cover in this guide. In FastAPI we will validate the token, but as a backend developer used to having total control over the authentication process, I can’t help but implement a meAPI where we can get the current user information and change it with a PUT request. Additionally, I want to show how easy it is to use the user metadata for any information you want to store for the user. I am using this to store personal preferences (i.e. hasDarkModeEnabled), as well as additional information like a subscription ID. In the next chapter, we will setup the Auth0 instance for our FastAPI backend.
Auth0 Setup — Backend
First, you will need to sign up to Auth0 at https://auth0.com/ and setup your account. If there are any default applications, you may go ahead and delete them as we don’t need them for this guide. If you are not familiar, you can play around with the settings first, customize your login box (Branding > Universal Login) etc. Whenever you are ready you can go ahead and create the resources for the backend.
You will need an API, which you can create under Applications > APIs. Select Create API and give the API any display name and identifier you like. The identifier can’t be changed after the fact, it is recommended to use a URL. Most of the time I just choose the URL of the backend. If you don’t have any other preferences, you can add the API, which automatically adds an Machine-to-Machine Application as well. For the API you will not need to setup any more than this. However, you will need to copy the API audience, which is the identifier you added before. Now you need to go to the applications page where you have an application which is named after the API you just created with the suffix “(Test Application)”. Go ahead and copy the client ID and client secret for this. Also make sure that under the setting APIs for the Test Application both the API and the Auth0 Management API are selected as authorized. This ensures that we can adjust the user from the backend, as we can access the Auth0 API with this later.

Please make sure that you now have the following:
- Auth0 Client ID for the Backend Application
- Auth0 Client Secret for the Backend Application
- API Audience
- Auth0 Domain for your instance (xxx.REGION.auth0.com)
FastAPI setup
On to the coding for the backend. My current preference is FastAPI, but you can use the code very similarly with Flask or any other Python framework. This code is also mostly based on the official tutorial of Auth0, however I found it lacked specifically in regards to interacting with the user object. Also note that we don’t use the official Auth0 Python SDK, as it is not necessary, and I don’t want to bloat the project requirements.txt. I have used it in the past and you can too, however I didn’t see a large benefit.
As in the Auth0 tutorial, you will need to add a few dependencies. If you have your FastAPI app already set up, you will only need the dependency mentioned below to check the JWT.
pip install 'pyjwt[crypto]'
After this initial setup we need a method to authenticate the user. In FastAPI I use a dependency injection for that, you can use the method with FastAPIs Depends or Security injection. For my app I have a default fallback in the app object, as all my endpoints need authentication.
app = FastAPI(
dependencies=[Security(verify)]
)
If you don’t want coverage of your entire app, you can add the method to specific endpoints. Note that you will need to add it manually anyways if you need the authentication string (sub) within the endpoint. FastAPI makes sure that it doesn’t call the authentication twice.
def my_endpoint(sub: str = Security(verify)) -> None:
With this manual flag, you can mark the endpoint as needing authentication.
But now on to the actual verify method:
async def verify(
token: Optional[HTTPAuthorizationCredentials] = Security(HTTPBearer(auto_error=False)),
) -> str:
if token is None:
raise UnauthenticatedException
try:
signing_key = JWKS_CLIENT.get_signing_key_from_jwt(token.credentials).key
except jwt.exceptions.PyJWKClientError as error:
raise UnauthorizedException(str(error))
except jwt.exceptions.DecodeError as error:
raise UnauthorizedException(str(error))
try:
payload = jwt.decode(
token.credentials,
signing_key,
algorithms=[AUTH0_ALGORIGHM],
audience=AUTH0_AUDIENCE,
issuer=AUTH0_ISSUER,
)
except Exception as error:
raise UnauthorizedException(str(error))
return payload["sub"]
This is adjusted for returning only the sub string as it is the only thing I need later in the endpoint. If you need more details from the Auth0 dict, you can either return them here or return the entire dict. This verify method is very similar to what Auth0 recommends in the official guide. You’ll need to copy the exceptions from there for this code to work. It is up to you to input the Auth0 information, I am using environment variables for this.
AUTH0_DOMAIN = os.getenv("AUTH0_DOMAIN", "XX.eu.auth0.com")
AUTH0_AUDIENCE = os.getenv("AUTH0_AUDIENCE", "https://MY-API-URL.com")
AUTH0_ISSUER = os.getenv("AUTH0_ISSUER", "https://XX.eu.auth0.com/")
AUTH0_ALGORIGHM = os.getenv("AUTH0_ALGORIGHM", "RS256")
JWKS_CLIENT = jwt.PyJWKClient(f"https://{AUTH0_DOMAIN}/.well-known/jwks.json")
This setup would be enough, if we just want to verify that the user received their token from Auth0. Like I mentioned earlier, I am used to the control over the user object with Django, so I am going a step further to also provide a small meAPI. The actual API endpoints I will leave up to you, but I will provide the methods you can use to call in them.
First, you will need a management token to call the Auth0 management API. Here we will need our last two variables that we got from Auth0.
AUTH0_DOMAIN = os.getenv("AUTH0_DOMAIN", "XX.eu.auth0.com")
AUTH0_CLIENT_ID = os.getenv("AUTH0_CLIENT_ID")
AUTH0_CLIENT_SECRET = os.getenv("AUTH0_CLIENT_SECRET")
def get_management_token() -> str:
re = requests.post(
f"https://{AUTH0_DOMAIN}/oauth/token",
json={
"client_id": AUTH0_CLIENT_ID,
"client_secret": AUTH0_CLIENT_SECRET,
"audience": f"https://{AUTH0_DOMAIN}/api/v2/", # This is the management audience now, not the API audience
"grant_type": "client_credentials",
},
).json()
return re["access_token"]
With this you can now call the Auth0 API to get a user object or change it even. Note that you are responsible for the correct scoping of the requests. The management token doesn’t care if the user changes their own information or that of another user. For retrieving and updating of the user information I implemented two generic calls to the API.
def get_user(sub, mgm_token: str = get_management_token()) -> dict:
re = requests.get(
f"https://{AUTH0_DOMAIN}/api/v2/users/{sub}",
headers={"Authorization": f"Bearer {mgm_token}"},
)
if re.status_code != 200:
raise HTTPException(re.status_code, re.json())
return re.json()
def patch_user(
input_obj: dict,
sub,
mgm_token: str = get_management_token(),
) -> dict:
re = requests.patch(
f"https://{AUTH0_DOMAIN}/api/v2/users/{sub}",
headers={"Authorization": f"Bearer {mgm_token}"},
json=input_obj,
)
if re.status_code != 200:
raise HTTPException(re.status_code, re.json())
return re.json()
This is all you need to interact with the user object. You can build a meAPI with CRUD logic for this pretty easily.
Auth0 also offers a key-value storage directly on the user object. I am using this for user preferences and similar information that I normally would store in a user object. To use this user_metadata storage, I wrote three small methods making use of the previous methods to retrieve and update the metadata store.
def get_user_metadata(sub) -> dict:
return get_user(sub).get("user_metadata", {})
def patch_user_metadata(input_obj: dict, sub) -> dict:
return patch_user({"user_metadata": input_obj}, sub)
def clear_user_metadata(sub) -> dict:
return patch_user({"user_metadata": {}}, sub)
For demonstration purposes I will move all of this together into an endpoint that toggles the user’s dark mode preference.
def toggle_user_darkmode_preference(sub: str = Security(verify)) -> None:
user_metadata = get_user_metadata(sub)
user_metadata["darkmode"] = not user_metadata.get("darkmode", False)
patch_user_metadata(user_metadata, sub)
A small note on testing: You can override the verify method for the tests and return a test string like the code below. However, this will mean that once you are using methods like patch_user_metadata Auth0 will throw an error as it doesn’t recognize the test string. I worked around this by overriding all the methods and using a dictionary to keep track of the current user and therefore mocking all the API calls. This might be too much for your application, depending on how essential it is for users to be updated or changed.
def get_test_sub():
return "auth0|testsub"
app.dependency_overrides[verify] = get_test_sub
Bonus: How do I get an access token as a backend developer?
One of the things that annoyed me for a long time was that I never knew how to get a valid Auth0 token to test with. I could login to the frontend and try to get it from there or I could login to Auth0, where you can get a testing token. The testing token however wasn’t very useful, as there was no actual user behind it, so for validation it is useful, but as soon as you need user information it fails. Rest assured, there is a more elegant solution: the Auth0 CLI. You can download it for your OS (as long as it is macOS, Windows, Linux or can run Go). For macOS you can simply use brew:
brew tap auth0/auth0-cli && brew install auth0
After that you can use the following command to get a testing token:
auth0 test token -a https://YOUR-API-AUDIENCE.com -s openid
Once you run this, you will need to select your frontend application as the Client ID!

Then the browser will open, and you can login to the account you want the testing token for. When done, switch back to the console and copy the ACCESS TOKEN from there and you can use this in your FastAPI application as JWT. This token is valid as long as you ordered it to in your Auth0 settings. The default is 24 hours, so don’t be surprised if you need to replace it daily.
Auth0 Setup — Frontend
The additional setup for the frontend application is simple compared to the backend. On the Applications > Applications page simply click Create Application and follow the wizard by selecting Single Page Applications (you can change this after the fact if needed) and providing a visible name. Then copy the client ID from the generated SPA. You will need to provide the following fields with your local and later your frontend URL: Allowed Callback URLs, Allowed Logout URLs and Allowed Web Origins. It will look like this for Vue local:

Then you can follow the guide that Auth0 provides embedded in its interface, but we will show it here as well.
First you’ll need to add the Auth0 SDK:
npm install @auth0/auth0-vue
After that you can add the plugin to your app like this in your main.ts:
import { createAuth0 } from '@auth0/auth0-vue';
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
app.use(
createAuth0({
domain: 'XX.eu.auth0.com',
clientId: 'THE_CLIENT_ID_YOU_COPIED',
authorizationParams: {
redirect_uri: window.location.origin,
audience: 'THE_API_AUDIENCE',
},
}),
);
app.mount('#app');
After that you can go ahead and add a login and logout button like this:
<template>
<a v-if="!isAuthenticated" @click="loginWithRedirect()">Login</a>
<a @click="logout_local">Sign out</a>
</template>
<script setup lang="ts">
import { useAuth0 } from '@auth0/auth0-vue';
const { loginWithRedirect, logout, isAuthenticated } = useAuth0();
function logout_local() {
logout({ logoutParams: { returnTo: window.location.origin } });
}
</script>
I added a couple of things here to demonstrate different capabilities of the SDK
- See that you can either call the Auth0 methods from the template directly or from your script part.
- You can provide a couple of documented parameters to the login and logout methods, i.e. if the login should prefer a signup page or the login page
- The isAuthenticated flag can be used from here on out in your templates to show content based on this fact. There is also a user object you can import from useAuth0, which you could use to show email address or similar information. We won’t do this, as we get this info from the API.
Now on to answering the last question: how can we actually make a valid API call now? I wrote a helper function you can implement as well; my helper function has an API in mind that was generated by the openapi-generator-cli with the Axios client. But you can adjust this to your needs, the Auth0 part stays constant.
import { useAuth0 } from '@auth0/auth0-vue';
import { Configuration } from '../api/configuration';
export async function getApiConfig() {
const { getAccessTokenSilently } = useAuth0();
return new Configuration({
basePath: "https://YOUR_API_URL",
accessToken: getAccessTokenSilently(),
});
}
With this configuration you will get an access token, that you can send to your API.
Conclusion
This exact setup I needed to implement a couple of times already and it took me embarrassingly long to reimplement after the first time, so I am documenting it here to follow myself. After structuring this, it doesn’t at all seem complicated, but when during a sprint and tickets left and right getting escalated, it might not be as obvious. The second time I implemented this as the backend developer I remember the frontend team coming to us and asking how they could generate a token that was accepted by the backend. For me before it was as simple as saying “the backend accepts the token from Auth0, I don’t know what you guys need to do”. Now I consider what needs to be done in the frontend as well, especially preparing the Auth0 instance and communicating the correct audience for them to use.
For our use cases, Auth0 is a helpful tool, and we use it for authentication and user management daily in multiple of our apps. While there might be better tools out there, for now, it seems to be sufficient for us. It is easy enough to configure, scales rapidly, and allows us to focus on other priorities besides securing authentication, which is essential in small teams like ours.
In the future, I might consider adding an article about implementing roles and authorization (not only authentication, as covered in this article), or other FastAPI-related topics. If you’re interested, please let me know!
Stackademic 🎓
Thank you for reading until the end. Before you go:
- Please consider clapping and following the writer! 👏
- Follow us **X | LinkedIn | YouTube | Discord**
- Visit our other platforms: **In Plain English | CoFeed | Venture | Cubed**
- More content at **Stackademic.com**
메타데이터
- post_id
- c3631e80d8b8
- slug
- master-auth0-with-vue3-fastapi-your-2024-guide-c3631e80d8b8
- url
- https://blog.stackademic.com/master-auth0-with-vue3-fastapi-your-2024-guide-c3631e80d8b8
- canonical_url
- https://blog.stackademic.com/master-auth0-with-vue3-fastapi-your-2024-guide-c3631e80d8b8
- author_url
- https://medium.com/@creyd
- status
- ok
- fetched_at
- 2026-07-24 08:52:30