Cookie is in /api route but not in 'localhost:3000' or '/' - cookies

I am working on the login system but have been stuck for a while, cookies are in the response header but not set in the application tab.
Edit: looks like cookie is being stored to path '/api'. But after setting path:'/' nothing changed.
/api/login.js
export default async (req, res) => {
if (req.method === "GET") res.send(200);
else if (req.method === "POST") {
// console.log(req.body);
const user = await loginHandler(req);
const matchPassword = await bcrypt.compare(
req.body.password,
user[0].Password
);
if (!matchPassword) {
res.send(400);
} else {
const token = jwt.sign(
{
Email: user[0].Email,
},
process.env.SECRET,
{ expiresIn: "12h" }
);
res.setHeader(
"Set-Cookie",
cookie.serialize(token, {
httpOnly: true,
maxAge: 12 * 3600 * 1000,
secure: process.env.NODE_ENV !== "development",
sameSite: "strict",
path:"/",
})
);
res.send(200);
}
}
};
login form
const headers = {
"Content-Type": "application/json",
};
const handleSubmitForm = async (enteredEmailAndPassword) => {
const user = {
...enteredEmailAndPassword,
};
await axios.post(
"/api/login",
user,
{
headers: headers,
},
{ withCredentials: true }
);
};
response header
Set-Cookie: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJFbWFpbCI6InZmdkBnbWFpbC5jb20iLCJpYXQiOjE2NTI1OTMzMzgsImV4cCI6MTY1MjYzNjUzOH0.Wsl25NglaidYnzpIrPxK6FS5nAXjUe1tK7DQQ-KVuUE=%5Bobject%20Object%5D
ETag: "3-n5rwKVhboBTgfNORDKl2z1YWBhY"
Content-Type: application/json; charset=utf-8
Content-Length: 3
Vary: Accept-Encoding
Date: Sun, 15 May 2022 05:42:18 GMT
Connection: keep-alive
Keep-Alive: timeout=5
What should I do to set cookies in the application tab?

Related

API gateway returns 502 bad gateway but I can see response cloud watch

I am performing a simple api integration which integrated with lamda and api gateway.
const axios = require('axios');
const url = require("url");
exports.handler = async (event, context) => {
// TODO implement
var maxRJ = event.queryStringParameters.maxResults;
var jiraLabelJ = event.queryStringParameters.labels;
var statusJ = event.queryStringParameters.status;
const config = {
headers: {
"Accept": "application/json",
"Accept-Encoding": "gzip,deflate,compress",
"Authorization": "XXXXXXXX"
}
};
const queryParams = {
jql: "status="+statusJ+" AND labels="+jiraLabelJ+"",
maxResults: maxRJ,
};
const params = new url.URLSearchParams(queryParams);
console.log(params);
const output = axios.get(`apiURL?${params}`, config)
.then(response => {
return(JSON.stringify(response.data));
})
.catch(error => {console.error(error)
return(JSON.stringify(error));
});
return output;
};
The above lamda is integrated with api gateway with LAMBDA_PROXY . But while testing the api gateway integration I can see the api response but api gatway returns 502
Response Body
{"message": "Internal server error"}
Wed Dec 14 15:29:17 UTC 2022 : Execution failed due to configuration error: Malformed Lambda proxy response
Wed Dec 14 15:29:17 UTC 2022 : Method completed with status: 502
.
Output/test integration shows the log-
Wed Dec 14 15:29:17 UTC 2022 : Endpoint response body before transformations: {api response}
You are returning a response before your promise resolves.
You should await your API call and return a proxy response as #AnkushJain commented.
const axios = require('axios');
const url = require("url");
exports.handler = async (event, context) => {
// TODO implement
const maxRJ = event.queryStringParameters.maxResults;
const jiraLabelJ = event.queryStringParameters.labels;
const statusJ = event.queryStringParameters.status;
const config = {
headers: {
"Accept": "application/json",
"Accept-Encoding": "gzip,deflate,compress",
"Authorization": "XXXXXXXX"
}
};
const queryParams = {
jql: "status="+statusJ+" AND labels="+jiraLabelJ+"",
maxResults: maxRJ,
};
const params = new url.URLSearchParams(queryParams);
console.log(params);
try {
const output = await axios.get(`apiURL?${params}`, config)
return {
statusCode: 200,
body: JSON.stringify(output.data)
}
} catch(error) {
console.error(error)
return {
statusCode: 500,
body: JSON.stringify({
message: error.message
})
}
}
};
jql: "status="+statusJ+" AND labels="+jiraLabelJ+"",
This is a security concern. Don't put user provided inputs directly into your JQL statement.

Undefined cookies

