Skip to content

Commit

Permalink
Fixed and simplified login flow by adding route guards
Browse files Browse the repository at this point in the history
  • Loading branch information
rimutaka committed Oct 29, 2024
1 parent 1df65ec commit 3bd9cac
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 71 deletions.
61 changes: 19 additions & 42 deletions vue/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { watch, watchEffect } from 'vue';
import { RouterView, useRoute } from 'vue-router'
import { useAuth0 } from '@auth0/auth0-vue';
import { storeToRefs } from 'pinia'
import { LAST_AUTH_TIMESTAMP, URL_PARAM_TOPICS, URL_PARAM_LIST_SEPARATOR } from "@/constants";
import { URL_PARAM_TOPICS, URL_PARAM_LIST_SEPARATOR } from "@/constants";
import { useMainStore } from '@/store';
import TopHeader from './components/TopHeader.vue';
Expand All @@ -28,61 +28,38 @@ const route = useRoute();
console.log(`App load/auth: ${isLoading.value}/${isAuthenticated.value}`);
// save auth details in the localStorage
if (isLoading.value) {
console.log("Auth is loading");
} else {
updateAuth();
}
// needed to minimize auth errors when the token is requested before the auth is complete
watch(isLoading, (newVal, OldVal) => {
// get token details as soon as the user is authenticated
watch(isAuthenticated, (newVal) => {
if (newVal) {
console.log(`Auth is still loading: ${newVal} / ${OldVal}`);
} else {
updateAuth();
addTokenClaimsToStore();
}
});
function updateAuth() {
if (isAuthenticated.value) {
// a flag to tell the app that the user was authenticated before
// and it is OK to ask to re-authenticate if the token is expired
localStorage.setItem(LAST_AUTH_TIMESTAMP, Date.now().toString());
// console.log("Auth status updated in LS");
console.log(idTokenClaims.value);
email.value = idTokenClaims.value?.email;
token.value = idTokenClaims.value?.__raw;
// console.log(`Email: ${email.value}`);
}
else {
// console.log("Not authenticated");
(async () => {
// log in the user if the the user was logged in before
const lastAuth = localStorage.getItem(LAST_AUTH_TIMESTAMP);
// console.log(`Last auth/auth'd: ${lastAuth}/${isAuthenticated.value}`);
if (lastAuth && !isAuthenticated.value) {
console.log("User was logged in before, logging in again");
try {
const accessToken = await getAccessTokenSilently();
// console.log(`Access token: ${accessToken}`);
} catch (e) {
console.log(`Error getting access token: ${e}`);
loginWithRedirect();
}
}
})();
/// copy token details to the store
function addTokenClaimsToStore() {
if (!isAuthenticated.value) {
console.log("Cannot update token - not authenticated");
return;
}
// console.log("Auth status updated in LS");
console.log("idTokenClaims", idTokenClaims.value);
// console.log(`Email: ${email.value}`);
email.value = idTokenClaims.value?.email;
token.value = idTokenClaims.value?.__raw;
}
/// 1. copy the list of topics from the URL to the store
/// 2. copy the token details to the store
watchEffect(() => {
// use query string parameters to preset the selected topics
const qsTopics = route.query[URL_PARAM_TOPICS]?.toString();
if (qsTopics) {
console.log("Setting selected topics from query string: ", qsTopics);
selectedTopics.value = qsTopics.split(URL_PARAM_LIST_SEPARATOR);
}
addTokenClaimsToStore();
});
</script>
19 changes: 6 additions & 13 deletions vue/src/components/HomeForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
<div class="flex flex-wrap mt-12 mb-4">
<div class="flex-shrink text-start mx-auto">
<Button label="Browse more questions or subscribe" icon="pi pi-envelope" raised rounded class="font-bold px-8 py-4 md:me-4 mb-2 whitespace-nowrap" @click="navigateToSubscription" />
<p class="text-xs text-center md:mb-auto text-slate-500">You will be asked to <span class="link" @click="signIn">sign in</span> with <i class="pi pi-github ms-1 me-2"></i><i class="pi pi-google me-2"></i><i class="pi pi-microsoft me-2"></i><i class="pi pi-linkedin me-2"></i></p>
<p class="text-xs text-center md:mb-auto text-slate-500">You will be asked to
<a :href="`/${PageNames.SUBSCRIPTION}`" @click.prevent="router.push(PageNames.SUBSCRIPTION)">sign in</a>
with <i class="pi pi-github ms-1 me-2"></i><i class="pi pi-google me-2"></i><i class="pi pi-microsoft me-2"></i><i class="pi pi-linkedin me-2"></i>
</p>
</div>
<p class="w-full text-center my-4">or</p>
<div class="flex-grow text-center mb-4">
Expand All @@ -15,7 +18,7 @@
</div>
</div>
<TransitionSlot>
<SampleQuestion v-if="currentTopic" :topic="currentTopic" :nonce="nonce"/>
<SampleQuestion v-if="currentTopic" :topic="currentTopic" :nonce="nonce" />
</TransitionSlot>
</div>
</template>
Expand All @@ -24,10 +27,10 @@
<script setup lang="ts">
import { ref } from 'vue';
import router from '@/router';
import { useAuth0 } from '@auth0/auth0-vue';
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store';
import { TOPICS, URL_PARAM_LIST_SEPARATOR } from "@/constants";
import { PageNames } from '@/router';
import Button from 'primevue/button';
import TopicsList from './TopicsList.vue';
Expand All @@ -36,7 +39,6 @@ import SampleQuestion from "./SampleQuestion.vue";
const store = useMainStore();
const { selectedTopics, currentTopic } = storeToRefs(store);
const { isAuthenticated, loginWithRedirect } = useAuth0();
const nonce = ref<string | undefined>(undefined); // needed to force re-render of SampleQuestion for the same topic
/// Show a random question from the selected topics or all topics
Expand All @@ -60,13 +62,4 @@ async function navigateToSubscription() {
}
}
/// Auth0 login
function signIn() {
if (!isAuthenticated.value) {
loginWithRedirect();
} else {
console.log("Already authenticated");
}
}
</script>
2 changes: 1 addition & 1 deletion vue/src/components/SubscriptionForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ async function subscribe() {
watchEffect(async () => {
console.log(`Fetching user details for: ${email.value}`);
// only fetch if topic is set
// only fetch if the user is known
if (!email.value) return;
// redirect the user to login with the list of topics as a parameter
Expand Down
4 changes: 2 additions & 2 deletions vue/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ app.use(router)

app.use(PrimeVue, {
theme: {
preset: Aura
preset: Aura
}
})

Expand All @@ -25,7 +25,7 @@ app.use(
domain: "dev-lbpjc402mmk4uxbs.us.auth0.com",
clientId: "p2xjvyoxb8HoKSt1QNDx7CQ8Ka2lXgUJ",
authorizationParams: {
redirect_uri: window.location.href
redirect_uri: window.location.origin,
}
})
);
Expand Down
32 changes: 21 additions & 11 deletions vue/src/router/index.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,48 @@
import { createRouter, createWebHistory } from 'vue-router'
import { createAuth0, authGuard } from '@auth0/auth0-vue';
import { authGuard } from '@auth0/auth0-vue';

import HomeView from '../views/HomeView.vue'
import QuestionFormView from '@/views/QuestionFormView.vue'
import QuestionView from '@/views/QuestionView.vue'
import AboutView from '../views/AboutView.vue'
import SubscriptionView from '../views/SubscriptionView.vue'

/// A list of page names used elsewhere in the app
export const PageNames = {
HOME: 'home',
ADD: 'add',
QUESTION: 'question',
ABOUT: 'about',
SUBSCRIPTION: 'subscription',
}

const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
name: PageNames.HOME,
component: HomeView
},
{
path: '/add',
name: 'add',
component: QuestionFormView
path: '/' + PageNames.ADD,
name: PageNames.ADD,
component: QuestionFormView,
beforeEnter: authGuard
},
{
path: '/question',
name: 'question',
path: '/' + PageNames.QUESTION,
name: PageNames.QUESTION,
component: QuestionView,
},
{
path: '/about',
name: 'about',
path: '/' + PageNames.ABOUT,
name: PageNames.ABOUT,
component: AboutView
},
{
path: '/subscription',
name: 'subscription',
path: '/' + PageNames.SUBSCRIPTION,
name: PageNames.SUBSCRIPTION,
component: SubscriptionView,
beforeEnter: authGuard
}
Expand Down
19 changes: 17 additions & 2 deletions vue/src/views/HomeView.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,35 @@
<template>
<TransitionSlot>
<HomePitch v-if="!currentTopic" />
<HomePitch v-if="!currentTopic && !isLoading" />
</TransitionSlot>
<HomeForm />
</template>

<script setup lang="ts">
import { ref, watchEffect } from 'vue';
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store';
import router from '@/router';
import { useAuth0 } from '@auth0/auth0-vue';
import { PageNames } from '@/router';
import TransitionSlot from "@/components/TransitionSlot.vue";
import TransitionSlot from "@/components/TransitionSlot.vue";
import HomeForm from '@/components/HomeForm.vue';
import HomePitch from '@/components/HomePitch.vue';
const store = useMainStore();
const { currentTopic } = storeToRefs(store);
const { isAuthenticated, isLoading } = useAuth0();
/// redirect to subscription page if the user is authenticated
watchEffect(() => {
console.log(`HomeView: Auth status: ${isLoading.value}/${isAuthenticated.value}`);
if (isAuthenticated.value) {
console.log("User is authenticated - redirecting to subscription page");
router.push({ name: PageNames.SUBSCRIPTION });
}
});
</script>

0 comments on commit 3bd9cac

Please sign in to comment.