Closed Lorentzo92 closed 6 months ago
To summarize your issue, when a user fails the access.admin
check when visiting the admin UI, they are not warned that they are unauthorized and you can't redirect that user.
If we just provide a config property for redirecting them somewhere else that feels incomplete to me. Payload always provides meaningful defaults whenever possible so without setting that property and making a page for it you would have bad ux and it is bad dx to have to do that.
Would it be expected to be redirected to /admin/unauthorized
which would show an unauthorized error?
From there we could use a new config property used to set the URL for a link to leave or log out in case they want to stay at the admin but log in with another account.
How does this sound? This looks more like a new feature to me.
Hi Dan,
Thanks for the reply. I agree with you, it is more like a feature and the /admin/unauthorized makes sense, of even just redirect to /login since the user is not authorized he/she should not be able to login, even if the payload-token exists in the cookies.
In the meantime i found a workaround by adding a middleware before mounting payload:
app.use("/cms", async (req, res, next) => {
const payload_user = await validateAccess(req);
if (payload_user) {
if (payload_user.user_type === "admins") {
next();
} else {
res.redirect("../");
}
} else {
next();
}
});
where validateAccess is
import { Request } from "express";
import { PayloadJWT } from "../../types";
const SECRET_COOKIE_NAME = "payload-token";
export const validateAccess = async (request: Request) => {
// validate
const cookieStore = request.cookies;
let token = "";
if (SECRET_COOKIE_NAME in cookieStore) {
const tokenCookie = cookieStore[SECRET_COOKIE_NAME];
if (typeof tokenCookie !== "undefined") {
token = tokenCookie;
}
}
if (token.length === 0) {
return undefined;
}
try {
// Convert the string to a Uint8Array
const encoder = new TextEncoder();
const secretData = encoder.encode(process.env.PAYLOAD_SECRET!);
// Create a hash of the secret
const hashBuffer = await crypto.subtle.digest("SHA-256", secretData);
// Convert the hash to a hexadecimal string
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
// Slice the first 32 characters
const secret = hashHex.slice(0, 32);
const [headerB64, payloadB64, signatureB64] = token.split(".");
const header = JSON.parse(atob(headerB64));
const payload = JSON.parse(atob(payloadB64)) as PayloadJWT;
return payload;
// // console.log([headerB64, payloadB64].join("."));
// console.log("payload:", payload);
// const data = new TextEncoder().encode([headerB64, payloadB64].join("."));
// const signature = Uint8Array.from(atob(signatureB64.trim()), (c) => c.charCodeAt(0));
} catch (err) {
console.error(err);
return undefined;
}
};
Hey @Lorentzo92 thanks for following up with your solution here. Gonna convert to discussion so others can find it!
Link to reproduction
No response
Describe the Bug
Hi,
We have a monorepo with nextjs14 app router and payload. In payload we have admins and users collections, only admin can access the admin panel. The routes structure is:
The issues we have is: if i login in nextjs /login as users i am correctly redirected to /, now if i try to go to /cms then payload remains pending since i am a user and i cannot access the admin panel, but i am not redirected, i only get an consolo log error "you are not allowed to perform this action"
I read through the doc but i could find a way to redirect this scenario.
To Reproduce
i can provide code if needed
Payload Version
2.8.2
Adapters and Plugins
No response