Hi, I am trying to protect selective branches from traffic redirecting unauthorized users to another login site. I have enabled Netlify Identity on Login Site, invited myself and gave reviewer
role to my user. Then I have created simple script to write _redirects
file based on custom logic/branches, ending up with this:
/* /index.html 200! Role=reviewer
/* https://XXXX.netlify.app/login?site=https://deploy-preview-564--XXXX.netlify.app/:splat 302!
Then in Login Site I made a simple login which returns me Netlify Identity session with access_token
and so on. I use that token to generate a cookie:
const cookie = require('cookie');
exports.handler = (event, context, callback) => {
const {token} = JSON.parse(event.body);
const expiry = Math.floor(Date.now() / 1000) + 60 * 60;
const netlifyCookie = cookie.serialize('nf_jwt', token, {
secure: true,
path: '/',
expires: new Date(expiry.toString()),
});
const response = {
jwt: token,
exp: expiry,
};
callback(null, {
statusCode: 200,
headers: {
'Set-Cookie': netlifyCookie,
'Cache-Control': 'no-cache',
},
body: JSON.stringify(response),
});
};
After storing the cookie in users cookies I redirect user to the redirect
function:
const parseURL = require('url-parse');
const cookie = require('cookie');
exports.handler = function (event, context, callback) {
const {referer} = event.headers;
const {site} = event.queryStringParameters;
const urlData = parseURL(site);
const siteOrigin = urlData.origin;
//check that cookies are present
const {headers} = event;
const cookieHeader = headers.cookie || '';
const cookies = cookie.parse(cookieHeader);
if (cookieHeader === '' || !cookies.nf_jwt) {
const redirectToURL = referer.match(/\?site=/g) ? referer : `${referer}?site=${site}`;
return callback(null, {
statusCode: 302,
headers: {
Location: redirectToURL,
'Cache-Control': 'no-cache',
},
body: JSON.stringify({message: 'Token is not present'}),
});
}
callback(null, {
statusCode: 302,
headers: {
Location: `${siteOrigin}/.netlify/functions/set-cookie?token=${cookies.nf_jwt}&site=${site}`,
'Cache-Control': 'no-cache',
},
body: null,
});
};
This redirect invokes set-cookie
function from the Gated Site:
const cookie = require('cookie');
exports.handler = (event, context, callback) => {
const {token, site} = event.queryStringParameters;
const twoWeeks = 14 * 24 * 3600000;
const netlifyCookie = cookie.serialize('nf_jwt', token, {
secure: true,
httpOnly: true,
path: '/',
maxAge: twoWeeks,
});
const html = `
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<noscript>
<meta http-equiv="refresh" content="0; url=${site}" />
</noscript>
</body>
<script>
setTimeout(function(){
window.location.href = ${JSON.stringify(site)}
}, 0)
</script>
</html>`;
callback(null, {
statusCode: 200,
headers: {
'Set-Cookie': netlifyCookie,
'Cache-Control': 'no-cache',
'Content-Type': 'text/html',
},
body: html,
});
};
The result is redirect back to login after successful Netlify Identity login - set-cookie
returns 302
and seems like the redirect from _redirects
is triggered, like if Role
condition was not met. I have decoded the token and roles are ok. Requests sent from login action up to the redirect back to the login:
...
"app_metadata": {
"provider": "email",
"roles": [
"reviewer"
]
},
...
I went through all Netlify docs and articles about the access control and I’m stuck here. One thing I noticed is that Netlify Identity token returns app_metadata.roles
but docs about JWT access control says it should be app_metadata.authorization.roles
- I could not map the token since I have no secret from Netlify Identity.
Thanks, help would be greatly apprieciated!
Disclaimer: I can only share the site to Netlify representatives.