Comments (11)
Could you try to move the logic of checking the user + plan directly into a Nitro plugin, we have session hooks for this: https://github.com/Atinux/nuxt-auth-utils?tab=readme-ov-file#extend-session
// server/plugins/session.ts
export default defineNitroPlugin(() => {
// Called when the session is fetched during SSR for the Vue composable (/api/_auth/session)
sessionHooks.hook('fetch', async (session, event) => {
const latestUserData = await findUserById(session.user.id);
const { subscribed, isCanceled, proPlan } = await checkPlan(latestUserData);
session.user.subscribed = subscribed;
session.user.isCanceled = isCanceled;
session.user..proPlan = proPlan;
})
})
This should update the session before returning it to useUserSession()
and will also work when running fetch
from useSessionSession()
from nuxt-auth-utils.
Closing this, thank you for the help!
from nuxt-auth-utils.
As a workaround I am doing a hard reload - return window.location.replace("/dashboard");
from nuxt-auth-utils.
You need to call the fetch
method to refresh the session on client-side @fayazara
const { fetch: refreshSession } = useUserSession()
async function onSubmit(event) {
try {
loading.value = true;
await $fetch("/api/auth/login", {
method: "POST",
body: state,
});
await refreshSession()
return navigateTo("/dashboard");
} catch (error) {
toast.add({
title: "Error",
description: error.statusMessage,
color: "rose",
});
loading.value = false;
}
}
from nuxt-auth-utils.
Worked perfectly, thank you!
from nuxt-auth-utils.
@Atinux reopening this for another question.
What is the right way to update the session after the user data has been updated and we want to update the session data? I saw there's replaceUserSession,
Use case:
I am using a webhook to update the users plan/subscription data after they pay on stripe. My db gets updated, but I am lost on a good way to update the session, because it wont happen unless I refresh the page or login again.
What I tried doing (but doesn't work properly)
<template>
<AppContainer title="Settings">
<div class="h-full p-4">
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4">
<div>Current subscription: {{ user?.proPlan?.name || "Free" }}</div>
</div>
<div class="grid grid-cols-3 gap-4 mt-4">
<div class="" v-for="plan in plans" :key="plan.id">
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4">
<h2 class="text-xl font-semibold">{{ plan.name }}</h2>
<p class="text-gray-500 dark:text-gray-400 text-sm">
{{ plan.description }}
</p>
<ul class="mt-4">
<li
v-for="feature in plan.features"
class="flex items-center gap-2"
>
<UIcon name="i-lucide-check" class="text-primary-500" />
<span>{{ feature }}</span>
</li>
</ul>
<div class="mt-4">
<span class="text-3xl font-semibold">{{ plan.price }}</span>
<span class="text-gray-500 dark:text-gray-400">/ month</span>
</div>
<UButton
class="mt-4"
variant="solid"
color="white"
size="lg"
block
label="Subscribe"
@click="subscribe(plan.stripePriceId)"
/>
</div>
</div>
</div>
</div>
</AppContainer>
</template>
<script setup>
const { user, fetch: refreshSession } = useUserSession();
const { data: plans } = await useFetch("/api/stripe/get-plans");
const route = useRoute();
const toast = useToast();
const subscribe = async (planId) => {
const data = await $fetch(`/api/stripe/checkout?plan=${planId}`);
if (data.url) window.location.href = data.url;
};
onMounted(async () => {
await $fetch("/api/auth/update-session");
});
</script>
Created a api route called update-session
import { findUserById } from "@/server/utils/queries/users";
export default defineEventHandler(async (event) => {
const session = await requireUserSession(event);
const userId = session.user.id;
const latestUserData = findUserById(userId);
delete latestUserData.password;
const newSessionData = {
...session,
user: latestUserData,
};
await replaceUserSession(event, newSessionData);
return { success: true };
});
Doesn't update the session with the new data for some reason
from nuxt-auth-utils.
I think for such use case where you update the session on server-side, I would use useDocumentVisibility in the mounted() hook of the page in order to refresh the session when the tab becomes active again ;)
from nuxt-auth-utils.
@Atinux I dont think the issue is related to updating the data in realtime, sorry if I was not clear, the session is not updated even after I get redirected from the stripe page or when the page is refreshed
Below video might explain my problem better.
- You can see the stripeId and other details are empty.
- Stripe flow is completed and data gets added in my db.
- We're redirected back to my billing page and I still see the "Plan as Free"
- You can see the stripe details in my db
- I refresh the page and still see the data not yet update.
The session get's updated only if I logout and login, probably because we're clearing repopulating the session data. I think my question probably is, does the session data not get updated when I refresh the page?
Screenshot.25-02.at.19.mp4
from nuxt-auth-utils.
Apologies I understand this is not an issue related to the module, rather an issue with my business logic. Just trying to understand how to get subscriptions working.
I now realise that we set the session only when the user logins and it's not mutated after that, so when the user is redirected from stripe the db is updated not the session.
So I thinking I will just set the session one more time once we land on this page.
from nuxt-auth-utils.
UPDATE:
I am now manually updating the session and it still won't update my session in the client 😅
billing.vue page
<template>
<AppContainer title="Settings">
<div class="h-full p-4">
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4">
<div>Current subscription: {{ user?.proPlan?.name || "Free" }}</div>
</div>
<AppBillingPlanSelector />
</div>
</AppContainer>
</template>
<script setup>
const { user, fetch: refreshSession, session } = useUserSession();
await useAsyncData("session-manager", async () => {
await useRequestFetch()("/api/auth/update-session");
await refreshSession();
});
</script>
And this is the update-session api endpoint
import { findUserById } from "@/server/utils/queries/users";
export default defineEventHandler(async (event) => {
try {
console.log("I am here in update-session.js");
const session = await requireUserSession(event);
const userId = session.user.id;
console.log("userId", userId);
const latestUserData = await findUserById(userId);
delete latestUserData.password;
const { subscribed, isCanceled, proPlan } = await checkPlan(latestUserData);
latestUserData.subscribed = subscribed;
latestUserData.isCanceled = isCanceled;
latestUserData.proPlan = proPlan;
console.log(latestUserData);
const updatedSession = await setUserSession(event, { user: latestUserData });
console.log("updatedSession", updatedSession);
return { success: true };
} catch (error) {
console.log(error)
throw createError({statusCode: 500, statusMessage: "Error updating session"});
}
});
I can see the logs getting printed in the console from the api and the updated session data, but it still wont get updated in the client side as I am calling the fetch: refreshSession
method after I update my session in the server with my custom endpoint.
from nuxt-auth-utils.
Thank you 🫡
from nuxt-auth-utils.
Related Issues (20)
- Strange issue, Auth0 always needs to be logged in twice repeatedly to be recognized properly HOT 3
- [Question] Expose/access the tokens HOT 5
- Discord oauth error HOT 2
- Better typing of UserSession HOT 3
- Max key length? HOT 1
- `setUserSession()` is merging data HOT 4
- Utils does not work with Azure SWA HOT 7
- Verify Request Origin for session decoding HOT 1
- Only expose public data part of session HOT 6
- [Google] Not possible to provide extra config for authorization HOT 1
- Prefer Single Exports Over `oauth` HOT 1
- Support Dynamic Config HOT 1
- Casdoor Provider Support.
- Create OAuth provider in userland code HOT 1
- (discord oauth2) Session state not persisting across page refreshes with Nuxt 3 and useUserSession only when deployed on Vercel HOT 3
- Facebook Login HOT 4
- How can use Laravel passport HOT 1
- Cannot use clear in middleware HOT 1
- Add more scopes on the google oath HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from nuxt-auth-utils.