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)
Related
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.
I implemented a twitter login authorizer and I put an API route as the callback.
The Lambda function evoked on that route is the following:
const loginTwitterCallback = async (e, context) => {
const fetch = (...args) =>
import("node-fetch").then(({ default: fetch }) => fetch(...args));
const state = e.queryStringParameters.state;
const code = e.queryStringParameters.code;
try {
await fetch(
"https://api.twitter.com/2/oauth2/token?code=" +
code +
"&grant_type=authorization_code&client_id=" +
process.env.TWITTER_CLIENT_ID +
"&code_verifier=jwqoijoiw&redirect_uri=" + MY REDIRECT URI,
{
method: "POST",
headers: {
"Content-type": "application/x-www-form-urlencoded",
},
}
)
.then((res) => {
return res.json();
})
.then(async (data) => {
const accessToken = data.access_token;
return {
headers: {
Location:
"http://127.0.0.1:3000/auth/social?type=twitter&access_token=" +
encodeURIComponent(accessToken),
},
body: null,
statusCode: 302,
};
});
} catch (err) {
console.log(err);
}
};
Basically the user should be re-routed to the front-end where another POST request will be made to the API which will make a request to the Twitter API with the Bearer token and update the database.
The point is, I'm not being redirected to the front-end in the first place and I don't understand how to fix it.
Thanks a lot in advance.
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?
I'm trying to know how to use cookies with AWS-Lambda with the serverless framework as per this blogpost
and following is my serverless.yml code
functions:
hello:
handler: handler.hello
events:
- http:
path: /post
method: post
cors:
origin : 'https://xyz.netlify.app'
and Lambda function as per following
"use strict";
const cookie = require("cookie");
module.exports.hello = async (event) => {
const body = JSON.parse(event.body);
const name = body.name;
const value = body.value;
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "https://xyz.netlify.app",
"Access-Control-Allow-Credentials": true,
"Set-Cookie": cookie.serialize(name, value, {
expires: new Date(new Date().getTime() + 10 * 1000),
}),
},
body: JSON.stringify(
{
input: event,
},
null,
2
),
};
// Use this code if you don't use the http event with the LAMBDA-PROXY integration
// return { message: 'Go Serverless v1.0! Your function executed successfully!', event };
};
As you can notice, I already have configured the code to avoid any cors issue.
While try to send a post request as per following,
const name = document.getElementById('name')
const value = document.getElementById('value')
const post_btn = document.getElementById('post_btn')
post_btn.addEventListener('click', () => {
console.log(name.value, value.value)
const post_url = 'https://abcdxyz59t9.execute-api.ap-south-1.amazonaws.com/dev/post'
const user = {
name: name.value,
value: value.value
};
// request options
const options = {
method: 'POST',
body: JSON.stringify(user),
headers: {
'Content-Type': 'application/json'
}
}
// send POST request
fetch(post_url, options)
.then(res => res.json())
.then(res => console.log(res));
})
I do get a Set-Cookie header like below
But the cookie doesn't get saved in the browser.
That's not the case when I directly try to hit a get request with that URL without the cors in the browser. Can anyone please tell me what to do?
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