Receiving an email on localhost (kubernetes pod) - javascript

I have a following issue:
I'm writing an integration test (cypress) for resetting password. The issue is, that right now I send the url (with key needed to reset the password) to users email. Email must be real (so eg. something#something.comething).
I wanted to use something like mailhog for this sake, but I don't think it's possible in this case, since I send api request from frontend to backend with en email that requested password change, then backend sends a message to this email address with the url (so I can't do it directly from frontend and I'd like to avoid backend changes in this case).
Is there some service, that I could use, that would eg. run in kubernetes pod or just straight on localhost, to "pretend" to be a real email, so I could signup with it and then reset the password for it? It must have some api, that would allow me to get the email value (for the sake of getting the url with reset key).

Related

Elrond Verify Signature on Backend PHP

I have a dApp where you login with your Elrond wallet and you generate a signature (containing the wallet address and some more data).
While making requests to an endpoint, I pass the signature on payload and I need to verify it on the backend (so you can't change the wallet address and make requests on someone else's behalf).
I am using PHP with Laravel Framework.
How can I verify the signature on the backend and get the wallet address?
i've written a Laravel SDK for Elrond that can help you with that, or you can copy the logic from: https://github.com/Superciety/elrond-sdk-laravel
note: it's still work in progress & mostly undocumented - i'd welcome any contributions
to verify signatures coming from your dapp, you'd use it this way:
$isValid = Elrond::crypto()->verifyLogin($token, $signature, $address);
where $token is an arbitrary string unique to the user's session to avoid replay

Authenticate requests from frontend that doesn't have tokens

Not sure if the title summarises my question well.
Basically, I am trying to authenticate routes such as checking if user exists etc. I only want to allow
requests coming from my frontend application to be approved, but, since no user is signed in there is no token to send.
Api request -
mywebiste/checkUser/email
This route is unprotected on my backend because no user is logged in.
BUT I want to protect this route, in such a way that it's accessible only from the frontend.
Some ideas I came up with were adding specific headers tag from the frontend and check them on the backend, but that could be easily replicated, is there something more secure like using tokens etc.
I am using React and Node.js
Same origin policy is going to give you some basic protection, but basically if an API endpoint is exposed publicly, it's exposed publicly. If you don't want that route to be publicly accessible you need to add access control.
If you use that route to check if a user is already registered, you could, for example, merge it with the user registration route and send a different error code if the user already exists (which is not a great idea because it leaks which emails are registered on your system).
You can verify that a request was originated by a user (by authenticating him) but you cannot verify that a request comes from a particular client because of these two reasons :
If you include some API key in your client (web page or other), it's easily retrievable by everyone (the best thing you could do is offuscate it which makes things slightly harder but still possible)
If you send an API key over the network it's easily retrievable as well
The only thing you could do is prevent other web pages from calling your backend on behalf of the user, by using CORS (which is actually active by default if you dont specify an Access-Control-Allow-Origin header)
I ended up creating a kind of working solution, so basically, I create a new base64 string on my frontend and attach that to the header while making a request to the backend. The base64 string is different every minute, so even if the header is copied, it differs every minute and is combined with your secret key.
I have made a package so that people can use it if they want - https://github.com/dhiraj1site/ncrypter
You can use it like so
var ncrypter = require('ncrypter');
//use encode on your frontend with number of seconds and secret key
var encodedString = ncrypter.encrypt(2, 'mysecret1')
//use decode on your backend with same seconds and secret
var decodedString = ncrypter.decrypt(encodedString, 2, 'mysecret1');
console.log('permission granted -->', decodedString);

How to implement "forgot/reset password" feature properly in Node.js? (Using one time token)

I am implementing a forgot/reset password functionality in a Node.js app using NestJs.
That is the general flow:
A user types in his email in a "forgot password" form and submits the request
The server generates a jwt token with the user's ID as the payload, then sends an email with the token as the link to reset the password (example: GET: example.com/reset/generated_jwt_token)
User clicks the link from his email, the reset password page is rendered, he fills the form with the new password and submits the form with the password as the body (example: POST: example.com/reset/generated_jwt_token)
Server verifies the token (that is not expired + user ID from payload exists in the DB) and updates the password.
The main problem with this approach is that the jwt token can be used unlimited amount of times to reset the password (until it expires after X minutes).
Is there a way to solve this? some say to put the current password's hash as the payload since it will be changed anyway and will guarantee 1 time use, but I'm not a fan of this method.
EDIT: Another approach i encountered is creating a blacklist collection in the DB of jwt token that cannot be used more than once. Or using a cache in redis the same way, but it seems not very scalable.
When a token is generated, you could save it (or something unique embedded inside it) into the database under that user. Then, the server verifies the token:
(1) when the link from the reset email is clicked
(2) when the user submits the reset password page
by checking that the token is the same as the one for that user in the database.
Also, when the user successfully changes their password, clear the token from the database so it can't be used again.
I agree with the (accepted) answer of #CertainPerformance.
I would like to add - Consider using authentication-flows-js. You will not have to worry about the implementation at all!
It is a module that answers most flows - authentication, registration, forgot-password, change password etc., and it is secured enough so applications can use it without the fear that it will be easily hacked.
From an article I wrote:
Forgot Password
The user enters their email in the forgot password
form, and clicks submit. The server (AFM) verifies the account exists
and is not locked. If it is locked, AFM throws an error. Otherwise, an
email is sent to the user with a token. That token is stored in the DB
in the same row/document/record of the user.
Read the full article with more explanations here.

Validating user token from backend

I am trying to verify on my backend side (node.js) user's token. Based on the official documentation docs I should download first all JWT from
https://cognito-idp.${region}.amazonaws.com/${UserPoolId}/.well-known/jwks.json
But for some reason this address doesn't exists (of course with valid region and UserPoolId). Everything should be configured well because signup, it's confirmation and login works perfectly, users are added to the pool, I've got token. Any idea what can be wrong ?
For me the following works to access the JWK Set (basically replaced the region and user pool id in the url above).
https://cognito-idp.us-east-1.amazonaws.com/us-east-1_O2vEE1sUF/.well-known/jwks.json
https://cognito-idp.us-east-1.amazonaws.com/us-east-1_O2vEE1sUF/ should be coming from your iss field.

Meteor forgotPassword & sendResetPasswordEmail dataflow

I'm not fully understanding the process for processing a 'forgot password' request from the user. Just looking for a little clarification.
On the client you take the user's email and pass that to Accounts.forgotPassword which triggers a call to Accounts.sendResetPasswordEmail on the server. Accounts.forgotPassword only takes email as an argument.
So Accounts.sendResetPasswordEmail is triggered which actually sends the email to the user, but that's looking for a userId...
Just confused by the logic there. Why not just call sendResetPasswordEmail from the client with an email and a userId as arguments?
It's important to note that Accounts.sendResetPasswordEmail can only be called from the server, and is automatically called for you as the result of the call to Accounts.forgotPassword. So in general you don't need to directly call it, however you probably do want to customize the email (from, subject, body) via Accounts.emailTemplates.
Of course, you could call Accounts.sendResetPasswordEmail via a method but consider the most common use case:
I'm a user of the system, but I'm not logged in (no Meteor.userId()). I have an email which is attached to my account. I want to get a reset password email based only on that information. And that's exactly what Accounts.forgotPassword does for you. How convenient!
Note also that by requiring an email on a route that has to be exposed to the public, you are also inherently filtering out baddies which don't know the emails of your users.

Categories