Creating a login with AWS cognito and javascript - javascript

I am creating a login page. The idea is to take the username and password then use that to get an id token from AWS cognito user pool.
Then I need to store the token in a database and transfer that token to index.html along with the username. This is because index.html needs the token to make a post request to an API gateway using the same id token and it needs to know the user name to keep track of which user is currently logged in.
Now the index.html has to check if the token transferred to it matches the token in the database or not.
If it does and the token is not expired, then there is no redirection, otherwise, the index.html redirects to login.html.
The problem is my back-end completely relies on Amazon Lambda functions and API gateways because my company does not want me to use any back-end language. Now, I found that lambda functions could not set browser cookies nor read browser cookies.
This left me no choice but to use javascript cookies, sessions and local storage to transfer the token and username to index.html. However, this approach is considered to be insecure.
There aren't any tutorials on a secure login system using cognito.
Note: Any other secure login system will do the work, but remember I need to pass username and password to user pool to get an ID token which means, if I use any other login method, then I would now need to pass username and password both to index so that index can make a request to user pool to get an id token and make a request to the API gateway.
Now my question is, is there a way to actually transfer data to index from login without compromising security? Can I use lambdas in any other way to transfer the tokens?
Please help. Thanks in advance.

Now, I found that lambda functions could not set browser cookies nor read browser cookies.
I don't think this is strictly true.
Using Lambda Proxy Integration gives your Lambda function visibility into and control over many aspects of the HTTP request. This includes setting and reading arbitrary headers (including set-cookie).
To demonstrate, you can set a function like this up and attach an API Gateway trigger (with Lambda Proxy Integration enabled) to it:
exports.handler = (event, context, callback) => {
var returnobj = {
"statusCode": 200,
"headers": {
"Content-Type": "application/json", "access-control-allow-origin": "*",
"Set-Cookie": "testcook=testval; path=/; domain=xxxxxxxxxx.execute-api.us-east-1.amazonaws.com; secure; HttpOnly"
},
"body": JSON.stringify({})
};
console.log("headers", event.headers.Cookie);
callback(null, returnobj);
};
This function returns a Set-Cookie header that the browser will respect and send along with future requests to this domain. If you hit this in a browser twice, you'll see the cookie sent by the browser and logged by the lambda on the second request.
If you aren't willing to use Lambda Proxy Integration, you can probably still pull this off by mapping part of your Lambda response to a header in API Gateway.

Related

How can I safely implement my login routes?

I am currently making a login and registration system as a project for a website, but I am uncertain of how I can safely implement the routes/logic for it. Currently, in my client side code I send a fetch request to my login or register route, and do the logic there, and then send a JSON object back, which is manipulated whether there is an error or not, and I have implemented CORS and Header (Origin and Referrer headers) authorization middleware within my POST routes, so no external script can mass produce users/login [aka brute force]. Is there another safer and better way of handling this?
What you want to do is, to use either JWT or Session Cookies.
Algorithm ->
User visits the /login page
User enters user id and password
U send a fetch or Axios request to your servers POST API route
axios(`/<api_route_here>`,{
method: "POST",
headers: {
Authorization: `Basic ${btoa(`${username}:${password}`)}`
}
})
In the above code, we are encoding the username and password with base64 and then sending them back to the server with the Authorization header. username:password
Note: Make sure u are using an HTTPS connection
In the server u decode the Authorisation value from the header. Then create a hash of the password with username as its salt. Then query your database if the hash matches the user's password's hash.
We are hashing here to prevent leaking passwords in case of a database hack.
It is obvious, that you will store the password for the user using the same hashing technique.
If the query is positive then send a 200 response else send a 401.
In the Axios promise resolution check for the headers status code to figure out if the sign-in was successful
To prevent asking the user their password every time. U must use session cookies. i.e in step 4 if the password is correct add a Set-Cookie header property with a session token value. Store that session token to your database. Next time you API is hit, check for the cookie. if the cookie exists then check that session token with your database. otherwise, send a 401
To prevent route spamming, implement a captcha.

Hide JWT token in Javascript

I've implemented a JWT authentication for my rest api.
I'm struggling to understand how to hide the token in JavaScript.
For example, all the clients (web browser and mobile phone app) will call my api with an header:
Authorization': 'Bearer eyJ0eXAiOXXXXXXX
In PHP it makes sense, but in JavaScript "everyone" can see the token. So what's the point of having one?
Even if the token expires after X minutes, all you need to do is get the new token every X minutes, and you have access to the same API.
Did I miss something?
Of what I have understand of Token, they are used to help the server to know 'who is sedding this request' and if this person has the right to.
they are made for simplification of this process, not for security.
If you don't use Token, I think, that means you have to send and check password at each request.
But yes, the information inside is not hidden, as you read Here:
Do not put secret information in the payload or header elements of a JWT unless it is encrypted
I know that you can encrypt your token, but I've never done this, so I can't say much about it.
A solution is using SSL/HTTPS for security.

How to know if user is loggedin in with passport.js across subdomains