when I do request with postman code works, but from the front it doesn't.
Problem with undefined oldRefreshToken when I do request from front.
But I don't know why it parse cookies from postman and does not from front :(
Server login part:
#Public()
#Post('login')
#HttpCode(HttpStatus.OK)
async signinLocal(
#Body() dto: AuthDto,
#Res({ passthrough: true }) response: Response,
): Promise<any> {
const tokens = await this.authService.signinLocal(dto);
response.cookie('refreshToken', tokens.refreshToken, {
maxAge: 30 * 24 * 60 * 60 * 1000,
httpOnly: true,
});
return { accessToken: tokens.accessToken };
}
Server refreshToken part:
#Public()
#UseGuards(RefreshTokenGuard)
#Post('refresh')
#HttpCode(HttpStatus.OK)
async refreshTokens(
#GetCurrentUser('sub') userId: number,
#Req() request: Request,
#Res({ passthrough: true }) response: Response,
): Promise<string> {
const oldRefreshToken = request?.cookies['refreshToken'];
const tokens = await this.authService.refreshTokens(
userId,
oldRefreshToken,
);
response.cookie('refreshToken', tokens.refreshToken, {
maxAge: 30 * 24 * 60 * 60 * 1000,
httpOnly: true,
});
return tokens.accessToken;
}
Frontend part:
const response = await fetch("http://localhost:3001/auth/refresh/", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + token,
},
});
Maybe you can't access the token in the frontend, because it's http only (wich means no javascript in the frontend can access the cookie)

Graphql Apollo setting cookies is dont working

I'm trying to set cookies in apollo client.
I'm setting the response cookie which works fine, also working on graphql playground with setting "request.credentials": "same-origin", or "include" and it stores cookies successfully.
My problem starts when I'm trying to store cookies from FE app (React, Apollo client). When i put the credentials: "same-origin" the app is working but the cookies are not saved. And when i use "include" the queries are cors blocked.
FRONTEND
const RouterComponent: FC = () => {
const cache = useMemo(() => {
return new InMemoryCache();
}, []);
const client = useMemo(() => {
const token = localStorage.getItem('token') || 'token';
const httpLink = createHttpLink({
uri: 'http://localhost:4000/graphql',
credentials: 'include',
headers: {
authorization: token ? `Bearer ${token}` : '',
},
});
const link = from([
httpLink,
createUploadLink({
uri: 'http://localhost:4000/graphql',
}),
]);
return new ApolloClient({
link,
cache,
typeDefs,
});
}, [cache]);
return (
<ApolloProvider client={client}>
<Switch>
<Route exact path="/" component={MainPage} />;
<Route exact path="/:category" component={Category} />;
</Switch>
</ApolloProvider>
);
};
QUERY
games: (_: any, args: any, {req, res}: any) => {
const refresh_token = sign({userId: "123"}, "secret", {expiresIn: "7d"})
const access_token = sign({userId: "123"}, "secret", {expiresIn: "15min"})
res.cookie('refresh-token', refresh_token, {expire: 60 * 60 * 24 * 7}) // 7 days
res.cookie('access-token', access_token, {expire: 60 * 15}) // 15 mins
return Game.find()
}
SERVER.TS
const { ApolloServer } = require( 'apollo-server-express');
const {typeDefs} = require( './typeDefs');
const {resolvers} = require( './resolvers');
const express = require( 'express');
const cors = require( 'cors');
const path = require( 'path');
const bodyParser = require( 'body-parser');
const mongoose = require("mongoose");
const dotenv = require('dotenv');
const MONGO_CONNECTION = ""
const app = express();
export default (async function () {
try {
await mongoose.connect(MONGO_CONNECTION, {
useNewUrlParser: true,
useUnifiedTopology: true})
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req, res }: any) => {
return {
req,
res
};
},
});
const corsConfig = {
origin: '*',
credentials: true,
allowedHeaders: ['Content-Type', 'Authorization'],
};
dotenv.config();
app.use(function (req: any, res: any, next: any) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/images', express.static(path.join(__dirname, 'images')));
const dir = path.join(process.cwd(), 'images');
app.use(express.static(dir));
app.use(express.static('public'))
app.use(express.static('files'))
server.applyMiddleware({ app, cors: corsConfig });
app.listen({ port: 4000 }, () =>
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
)
} catch (err) {
console.error(err);
}
})();
thank you for any help

Set Session ID Cookie in Nuxt Auth

