Reseting password issue in Node.js with JWT - node.js

I am facing an issue with reseting password when users forgetting their passwords.
So lets say my Frontend is published in IP say 12.12.12.12
And my Backend services are running in 12.12.12.12:3000/api
So a user is forgetting the password and clicks on forget-password button which calls the
following service:
POST - 12.12.12.12:3000/api/forgotpassword
body: email address
After controlling the email, a link like this:
GET - 12.12.12.12:3000/api/resetpassword?token={token}
is sent to provided email.
So the problem starts now. How would you open the frontend when this link is clicked?If the token is not expired and valid.
Is it a good idea to use redirect in here? lets say I redirect to reset password page like:
12.12.12.12/resetpassword
But in here how I add the token at the end? otherwise everyone will have access to this page.
Hope I managed to explain the issue.
One last issue is
res.redirect(/resetpassword) ---> 12.12.12.12:3000/api/resetpassword (doesn't open page)

the back-end url is not going to be exposed to user, you just send front-end password recovery page url and pass a token as get parameter.
reset page without parameter can be used to request recovery email and page with get parameter can be used to check the token with back-end to authenticate user and show it field.

Related

How to login from central domain to subdomain in angular using JWT?

I want to implement a feature in which there is a central login site lets say: https://example.com , and when user enter login credentials in this page and select from dropdown on which sub domain user wants to log into, the user gets logged into that subdomain like https://abc.example.com.
I am using MEAN stack and jwt token for authentication. JWT implementation is applied in standard way in which first: request is sent to "/authenticate" and then token is returned which will be stored in browser local storage.
I have successfully done one site authentication ie. login from https://example.com and logging user in that domain, but now I want to implement like this flow =>
On login page of https://example.com :
User can select an option from drop down in which subdomain to login
After that user enters login credentials ( these credentials can be different or same for all subdomains )
User gets redirected to dashboard page of that subdomain ( with JWT token stored in the local storage of that selected sub domain )
Above is the flow I want to be implemented but can be changed if other flow achieves the same result
I have searched questions and blogs regarding this topic:
I have gone through SSO ... but that is not what exactly I want; because SSO is like login in one subdomain and it gets logged in everywhere else... but I want to login from a single login page to subdomain's dashboard page based on user selection.
How I have thought of implementing this (not working) :
I will first send "/authenticate" request to https://example.com with parameter like
{ username: "alice", password: "****", subDomainUrl: "https://abc.example.com"}
My nodejs backend will authenticate and return me the JWT token. Now I will redirect to that subdomain(https://abc.example.com) and send this token from https://example.com to https://abc.example.com and somehow it will get stored in this subdomain's(https://abc.example.com) localstorage. After it is stored in local storage I can easily do my other work.
So how to implement this? Is the above approach practical; if then how to properly do it? What is the best way to implement these kind of architectures? Any help will be great, Thanks!
I suggest you first send /authenticate request from https://example.com/.
It will be validated by nodejs backend and then generate JWT token and redirect to the new subdomain including token.
http.get('*',function(req,res){
res.redirect('https://abc.example.com?token='+JWTtoken);
})
You can fetch the token from the subdomain and store in your local storage. Further, you can use this token for your api authentication.

Is this password-less auth flow secure?

I'd like to implement a passwordless auth flow for my mobile app that only requires a user clicking a link in their email to log in. Similar to how Slack handles auth. I'll be using node and jwt for this implementation.
I think I've come up with a secure design, but I'm sure I'm missing something. I would love some critique from the community 🙏.
Here we go:
User opens the mobile app.
We check to see if user has a token in their local storage.
If they do, we add that token to their headers and send to the home page of the app.
Else, we prompt them to enter their email to get started
When they click "Submit", we POST that email address to the requestMagicLink endpoint on our server.
The server checks the database for a user with that email address
If we find a user with that email, we take the id from that user
If the user does not exist, we create a new user, and get that id
We use JWT to generate a token with the id, and our secret that expires after 1 hour
We send that token to the user via a link in an email.
Upon being clicked, that link sends a GET request to our server at the magicLogin endpoint with the token in a query param
We verify that the token is correct using JWT and our secret.
If it fails verification, we redirect the user to the screen where we prompt them with their email to get started.
If it's successful, we generate a new JWT token using their id, and our secret that doesn't have an expiration, then pass that back to the user in the params of a URL that redirects them to a success page in our app.
The app takes the token from the param and stores it in local storage until the user chooses to logout, and the user is redirected to the home page.
The requests to the api all now contain the token in the headers, and the user is good to go.

Steam authentication API, passing data back to Angular

I have this problem with Express(NodeJS)/Angular web app where I rely on Steam's login authentication. Essentially when the user clicks "Login" he's redirected to the Steam authentication(Steam's website), once logged in the user is redirected back to a specific route on my backend called /verify. Once the user hits /verify there are session variables containing necessary user data to access. Therefore I use JWT to generate a token with this data to send back to the client(Angular in this case).
The problem is sending this token back to the frontend(the client) to save in local storage.
Any help is highly appreciated! Currently, I pass the token via a query string with a redirect back to the frontend, but this doesn't seem like a good solution.
Maybe I should stick to server-side sessions and write HTTP routes to GET user data. The problem with this approach is once again the client is completely unaware when the user authenticates himself on the backend, since the only callback is triggered is on the backend.
EDIT:
Tried another approach, however once again unsure of it's the right way to go both code-wise and security-wise.
Redirect the user to the Steam authentication page.
Wait for the authentication callback on server side, in my case it hits the route '/verify'.
Once at /verify the session cookie is already set, therefore I redirect the user back to my Angular app to a specific route called '/login'.
On /login the user requests a token based on the session cookie on the server, the token in my case is a JSON Web Token(JWT).
Once the token is saved in local storage I simply redirect the user to any page in my Angular app.
If this is the wrong way to do it, please let me know!

SAML2.0 Authentication with Node.js and SPA

I've been scratching my head for about 2 days on how to solve what seemed to be a simple task, but it's starting to drive me crazy.
I have an application where users will use SAML 2.0 to authenticate.
I have a react-application set up for the front-end, and was thinking I was gonna use JWT to secure the rest-api communication between front-end and backend.
When a user signs in, the flow is the following:
User accesses www.server.com/ and gets served the static HTML with react-application
User clicks 'Sign in' and accesses www.server.com/login
passport-saml redirects user to saml identity provider. User logs in.
User calls back to www.server.com/callback with a SamlResponse in the req.body which is decoded by passport-saml and put into req.user.
If the user doesn't already exist, I create the user in the database.
I create a JWT.
What should I do next? The problem is that the user is not in the react-application when calling back from the identity provider, so I've lost all state in the application, so whatever I reply with will get sent to the browser.
Is there any way I could force the browser to give me the SamlResponse which the identityprovider is calling back with? Then I could send it to the server as a http-request from the react-application.
After some thinking, I came up with the following solution which worked quite nicely for me.
SAML has something called RelayState which is a property that the Service Provider has to respond with. So now the process looks like this:
User accesses http://frontendserver.com and gets server the static page with the React application (not signed in.).
User clicks 'Login' and gets redirected to http://backendserver.com/login/?RelayState=http://frontendserver.com which authenticates via passport-saml and redirects user to SP. So I pass the origin of the request in RelayState.
User calls back to http://backendserver.com/callback with the SamlResponse, which includes the RelayState.
I create a token, and redirect the user to RelayState/#token.
I can then parse the url in the React application, and add the token as a header for any further requests.
This might've seemed like the obvious way to do it, but it took me quite a while to figure out that this would work.
I know this question is for Node backend, but I found an article of the implementation for a PHP/Apache webserver backend here and I think it can help someone trying to understand the flow of the process of how this type of thing works.

Facebook login flow with to nodejs

I am working on a REST API backend service for an app that uses both email and facebook login. Lets just pretend this app is a todo list app and a user can sign in and add notes which they could later view on may different devices.
The "Login with email" is pretty simple, the app would make a request to:
URL: /v1/login
Params: email, password
Then the serivce returns an access token if all this information is correct so we know the identity of the user creating, updating or deleting a note/list item.
Now for the facebook side. I've seen several differnet answers all over StackOverflow and Facebook's documentation. Some people say, just pass in the id and login the user with the matching id. This would mean calling the login function from the Facebook SDK and just keeping that id to send in a request.
URL: /v1/login/facebook
Params: id
That would work but seems highly unsecure. Anyone could get someone else's Facebook id and just send a request to the server. Facebook's documentation mentions also using the account email. We'll what if the user ever changes their email on Facebook, they could never login to this app again. Another hint of security would be passing in the token from Facebook every time. Since those tokens can change or expire, there really wouldn't be a way login past the expiration date.
The final method I know of would be passing in the app secret:
URL: /v1/login/facebook
Params: id, secret
This seems by far the most secure, if you are using https to connect to the server. The downside to this method is, what if the Facebook secret token is ever reset? I mean you could always make a call to the server to request and check if token was reset and if so pass back the new one. But then if anyone had access to the endpoint to check out of date tokens, it could give them the new secret token.
I know we are dealing with the internet here and there will always be security flaws and there isn't a perfect way to do this. But what is the best way?
Try to send facebook_token for that user.
URL: /v1/login/facebook
Params: facebook_token
and service side make a service call to facebook graph api to get information about that user using facebook_token.
get the facebook id from that response and use it to provide data to that user.

Resources