I'm building a small static website that I have hosted on s3. I used Cognito to get some basic user verification up and running (login, logout). I want to restrict certain parts of the website to only logged in users.
I worked through module 2 of this workshop https://github.com/aws-samples/aws-serverless-workshops/tree/master/WebApplication. In this workshop, the page /rides.html
is restricted to logged in users. If you are not logged in and try to access /rides.html
, the page will start to load, and then quickly redirect you to /signin.html
. The trouble with this is that unauthorized users can still see the rides page for a split second before redirection occurs.
Here is their code that handles redirecting a user who hasn't logged in. It is run as javascript when a user tries to access /rides.html
WildRydes.authToken.then(function setAuthToken(token) {
if (token) {
authToken = token;
} else {
window.location.href = '/signin.html';
}
}).catch(function handleTokenError(error) {
alert(error);
window.location.href = '/signin.html';
});
I am having a lot of trouble determining the best way to ensure only users who have signed in can access parts of my website. Very new to anything webdev/AWS related, and I'm having some trouble finding this information online.
Edit: To clear up what I want to achieve - I want the entire rides.html
page to be inaccessible to anyone who hasn't logged in.
Solution: We ended up putting a restricted CloudFront in front of the s3 bucket. Then, we had a lambda triggered when someone tried to access the CloudFront. Here is a tutorial: https://douglasduhaime.com/posts/s3-lambda-auth.html
I did not work through the workshop you mention, but from reading the README of module 2 I understand that they are implementing User Authentication and Registration with Amazon Cognito User Pools.
Redirecting from a site which is inaccessible is fine, you must not ensure that it is never loaded. Let me explain why:
The "sensitive" information which is displayed on the site is not static. It is loaded from a REST backend in module 4. Since the authentication is static by means of JWT, the data is never loaded from the REST backend if the user is not authenticated.
So what should the page /rides.html
do?
EDIT:
In order to restrict access to one single object in S3, you could add a bucket policy like the following one to the s3 bucket:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::<your-bucket-name>/*"
},
{
"Effect": "Deny",
"NotPrincipal": {
"AWS": "<your-user-arn>"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::<your-bucket-name>/rides.html"
}
]
}
This will make all objects public except the rides.html
file. If you want to access it, you will have to use a signed url. [1]
Please note that you must not use a bucket or object ACL which grants public access to everyone in conjunction with this approach since it might prevent the object from staying private.
I do not know if the following works because of limitations in the docs [2], but you could give it a try.
It might be possible to use a web identity federation provider in the NotPrincipal attribute: "Federated": "cognito-identity.amazonaws.com"
.
You could then narrow down which federated user has access to the rides.html
object via condition keys (e.g. cognito-identity.amazonaws.com:sub). [3]
[1] https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls.html
[2] https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notprincipal.html
[3] https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With