简体   繁体   中英

Cookie set by "Set-Cookie" not detected for another http request

I have a login process where after a user successfully logs in, a cookie will be set via "Set-Cookie" in the response. I've set up my backend with an authentication middleware that always checks for the cookie whenever a new http request is received. So far, when a user logs in from the client, the cookie is successfully stored. However, when I make another request on the client, I somehow lose the cookie; and the server treats the new request as an unauthorized request.

Response header after logging in: 登录响应头

Request header after sending a request after login: newRequestRequestHeader

Codes: Login - Set-Cookie (server)

    public logIn = async (req: Request, res: Response, next: NextFunction) => {
        const logInData: LogInDto = req.body;
        const user: UserInterface = await this.User.findOne({ email: logInData.email });
        if (user) {
            console.log(user);
            const passwordMatch: boolean = await this.authService.matchPassword(logInData, user);
            console.log(passwordMatch);
            if (passwordMatch) {
                const token: Token = this.authService.createToken(user);
                const cookie: any = this.authService.createCookie(token);
                res.setHeader("Set-Cookie", [cookie]);
                res.status(200).json(
                    {
                        message: "Login success",
                        user: user
                    }
                );
            } else {
                next(new CredentialsException());
            }
        } else {
            next(new CredentialsException());
        }
    }

New Request after login (Client)

const Dashboard: React.FC = () => {

    const handleClick = async () => {
        const res: any = await axios.get<any>(
            "http://localhost:4000/getusers",
            {
                withCredentials: true
            }
        );
        console.log(res);
    }

Authentication middleware (server)

export async function authMiddleware(req: Request, res: Response, next: NextFunction) {
    console.log(req.cookies);
    const cookies: any = req.cookies;
    if (cookies && cookies.Authorization) {
        const pubKey: string | Buffer = fs.readFileSync("./server.public.key", "utf8");
        try {
            let verifyOptions: any = {
                algorithm: ["RS256"]
            };
            const tokenPayload: TokenPayload = jwt.verify(cookies.Authorization, pubKey, verifyOptions) as unknown as TokenPayload;
            const _id: string = tokenPayload._id;
            const user: UserInterface | null = await User.findById(_id);
            if (user) {
                req.user = user;
                next();
            } else {
                next(new AuthTokenException())
            }
        } catch (error) {
            next(new AuthTokenException());
        }
    } else {
        next(new AuthTokenException());
    }
}

Login from client (first request)

export const login = createAsyncThunk(
    "auth/login",
    async (loginData: LoginData, thunkAPI: any) => {
        try {
            const { email, password } = loginData;
            //config, data, headers, request, status, statusText
            //{ data: resData, headers: resHeaders } 
            const { data: resData, headers: resHeaders } = await axios.post<LoginResponse>(
                "http://localhost:4000/login",
                {
                    email: email,
                    password: password,
                },
            );
            console.log(resData);
            console.log(resHeaders);
            return resData;
        }
        catch (error: any) {
            console.log(error.message);
            console.log(thunkAPI.rejectWithValue(error.message));
            return thunkAPI.rejectWithValue(error.message);
        }
    }
)

Are there some headers I need to set when I send the new request in handleClick ?

Since you're sending credential, you will need to specify your url and enable the credential, you cannot use "*"

const corsOptions = {
    origin: "http://localhost:3000", // or your exact frontend URL
    methods: "GET, POST, PUT, DELETE, OPTIONS, HEAD",
    credentials: true,  // this is for cookie
};

app.use(cors(corsOptions));

You don't have to enable credential on your first request since you only try to login, and you re not sending any cookie for the first time. You can check their documentation for more detail https://github.com/expressjs/cors

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM