Sending username and password safely

  

Hello guys,


I am working on my own Two factor authentication implementation.

I have one screen with username and password and want a second screen for the user to input the two factor code. 

In order to make sure the correct user is logged in, i need the username and password, or atleast that he entered the correct password in the last screen.

I do not want this in the url for obvious reasons (changing it for a user would be easy).


So my question is how do i safely pass this data between my screens?

Solution

Hi Tim,

First, I'll try to answer your actual question:

Since you would typically not send the code to the user before they have succesfully supplied their credentials, why do you need to store or pass the username and password? You can verify whether there's a match by looking up the username in the User Entity (assuming that's what you're using), encrypting the password (EncryptPassword from the Users eSpace) and checking that against the stored hash, and only if that matches continue.

Next, you'd probably create a session key (GUID, GenerateGuid from System) and store the key, the UserId and a timestamp (so you can limit the duration the user can perform step 2) in an Entity, and pass the GUID to the second screen. Then if the 2nd authentication succeeds, you can login the user using Login from System, using the stored UserId. The only downside of the latter is that it doesn't do tenant switching like UserLogin from Users, but if you need that you can always clone Users and look how it's done.

As a last thought, if you don't want the GUID to display in the title bar of the browser, use a Screen Action as Destination of the button/link, and inside the Screen Action use the Destination Statement to redirect to the right page.

Secondly, why would you want to use two Screens? Perhaps there's a good reason for it, but alternatively, you could also use a single screen that has an If widget that contains the user credentials in the True part and the second authentication in the False part, then use Ajax Refresh to display/hide the right one. Thus you could just keep the password in a local variable, and you can use UserLogin from Users after the second authentication succeeds, supplying the username and password.

Solution

Kilian Hekhuis wrote:

Hi Tim,

First, I'll try to answer your actual question:

Since you would typically not send the code to the user before they have succesfully supplied their credentials, why do you need to store or pass the username and password? You can verify whether there's a match by looking up the username in the User Entity (assuming that's what you're using), encrypting the password (EncryptPassword from the Users eSpace) and checking that against the stored hash, and only if that matches continue.

Next, you'd probably create a session key (GUID, GenerateGuid from System) and store the key, the UserId and a timestamp (so you can limit the duration the user can perform step 2) in an Entity, and pass the GUID to the second screen. Then if the 2nd authentication succeeds, you can login the user using Login from System, using the stored UserId. The only downside of the latter is that it doesn't do tenant switching like UserLogin from Users, but if you need that you can always clone Users and look how it's done.

As a last thought, if you don't want the GUID to display in the title bar of the browser, use a Screen Action as Destination of the button/link, and inside the Screen Action use the Destination Statement to redirect to the right page.

Secondly, why would you want to use two Screens? Perhaps there's a good reason for it, but alternatively, you could also use a single screen that has an If widget that contains the user credentials in the True part and the second authentication in the False part, then use Ajax Refresh to display/hide the right one. Thus you could just keep the password in a local variable, and you can use UserLogin from Users after the second authentication succeeds, supplying the username and password.

Hey Kilian,


Great idea. I'm using TOTP, so the user will have the code at all times. 

I will try the one screen way, since that would be way cleaner, without the hassle of safely passing the data.

I have already created the flow to verify the credentials, so i can get started right away.


Thanks for the help.


Best Regards,

Tim


Hi Tim,

Glad I could be of help. Please mark my answer above as Solution if you think it deserves that :).