I have created two Mean.io apps in domain.com and in sub.domain.com respectively and everything works as expected in both but the problem is that the one in the subdomain (sub.domain.com) needs to know if the user is logged in the main app (domain.com).
I know that passport handles sessions and knows if user is logged in because it creates an user object in req for every request in express.js:
if (req.user) {
// logged in
} else {
// not logged in
}
The inconvenient here is that this approach works from within the domain but not outside. In other words, if I make a request to backend like this:
$http.get('/api/users/me').success(this.onIdentity.bind(this));
from domain.com, this will be populated with user data, but if I make the same request directly from the browser, for example, it returns null.
I need to understand how could I pass this information across domains? And if everytime this request $http.get('/api/users/me').success(this.onIdentity.bind(this)); is made, information is passed to backend?
I found the answer after some deep research.
Short answer: it is impossible using localStorage (data is only accesible by domain; not even for subdomains), which is the tool Mean.io now uses to store user information.
Long answer, every time, as long as you are logged in, you send a request to backend, angular intercepts the request before actually send it (this post explains this https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/) and adds an authorization header like this:
headers:
{
...
authorization: 'Bearer eyJhbGciOiJIUzI1NiJ9.JTdCJTIyX2lkJTIyOiUyMjU1ZDFjYmIxNDA..._rUsUBFxCQy3qqUGi9QGVD0YXCEk0',
...
}
which passport later employs to serialize user info into session and put it in req.user. The Bearer token is stored in localStorage and for that reason it's impossible to get it from outside the domain. The only way I came up with was with cookies with domain = '.domain.com' so that every subdomain could read those cookies.

How to store the access_token gained from OAuth for later use?

I'm attempting to get and store an access token from the Pocket API using Node.js. I am able to get the request token, redirect to the Pocket login page, redirect back to my site, and finally able to exchange the request token for an access token.
But that's where my problem lays. I don't know how I should go about actually storing the token, and without it I am unable to make API calls (of course). Here's the relevant code:
//called when Pocket API redirects back to /getAccessToken
function getAccessToken(response, requestToken) {
restler.post("https://getpocket.com/v3/oauth/authorize", {
headers: { "Content-Type" : "application/json",
"X-Accept" : "application/json" },
data : JSON.stringify({consumer_key:CONSUMER_KEY,code:requestToken})
}).on("complete", function(data, res) {
if(res.statusCode == 200) {
var accessToken = data.access_token;
console.log("Access granted: " + accessToken);
//BUT HOW DO I STORE THE ACCESS TOKEN FOR USE OF API CALLS ??
}
response.writeHead(307, {Location: DNS}); //go back to site
response.end();
});
};
I was thinking I should store the accessToken on the client side, but I don't actually know how to go about doing that. I've tried using cookies, but that didn't seem to work. Of course, I may have just implemented them wrong.
Your help is much appreciated.
How you store the access token usually depends on where you will be using the API.
I usually like to persist tokens in the database (like MongoDB) on the User document they are associated with, and then my web client can ping my server (via a RESTful endpoint) if it needs the token for anything. This way if the user clears all that state on the browser you don't have to go through the entire OAuth flow again.
you should probably make the cookies thing work. option 2 is to use localStorage but if you're struggling with cookies i wouldn't try going down that path - it gives you more control of when the tokens are sent across the wire but also requires a lot more work to make your serverside and clientside code coordinate.

Google Javascript API: What happen after access token expire?

I have a client-side web app (no backend) that uses Google Javascript API.
I have an issue regarding the access-token that I got after the login is successful.
From the callback, we can see that the access-token is set to expire in 1 hour.
expires_in: "3600"
Question is, how can I "get a new token"?
From the documentation, I'm under the impression that after the token is invalid, we have to (and I quote) perform a new re-authorization flow with immediate set to true to get an up-to-date access token.
Source:
https://developers.google.com/+/web/api/javascript
However, when I tried to call again the auth method:
gapi.auth.authorize(parameters, callback)
I got the token object, but there's no access-token inside.
{
client_id: "{my_client_id}.apps.googleusercontent.com"
cookie_policy: undefined
expires_at: "1370371466"
expires_in: "86400"
g_user_cookie_policy: undefined
issued_at: "1370285066"
response_type: "token"
scope: "https://www.googleapis.com/auth/plus.login https://gdata.youtube.com"
}
Am I missing something? How do we usually get a refreshed token after one expired?
On client side, access token is temporary. This is by default online access to user resources. In order to get access tokens again, you need to redirect user for permissions again.
In the OAuth protocol, your app requests authorization to access resources which are identified by scopes, and assuming the user is authenticated and approves, your app receives short-lived access tokens which let it access those resources, and (optionally or more precisely on server side) refresh tokens to allow long-term access.
for server side apps and for offline access of user resource you need to have refresh token Refer to: Google Analytics API Automated Login
Also read: https://developers.google.com/accounts/docs/OAuth2WebServer
https://developers.google.com/accounts/docs/OAuth2UserAgent

Categories