Cloudfront Lambda@edge set-cookie标头不工作
我有一个CloudFront Distribution,该发行版在Viewer请求和查看器响应中使用2 lambda@edge函数。
在该应用中,将有一个第一个请求,该请求在查询字符串上具有令牌,然后有一系列的请求,其中包含“ cookie”标题的令牌。
我根据查看器请求从“ querystring”中验证令牌。验证后,我将令牌添加到查看器响应中,作为cookie。
问题是,我可以在客户端浏览器上看到“ set-cookie”标头,但没有设置任何cookie。因此,以下请求不包括任何cookie标头。当查询字符串中没有JWT时,我需要从cookie验证令牌。
查看器请求代码:
const crypto = require("crypto");
var response401 = {
statusCode: 401,
statusDescription: 'Unauthorized'
};
exports.handler = async (event, context) => {
const request = event.Records[0].cf.request;
const key = "SECRET KEY";
const token = event.Records[0].cf.request.querystring.split("jwt=")[1];
if(!token){
console.log("Missing authorization token.");
return response401;
}
try {
jwt_decode(token,key)
} catch (error) {
console.log(error);
return response401;
}
return request;
};
function jwt_decode(token, key, noVerify, algorithm) {
// check token
if (!token) {
throw new Error("No token supplied");
}
// check segments
var segments = token.split(".");
if (segments.length !== 3) {
throw new Error("Not enough or too many segments");
}
// All segment should be base64
var headerSeg = segments[0];
var payloadSeg = segments[1];
var signatureSeg = segments[2];
// base64 decode and parse JSON
var header = JSON.parse(_base64urlDecode(headerSeg));
var payload = JSON.parse(_base64urlDecode(payloadSeg));
if (!noVerify) {
var signingMethod = "sha256";
var signingType = "hmac";
// Verify signature. `sign` will return base64 string.
var signingInput = [headerSeg, payloadSeg].join(".");
if (!_verify(signingInput, key, signingMethod, signingType, signatureSeg)) {
throw new Error("Signature verification failed");
}
// Support for nbf and exp claims.
// According to the RFC, they should be in seconds.
if (payload.nbf && Date.now() < payload.nbf * 1000) {
throw new Error("Token not yet active");
}
if (payload.exp && Date.now() > payload.exp * 1000) {
throw new Error("Token expired");
}
}
return payload;
}
function _verify(input, key, method, type, signature) {
if (type === "hmac") {
console.log(signature, _sign(input, key, method));
return signature === _sign(input, key, method);
} else {
throw new Error("Algorithm type not recognized");
}
}
function _sign(input, key, method) {
return crypto.createHmac(method, key).update(input).digest("base64url");
}
function _base64urlDecode(str) {
return Buffer.from(str, "base64").toString("utf-8");
}
和查看器响应代码,
const crypto = require("crypto");
var response401 = {
statusCode: 401,
statusDescription: 'Unauthorized'
};
exports.handler = async (event, context) => {
try {
const response = event.Records[0].cf.response;
const token = event.Records[0].cf.request.querystring.split("jwt=")[1];
const headers = response.headers;
const headerNameSrc = 'X-Amz-Meta-Last-Modified';
const headerNameDst = 'Last-Modified';
if (headers[headerNameSrc.toLowerCase()]) {
headers[headerNameDst.toLowerCase()] = [{
key: headerNameDst,
value: headers[headerNameSrc.toLowerCase()][0].value,
}];
console.log(`Response header "${headerNameDst}" was set to ` +
`"${headers[headerNameDst.toLowerCase()][0].value}"`);
}
const cookie = `token=${token}; Secure; HttpOnly; Max-Age=18000; SameSite=None`;
response.headers['set-cookie'] = [{
key : "set-cookie",
value : cookie
}];
return response;
} catch (error) {
console.log(error);
return response401;
}
};
所以我该如何解决问题?是否缺少CloudFront配置?
I have a CloudFront distribution which uses 2 Lambda@Edge functions at Viewer Request and Viewer Response.
In the app, there will be a first request which has a token at query string, and following series of requests which has the token at "cookie" header.
I validate the token from "querystring" at viewer request. After validation, I'm adding the token to Viewer Response as a cookie.
The problem is, I can see the "set-cookie" header at client browser, but it doesn't set any cookies. Thus, the following requests doesn't include any cookie headers. I need to validate the token from cookie when there is no jwt in query string.
Viewer Request Code:
const crypto = require("crypto");
var response401 = {
statusCode: 401,
statusDescription: 'Unauthorized'
};
exports.handler = async (event, context) => {
const request = event.Records[0].cf.request;
const key = "SECRET KEY";
const token = event.Records[0].cf.request.querystring.split("jwt=")[1];
if(!token){
console.log("Missing authorization token.");
return response401;
}
try {
jwt_decode(token,key)
} catch (error) {
console.log(error);
return response401;
}
return request;
};
function jwt_decode(token, key, noVerify, algorithm) {
// check token
if (!token) {
throw new Error("No token supplied");
}
// check segments
var segments = token.split(".");
if (segments.length !== 3) {
throw new Error("Not enough or too many segments");
}
// All segment should be base64
var headerSeg = segments[0];
var payloadSeg = segments[1];
var signatureSeg = segments[2];
// base64 decode and parse JSON
var header = JSON.parse(_base64urlDecode(headerSeg));
var payload = JSON.parse(_base64urlDecode(payloadSeg));
if (!noVerify) {
var signingMethod = "sha256";
var signingType = "hmac";
// Verify signature. `sign` will return base64 string.
var signingInput = [headerSeg, payloadSeg].join(".");
if (!_verify(signingInput, key, signingMethod, signingType, signatureSeg)) {
throw new Error("Signature verification failed");
}
// Support for nbf and exp claims.
// According to the RFC, they should be in seconds.
if (payload.nbf && Date.now() < payload.nbf * 1000) {
throw new Error("Token not yet active");
}
if (payload.exp && Date.now() > payload.exp * 1000) {
throw new Error("Token expired");
}
}
return payload;
}
function _verify(input, key, method, type, signature) {
if (type === "hmac") {
console.log(signature, _sign(input, key, method));
return signature === _sign(input, key, method);
} else {
throw new Error("Algorithm type not recognized");
}
}
function _sign(input, key, method) {
return crypto.createHmac(method, key).update(input).digest("base64url");
}
function _base64urlDecode(str) {
return Buffer.from(str, "base64").toString("utf-8");
}
And the Viewer Response Code
const crypto = require("crypto");
var response401 = {
statusCode: 401,
statusDescription: 'Unauthorized'
};
exports.handler = async (event, context) => {
try {
const response = event.Records[0].cf.response;
const token = event.Records[0].cf.request.querystring.split("jwt=")[1];
const headers = response.headers;
const headerNameSrc = 'X-Amz-Meta-Last-Modified';
const headerNameDst = 'Last-Modified';
if (headers[headerNameSrc.toLowerCase()]) {
headers[headerNameDst.toLowerCase()] = [{
key: headerNameDst,
value: headers[headerNameSrc.toLowerCase()][0].value,
}];
console.log(`Response header "${headerNameDst}" was set to ` +
`"${headers[headerNameDst.toLowerCase()][0].value}"`);
}
const cookie = `token=${token}; Secure; HttpOnly; Max-Age=18000; SameSite=None`;
response.headers['set-cookie'] = [{
key : "set-cookie",
value : cookie
}];
return response;
} catch (error) {
console.log(error);
return response401;
}
};
So, how can I solve the problem? Are there any missing CloudFront configuration?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论