I have the following set up in my nuxt.config.js file:
auth: {
redirect: {
login: '/accounts/login',
logout: '/',
callback: '/accounts/login',
home: '/'
},
strategies: {
local: {
endpoints: {
login: { url: 'http://localhost:8000/api/login2/', method: 'post' },
user: {url: 'http://localhost:8000/api/user/', method: 'get', propertyName: 'user' },
tokenRequired: false,
tokenType: false
}
}
},
localStorage: false,
cookie: true
},
I am using django sessions for my authentication backend, which means that upon a successful login, i will have received a session-id in my response cookie. When i authenticate with nuxt however, i see the cookie in the response, but the cookie is not saved to be used in further requests. Any idea what else i need to be doing?
This is how I handled this, which came from a forum post that I cannot find since. First get rid of nuxt/auth and roll your own with vuex store. You will want two middleware, one to apply to pages you want auth on, and another for the opposite.
This assumes you have a profile route and a login route that returns a user json on successful login.
I'm also writing the user to a cookie called authUser, but that was just for debugging and can be removed if you don't need it.
store/index
import state from "./state";
import * as actions from "./actions";
import * as mutations from "./mutations";
import * as getters from "./getters";
export default {
state,
getters,
mutations,
actions,
modules: {},
};
store/state
export default () => ({
user: null,
isAuthenticated: false,
});
store/actions
export async function nuxtServerInit({ commit }, { _req, res }) {
await this.$axios
.$get("/api/users/profile")
.then((response) => {
commit("setUser", response);
commit("setAuthenticated", true);
})
.catch((error) => {
commit("setErrors", [error]); // not covered in this demo
commit("setUser", null);
commit("setAuthenticated", false);
res.setHeader("Set-Cookie", [
`session=false; expires=Thu, 01 Jan 1970 00:00:00 GMT`,
`authUser=false; expires=Thu, 01 Jan 1970 00:00:00 GMT`,
]);
});
}
store/mutations
export const setUser = (state, payload) => (state.user = payload);
export const setAuthenticated = (state, payload) =>
(state.isAuthenticated = payload);
store/getters
export const getUser = (state) => state.user;
export const isAuthenticated = (state) => state.isAuthenticated;
middleware/redirectIfNoUser
export default function ({ app, redirect, _route, _req }) {
if (!app.store.state.user || !app.store.state.isAuthenticated) {
return redirect("/auth/login");
}
}
middleware/redirectIfUser
export default function ({ app, redirect, _req }) {
if (app.store.state.user) {
if (app.store.state.user.roles.includes("customer")) {
return redirect({
name: "panel",
params: { username: app.store.state.user.username },
});
} else if (app.store.state.user.roles.includes("admin")) {
return redirect("/admin/dashboard");
} else {
return redirect({
name: "panel",
});
}
} else {
return redirect("/");
}
}
pages/login- login method
async userLogin() {
if (this.form.username !== "" && this.form.password !== "") {
await this.$axios
.post("/api/auth/login", this.form)
.then((response) => {
this.$store.commit("setUser", response.data);
this.$store.commit("setAuthenticated", true);
this.$cookies.set("authUser", JSON.stringify(response.data), {
maxAge: 60 * 60 * 24 * 7,
});
if (this.$route.query.redirect) {
this.$router.push(this.$route.query.redirect);
}
this.$router.push("/panel");
})
.catch((e) => {
this.$toast
.error("Error logging in", { icon: "error" })
.goAway(800);
The cookie is sent by the server but the client won't read it, until you set the property withCredentials in your client request (about withCredentials read here)
To fix your problem you have to extend your auth config with withCredentials property.
endpoints: {
login: {
url: 'http://localhost:8000/api/login2/',
method: 'post'
withCredentials: true
}
}
Also don't forget to set CORS policies on your server as well to support cookie exchange
Example from ExpressJS
app.use(cors({ credentials: true, origin: "http://localhost:8000" }))
More information about this issue on auth-module github

Trying to get then send a cookie using react and fetch

I've been trying to implement some authentication component in my app for a few hours now, and I still don't understand some of the things that are happening.
Basically, I'd like to send a POST request containing some credentials to my API, which sends me a cookie back with a token if the credentials worked. Then, the cookie should be included in the headers of all future requests to my API (which I believed was automatic).
server.js (my API is a mockup for now, with JSON files)
...
app.post('/api/login', jsonParser, (req, res) => {
fs.readFile(ACCOUNTS_FILE, (err, data) => {
if (err) {
console.error(err);
process.exit(1);
}
const accounts = JSON.parse(data);
const credentials = {
email: req.body.email,
password: req.body.password,
};
var token = null;
for (var i = 0; i < accounts.length; ++i) {
const account = accounts[i];
if (account.email === credentials.email
&& account.password === credentials.password) {
token = account.token;
break;
}
}
if (token) {
res.setHeader('Set-Cookie', `access_token=${token}; Secure; HttpOnly;`);
res.json({ token });
} else {
res.json({ token: null });
}
});
});
...
app.js
...
handleConnection(e) {
e.preventDefault();
const email = this.state.email.trim();
const password = this.state.password.trim();
if (!email && !password) {
return (false);
}
fetch(loginUrl, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
credentials: 'include',
},
body: JSON.stringify(this.state),
})
.then((response) => response.json())
.then((data) => {
console.log(data);
})
.catch((error) => {
console.warn(error);
});
return (true);
}
...
Now the console.log(data) always displays my token (or null if my credentials are wrong), but the cookie thing doesn't work...
See, I receive the Set-Cookie header, but I still have no cookie on my page.
And even if I managed to get the cookie, when I try to create a cookie using document.cookie = "access_token=123"; and then send the request again, my cookie doesn't go in my header like it would with a jQuery Ajaxcall :
I read here that adding credentials: 'include' would save the day, but unfortunately it didn't.
What am I missing here?
Thanks in advance!
I had the same problem and I found the answer in Peter Bengtsson's comment here: https://davidwalsh.name/fetch
If I understood, in your case the fetch should be:
fetch(loginUrl, {
credentials: 'same-origin',
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(this.state),
})