In my Spartacus application(version 1.4.3) , I want to avoid a http post call made from refreshToken method in user-authentication-token.service.ts as we are having a separate setup for user login.
So I need to override the refreshToken method to avoid the http post method happening inside that method. Please let me know if there is a way to do it .
You described the solution in the question.
Create your own UserAuthenticationTokenService which extends spartacus one. Then override refreshToken method and provide your service as UserAuthenticationTokenService (eg. { provide: UserAuthenticationTokenService, useClass: NewUserAuthenticationTokenService })
Related
I'm attempting to create some route guarding using the new Next.Js 12 middleware feature. My authentication is based on a JWT token set on a cookie. I had previously implemented this using the API backend on Next.Js with no issues, and still when hitting the API routes the cookie will persist on the request no problem.
My issue appears when it will request a static page from the server. No cookies are attached so I can not determine if a User is authenticated and always redirect to a log in page. So for example the request to http://localhost:3000/ (Homepage) will not send any cookies to the middleware. But, http://localhost:3000/api/user will send a cookie to the middleware. Is there a setting I have missed in the documentation to allow this to happen?
Not sure if at all helpful but here is my _middleware.ts file that sits on the root of the pages.
import type { NextFetchEvent, NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
const middleware = (req: NextRequest, ev: NextFetchEvent) => {
console.log(req.cookies);
console.log(req.cookies['user']);
console.log(req.nextUrl.pathname);
if (req.nextUrl.pathname === '/') {
return NextResponse.redirect('http://localhost:3000/login');
}
};
export default middleware;
Next.js > 12.2
req.cookies.get("user")
Before Next.js 12.2,
req.cookies?.user
I had a same problem. I use tag for routing and it works but im not sure that it is a good choice.
I'm wondering if it's possible to essentially "reevaluate" the middleware conditions without actually changing the current route.
The middleware's purpose is to prevent non-logged-in users from accessing the "dashboard".
My issue is, a user could become logged in or logged out without necessarily changing route but they wouldn't be redirected until they try and change pages.
I have a VueX action that triggers when the user's auth state changes but this (from what I can see), can't access the redirect or route variables.
// /mixins/auth.js
const reevaluateAuthStatus = (store, redirect, route) => {
console.log(route)
const redirectPolicy = route.meta.map((meta) => {
if (meta.auth && typeof meta.auth.redirectPolicy !== 'undefined') { return meta.auth.redirectPolicy[0] }
return []
})
const user = store.getters['auth/getUser']
if (redirectPolicy.includes('LOGGEDOUT')) {
if (user) {
return redirect('/dashboard')
}
} else if (redirectPolicy.includes('LOGGEDIN')) {
if (!user) {
return redirect('/login')
}
}
}
module.exports = {
reevaluateAuthStatus
}
// /middleware/auth.js
import { reevaluateAuthStatus } from '../mixins/auth'
export default function ({ store, redirect, route }) {
reevaluateAuthStatus(store, redirect, route)
}
Appreciate any help on this :)
You cannot re-evaluate a middleware AFAIK because it's mainly this (as stated in the documentation)
middlewares will be called [...] on the client-side when navigating to further routes
2 clean ways you can still achieve this IMO:
use some websockets, either with socket.io or something similar like Apollo Subscriptions, to have your UI taking into account the new changes
export your middleware logic to some kind of call, that you could trigger again by calling the $fetch hook again or any other data-related fetching hook in Nuxt
Some more ugly solutions would probably be:
making an internal setInterval and check if the actual state is still valid every 5s or so
move to the same page you are actually on with something like this.$router.go(0) as somehow explained in the Vue router documentation
Still, most of the cases I don't think that this one may be a big issue if the user is logged out, because he will just be redirected once he tries something.
As if the user becomes logged-in, I'm not even sure on which case this one can happen if he is not doing something pro-active on your SPA.
I don't know if it's relevant or not, but I solved a similar problem this way:
I have a global middleware to check the auth status. It's a function that receives Context as a parameter.
I have a plugin that injects itself into context (e.g. $middleware).
The middleware function is imported here.
In this plugin I define a method that calls this middleware passing the context (since the Plugin has Context as parameter as well): ctx.$middleware.triggerMiddleware = () => middleware(ctx);
Now the middleware triggers on every route change as intended, but I can also call this.$middleware.triggerMiddleware() everywhere I want.
Is is possible to disable some of the default Spartacus calls?
After the user is logged in there are some calls that are made by default, but I do not need and would like to disable if possible.
These are the calls:
"...users/current",
"...users/current/consenttemplates...",
"...users/current/carts..."
The second and third one are made exactly after the login process and the first one is made after a page refresh or when navigating to different pages.
I found a way to do this by creating a custom interceptor and using NEVER from rxjs:
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
/**
* Deny list for calls we do not want to use from the Spartacus storefront
*/
if (request.url.includes('consenttemplates') || request.url.includes('carts') || request.url.includes('users/current')) {
return NEVER;
} else {
return next.handle(request);
}
}
You can also implement the related OccAdapter(s) and replace them in the providers array in a module. In your custom implementation you can leave the methods empty.
Here is described how: https://sap.github.io/spartacus-docs/cybersource-integration/#providing-a-custom-implementation-for-the-checkoutpaymentadapter
I have a site with web components based architecture, where each web component may be a separate Vue app with it's own API layer integrated via Axios. I need to implement Auth middleware for all HTTP requests, coming from either root app or web component app. I cannot use Axios built-in interceptors mechanism as there will be multiple instances of Axios. Is there a way I can do it with global JS methods? I know there is some browser extension based API out there, but that doesn't seem like something I am looking for.
Just in case anybody else is interested, I have solved it with service worker. You can subscribe to fetch events and respond according to your auth logics. Your service worker code will look something like following:
self.addEventListener('fetch', async (event) => {
const isAuthorised = await checkIsAuthorized(); // your auth API layer
if (!isAuthorised) {
const response = new Response(null, {
status: 401,
statusText: 'Unauthorised',
});
event.respondWith(response);
return;
}
event.respondWith(fetch(event.request));
});
Service worker is able to intercept axios requests from shadow DOM as well, so it's a good match for web components case.
Besides, there is a nice article by Bartosz Polnik on implementing auth layer using service worker.
I have a Nuxt app with authentication already running in universal mode.
I'm trying to convert the authentication service to Auth0. I'm following the Vue quickstart, but I discovered that auth0-js is a client side library since it uses a lot of 'window'-stuff that is not available on the server-side of Nuxt.
However, I got it kind of working by making it a client-side plugin and wrap all functions (that is calling the authservice in the lifecycle hooks) in a process.client check. It works "kind of" because when going to the protected page whilst not logged in, it flashes the page before being redirected to login page (since its rendered on the server-side as well, but the check only happens once it's delivered on the client side I presume).
My question now is: What can I do in order to add the check to server-side as well? (or at least make sure that the protected pages isn't flashed before being redirected).
What I've tried so far:
Saving the payload and the logged-in state in the store and check in some custom middleware, but that didn't do the trick.
Also, it seems to me that #nuxt/auth is outdated or something and the nuxt auth0 example as well. It uses auth0-lock while I'm using the new auth0 universal.
Anyone have suggestions on how to solve this issue? Thanks in advance!
not sure if this will be any help and have only answered a few questions (other account long time ago).
Update.. I read my answer then the question title (I think my answer does cover some of your context), but in regards to the title you could also look at using auth as a plugin. You can then handle stuff there before the page is hit.
I am not sure how your code is implemented, but this may help (hopefully).
If you are not using Vuex, I strong recommend it. Nuxt Vuex Store Guide
// index/store.js
// At least have the store initialized, but its most likely going to be used..
// page.vue
<template>
...
<div v-else-if="!$auth.loggedIn">
{{ test }}
</div>
...
...
data() {
if (!this.$auth.loggedIn) {
const test = 'Only this will load, no flash'
return { test }
}
}
$auth.loggedIn is built in, I read it ..somewhere.. in the docs
This will solve the no flash issue, you can also take advantage of a loader screen and asyncData to check the state before rendering the view to avoid a flash and populate data if it hangs.
You could also try using Vuex Actions, I am currently playing with these 2 in the process of where I am now. Learning about nuxtServerInit()
// store/index.js
import axios from 'axios'
export const actions = {
nuxtServerInit ({commit}, {request}) {
// This is good if you have the user in your request or other server side stuff
if (request.user) commit('SET_USER', request.user)
},
async GET_USER({ commit }, username) {
const user = await axios.get(`/user/${username}`)
if (user) commit('SET_USER', user)
}
}
export const mutations = {
SET_USER(state, user) {
// simple set for now
state.auth.user = user || null
}
}
The second one is combined using the fetch() method on the page itself.
// page.vue
async fetch({ $auth, store }) {
await store.dispatch('GET_USER', $auth.$state.user)
}
Now you can call $auth.user in your code as needed.
$auth.user is another built in I read ..somewhere..
You can also call $auth.user with the $auth.loggedIn to check if user exists on top of being logged in $auth.user && $auth.loggedIn.
It may be this.$auth.<value> depending on where you are trying to reference it.
I learned the asyncData() gets call first and logs in my server, then data() logs values in the server console as well (false, null), but in my Brave console they're undefined, i'd like an answer to that lol
I have been struggling with trying to get Auth0 to work how I wanted with JWTs, but as I kept crawling I found useful bits along the way (even in old demos such as the one you mentioned, just nothing with the lock stuff...). Also in terms of express and my API in general... Anyways, hope this helped (someone).