fskilnik
asked on
Scott Fell´s token idea
Hi there,
The question is related to this one:
https://www.experts-exchange.com/questions/28634665/if-else-in-body-tag.html?anchorAnswerId=40678923#a40678923
I would like to implement the "token idea", but I am not sure I understood what should I do.
(Please explain in a step-by-step basis. Feel free to mention "this must be stored in the database", or called from there, etc, because I know how to manage an SQL server database and I AM able to create some tasks like functions or store procedures if necessary.)
Thanks!
fskilnik
The question is related to this one:
https://www.experts-exchange.com/questions/28634665/if-else-in-body-tag.html?anchorAnswerId=40678923#a40678923
I would like to implement the "token idea", but I am not sure I understood what should I do.
(Please explain in a step-by-step basis. Feel free to mention "this must be stored in the database", or called from there, etc, because I know how to manage an SQL server database and I AM able to create some tasks like functions or store procedures if necessary.)
Thanks!
fskilnik
ASKER
Hi there, Scott Fell !!
Uau... this is simply MARVELLOUS.
I will start studying and implementing your ideas/solutions tomorrow (Monday), and I will be back, every two days at most, to tell you about my progress and, eventually, my doubts.
I am REALLY REALLY grateful.
Thanks A LOT for all the time and patience you had to explain/create this all !!!!
Regards,
fskilnik.
Uau... this is simply MARVELLOUS.
I will start studying and implementing your ideas/solutions tomorrow (Monday), and I will be back, every two days at most, to tell you about my progress and, eventually, my doubts.
I am REALLY REALLY grateful.
Thanks A LOT for all the time and patience you had to explain/create this all !!!!
Regards,
fskilnik.
ASKER
Hi there, Scott!
I have read your "scripts" carefully and I guess I understood the whole idea.
My first steps:
(1) I have already created the login page before, and it works ok. If the users logs in successfully, two things were already implemented:
first: a session "UserLogin" was created, that you call username (this is an EMAIL of the user, a nvarchar(90) field);
second: a session "UserID" is created, that you call user_id (this is an integer field) ;
Now a third thing should happen:
three: the function setToken(Session("UserID") ) should run, considering that I included the "token_task.asp" file (that you called "config.asp") at the begining of the page:
<!--#include virtual="token_task.asp" -->
Important: I have created the two additional fields in the users table: token AND token_expires, the first one a "nvarchar(50)" field and the second one a datetime field.
Some error occur and, after many tests, I am SURE the problem is in this line:
token = sha256(now&user&secret_key )
on the code given below. Why? Because if I put "token = 12345" as a substitute, it works as expected.
Of course I have copy-pasted the whole function definitions present at your config.asp page ...
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- -
function setToken(user)
'set token in cookie and log in table for 1 hour
token_expires = dateAdd("n",login_session_ minutes,no w)
token = sha256(now&user&secret_key )
'Response.Cookies("domaint oken")=tok en
'Response.Cookies("domaint oken").Exp ires=cdate (expires)
Set objConnection = Server.CreateObject("ADODB .Connectio n")
objConnection.open MM_myConnection_server_STR ING
SQLsproc = "UPDATE dbo.properTblUsers SET token = '" & token & "' WHERE properUserID = " & user
objConnection.CommandTimeo ut = 0
objconnection.execute SQLsproc
objConnection.close
end function
-------------------------- ---------- ---------- ---------- ---------- ---------- ---------- ---
You may note I did not put the last part in the update procedure, because I believe the "cdate(expires)" should be "cdate(token_expires)" anyway, correct? I also took out the "cookies" lines because I don´t know if I should define something related to these cookies previously, I mean, in other pages. I did not.
Please help.
Thanks a lot!
Regards,
fskilnik.
P.S.: I still did not put the lookupToken() function to work, by the way.
I have read your "scripts" carefully and I guess I understood the whole idea.
My first steps:
(1) I have already created the login page before, and it works ok. If the users logs in successfully, two things were already implemented:
first: a session "UserLogin" was created, that you call username (this is an EMAIL of the user, a nvarchar(90) field);
second: a session "UserID" is created, that you call user_id (this is an integer field) ;
Now a third thing should happen:
three: the function setToken(Session("UserID")
<!--#include virtual="token_task.asp" -->
Important: I have created the two additional fields in the users table: token AND token_expires, the first one a "nvarchar(50)" field and the second one a datetime field.
Some error occur and, after many tests, I am SURE the problem is in this line:
token = sha256(now&user&secret_key
on the code given below. Why? Because if I put "token = 12345" as a substitute, it works as expected.
Of course I have copy-pasted the whole function definitions present at your config.asp page ...
--------------------------
function setToken(user)
'set token in cookie and log in table for 1 hour
token_expires = dateAdd("n",login_session_
token = sha256(now&user&secret_key
'Response.Cookies("domaint
'Response.Cookies("domaint
Set objConnection = Server.CreateObject("ADODB
objConnection.open MM_myConnection_server_STR
SQLsproc = "UPDATE dbo.properTblUsers SET token = '" & token & "' WHERE properUserID = " & user
objConnection.CommandTimeo
objconnection.execute SQLsproc
objConnection.close
end function
--------------------------
You may note I did not put the last part in the update procedure, because I believe the "cdate(expires)" should be "cdate(token_expires)" anyway, correct? I also took out the "cookies" lines because I don´t know if I should define something related to these cookies previously, I mean, in other pages. I did not.
Please help.
Thanks a lot!
Regards,
fskilnik.
P.S.: I still did not put the lookupToken() function to work, by the way.
There are a couple of reason for creating the log in this way. For one can potentially be more secure because the token will change at each log in. Also, it eliminates the possibility that the session expired unexpectedly such as the worker process crashing and resetting the session or somebody staring at the screen for 10 minutes only to hit the submit button and get the time out error from being idle.
If the line token = sha256(now&user&secret_key ) is causing an error but you say you can use "token = 12345", the first thing to check is that the sha256 function is working.
Try something like response.write sha256("abc") and see what happens. If that is not working, make sure you have that in your scripts.asp. If it does work, the next thing to check is that you are passing data. Try using response.write user then response.write secret_key just to make sure you have those variables loaded with data or not misspelled. It will help if you use option explicit http://www.4guysfromrolla.com/webtech/faq/Intermediate/faq6.shtml. Also, make sure everything is converted to a string. IF the variable user could be a number, then make sure it is a string.
token = sha256(cstr(now)&cstr(user )&secret_k ey)
Once that is working, there should be a cookie that has the token string and a matching string in the user table. On each page load, I look up the cookie and match it with the user table field that contains the data. That will give you all the user fields including the expired, username, full name, user level etc that you can use later on in the page if needed.
Then you can do a way with storing this in a session.
If the line token = sha256(now&user&secret_key
Try something like response.write sha256("abc") and see what happens. If that is not working, make sure you have that in your scripts.asp. If it does work, the next thing to check is that you are passing data. Try using response.write user then response.write secret_key just to make sure you have those variables loaded with data or not misspelled. It will help if you use option explicit http://www.4guysfromrolla.com/webtech/faq/Intermediate/faq6.shtml. Also, make sure everything is converted to a string. IF the variable user could be a number, then make sure it is a string.
token = sha256(cstr(now)&cstr(user
Once that is working, there should be a cookie that has the token string and a matching string in the user table. On each page load, I look up the cookie and match it with the user table field that contains the data. That will give you all the user fields including the expired, username, full name, user level etc that you can use later on in the page if needed.
Then you can do a way with storing this in a session.
ASKER
Hi there, Scott Fell!
Excellent suggestions and testing-hints. After suffering a lot (as usual), I realized there were MANY problems:
1. The secret_key was defined in the wrong page
2. The "updating procedure" was not working inside the function, therefore I made the function redirect the "code" to another page, created only for updating the token, then it goes back to the previous page.
3. The conversion to strings inside sha256 were not necessary, but I thought that was the problem until I realized the ones above... typical... computing = maximizing pain, isn´t it? :)
Now the good news: at this moment, after all corrections, when the user logs in, the token is saved as expected, and the "now" component really makes the token be different each time the (same) user logs in... great!
Tomorrow (Thursday) I will continue from this point on and I will let you know my progress or my next doubts!
Thanks A LOT, really. I am really proud to be able to implement your suggestions... and you are great to help me on this whole stuff!!
Regards,
fskilnik.
Excellent suggestions and testing-hints. After suffering a lot (as usual), I realized there were MANY problems:
1. The secret_key was defined in the wrong page
2. The "updating procedure" was not working inside the function, therefore I made the function redirect the "code" to another page, created only for updating the token, then it goes back to the previous page.
3. The conversion to strings inside sha256 were not necessary, but I thought that was the problem until I realized the ones above... typical... computing = maximizing pain, isn´t it? :)
Now the good news: at this moment, after all corrections, when the user logs in, the token is saved as expected, and the "now" component really makes the token be different each time the (same) user logs in... great!
Tomorrow (Thursday) I will continue from this point on and I will let you know my progress or my next doubts!
Thanks A LOT, really. I am really proud to be able to implement your suggestions... and you are great to help me on this whole stuff!!
Regards,
fskilnik.
ASKER
Hello, Scott!
I am sorry for not coming back here for the last few days, but last week I was really busy and could not implement any other part of the phases of the solution you have provided.
Tomorrow (Tuesday) I will have some free hours and I will restart from where I´ve left.
Thanks a lot for your understanding and, again, I am sorry about my delay for this message.
Regards and have a great day/week!
fskilnik
I am sorry for not coming back here for the last few days, but last week I was really busy and could not implement any other part of the phases of the solution you have provided.
Tomorrow (Tuesday) I will have some free hours and I will restart from where I´ve left.
Thanks a lot for your understanding and, again, I am sorry about my delay for this message.
Regards and have a great day/week!
fskilnik
ASKER
Hi there Scott Fell,
Now I made a lot of progress and, what is great, I UNDERSTOOD how cookies are connected with the whole thing! :)
Well, let´s go to my question, please:
In a certain page, let us call it "Page01_test" , I call another page ("config.asp" as you called) to run the "lookupToken" function.
In the "Page01_test" page, I KNOW the "foundToken" string was properly extracted from the database, but when the "lookupToken" function runs, something wrong occurs...
> when I use the test line:
rsFoundToken.Source = "SELECT UserLogin, security_level FROM dbo.TblUsers WHERE userID = " & 5
it works as expected, I mean, I am able to create the lookupToken string successfully...
but when I try the almost-real test line:
rsFoundToken.Source = "SELECT UserLogin, security_level FROM dbo.TblUsers WHERE token = '" & foundToken & "' AND userID = " & 5
I get an error... I mean, the rsFoundToken.Source is NOT able to extract the line from the database in one case, but it can in the other. I am sure the token = .... is with something missing, perhaps the long string is making some trouble when it is looked into the database??
I have tried some changes like putting cstr(foundToken) , for instance, but it does not fix the problem, therefore I guess the problem is something out of my limited knowledge... the WHOLE (testing) function, to help you help me, follows:
Thanks a lot, as usual!!
Regards,
fskilnik.
function lookupToken()
lookupToken = "1|abc|User" ' return bad ' <---------- for testing purposes
foundToken = Request.Cookies("domain_to ken") <--------- I´ve called it like that, with "_" included...
If foundToken <> "" then ' if token cookie found then look up db' <---- from test I know foundToken is not empty...
' look up the user table based on token
Dim rsFoundToken
Set rsFoundToken = Server.CreateObject("ADODB .Recordset ")
rsFoundToken.ActiveConnect ion = MM_myConnection_server_STR ING
rsFoundToken.Source = "SELECT UserLogin, security_level FROM dbo.TblUsers WHERE token = '" & foundToken & "' AND userID = " & 5
rsFoundToken.CursorType = 0
rsFoundToken.CursorLocatio n = 2
rsFoundToken.LockType = 1
rsFoundToken.Open()
IF not rsFoundToken.bof or not rsFoundToken.eof then
' pipe delimited return username|admin'
lookupToken = "1|def|User"
End If
End If
End function
As you certainly understand, my test is to see if (say) abc is changed to def ...
Now I made a lot of progress and, what is great, I UNDERSTOOD how cookies are connected with the whole thing! :)
Well, let´s go to my question, please:
In a certain page, let us call it "Page01_test" , I call another page ("config.asp" as you called) to run the "lookupToken" function.
In the "Page01_test" page, I KNOW the "foundToken" string was properly extracted from the database, but when the "lookupToken" function runs, something wrong occurs...
> when I use the test line:
rsFoundToken.Source = "SELECT UserLogin, security_level FROM dbo.TblUsers WHERE userID = " & 5
it works as expected, I mean, I am able to create the lookupToken string successfully...
but when I try the almost-real test line:
rsFoundToken.Source = "SELECT UserLogin, security_level FROM dbo.TblUsers WHERE token = '" & foundToken & "' AND userID = " & 5
I get an error... I mean, the rsFoundToken.Source is NOT able to extract the line from the database in one case, but it can in the other. I am sure the token = .... is with something missing, perhaps the long string is making some trouble when it is looked into the database??
I have tried some changes like putting cstr(foundToken) , for instance, but it does not fix the problem, therefore I guess the problem is something out of my limited knowledge... the WHOLE (testing) function, to help you help me, follows:
Thanks a lot, as usual!!
Regards,
fskilnik.
function lookupToken()
lookupToken = "1|abc|User" ' return bad ' <---------- for testing purposes
foundToken = Request.Cookies("domain_to
If foundToken <> "" then ' if token cookie found then look up db' <---- from test I know foundToken is not empty...
' look up the user table based on token
Dim rsFoundToken
Set rsFoundToken = Server.CreateObject("ADODB
rsFoundToken.ActiveConnect
rsFoundToken.Source = "SELECT UserLogin, security_level FROM dbo.TblUsers WHERE token = '" & foundToken & "' AND userID = " & 5
rsFoundToken.CursorType = 0
rsFoundToken.CursorLocatio
rsFoundToken.LockType = 1
rsFoundToken.Open()
IF not rsFoundToken.bof or not rsFoundToken.eof then
' pipe delimited return username|admin'
lookupToken = "1|def|User"
End If
End If
End function
As you certainly understand, my test is to see if (say) abc is changed to def ...
>rsFoundToken.Source = "SELECT UserLogin, security_level FROM dbo.TblUsers WHERE token = '" & foundToken & "' AND userID = " & 5
At the top of the page, do a response.write foundToken and what do you get? Does it match what is currently in the database? If it helps, sometimes I use response.write "|"&foundToken&"|" to help detect if there is a space at either end. You can eliminate that by using trim(" something ") which will yield, "something".
At the top of the page, do a response.write foundToken and what do you get? Does it match what is currently in the database? If it helps, sometimes I use response.write "|"&foundToken&"|" to help detect if there is a space at either end. You can eliminate that by using trim(" something ") which will yield, "something".
ASKER
Hi, Scott!
Thanks for the nice testing-hints. "Unfortunately" I got the proper "message" (below) in the same page that calls the "config.asp" page where the "lookUpToken" function is placed.
That means that the foundToken IS correctly being found... I will try another more tests and let you know in say 1.5h from now...
Regards and many thanks,
fskilnik.
-------------------------- ---------- ---------
lookupToken = 1|def|User
logged_in_user = def
foundToken = |2a3f56c9814efde8f564f5004 dec9d9634c fc73f825a4 54834af05b 59915f747|
-------------------------- ---------- ---------
Thanks for the nice testing-hints. "Unfortunately" I got the proper "message" (below) in the same page that calls the "config.asp" page where the "lookUpToken" function is placed.
That means that the foundToken IS correctly being found... I will try another more tests and let you know in say 1.5h from now...
Regards and many thanks,
fskilnik.
--------------------------
lookupToken = 1|def|User
logged_in_user = def
foundToken = |2a3f56c9814efde8f564f5004
--------------------------
ASKER
Hi there, Scott!
Yep... found the mistake... from your wonderful testing-idea :
The foundToken shown above was LONGER than the one saved in the table field... reason: the "token" was defined as nvarchar(50), now I´ve changed it to nvarchar(200) and it worked as expected (saving the complete token value)!!
I will continue implementing your great "token idea" and I will be back tomorrow (Thursday) or on Friday, to tell you about my progress and my new doubts.
Thanks A LOT for all this, of course. Your expertise and time devoted to help me is really very very appreciated.
Kind Regards,
fskilnik.
Yep... found the mistake... from your wonderful testing-idea :
The foundToken shown above was LONGER than the one saved in the table field... reason: the "token" was defined as nvarchar(50), now I´ve changed it to nvarchar(200) and it worked as expected (saving the complete token value)!!
I will continue implementing your great "token idea" and I will be back tomorrow (Thursday) or on Friday, to tell you about my progress and my new doubts.
Thanks A LOT for all this, of course. Your expertise and time devoted to help me is really very very appreciated.
Kind Regards,
fskilnik.
Sounds good. I will not be online thursday.
ASKER
Thanks for the reply, Scott!
No problem at all, of course.
See you on Friday, then! Perhaps with the solution fully implemented... ;)
Regards,
fskilnik.
No problem at all, of course.
See you on Friday, then! Perhaps with the solution fully implemented... ;)
Regards,
fskilnik.
I just created an article based on this that has full working sample code. It may take a few days to be public but watch for it https://www.experts-exchange.com/Programming/Languages/Scripting/ASP/A_18259-User-Log-In-Using-A-Token.html
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi there, Scott!
Sorry again for the delay, but last week I moved from one place to another (I mean, my house) and my "free time" (not teaching time nor creating materials/homwork for my students) is being used to deal with plumbers, painters, etc... that means I´ve seen your last 2 posts above only now.
I will restart working on the "token solution" tomorrow and the first thing I will do is to read the links you´ve created and kindly provided!!
Thanks a lot, as usual!!
Kind Regards,
fskilnik.
Sorry again for the delay, but last week I moved from one place to another (I mean, my house) and my "free time" (not teaching time nor creating materials/homwork for my students) is being used to deal with plumbers, painters, etc... that means I´ve seen your last 2 posts above only now.
I will restart working on the "token solution" tomorrow and the first thing I will do is to read the links you´ve created and kindly provided!!
Thanks a lot, as usual!!
Kind Regards,
fskilnik.
ASKER
I´m back, Scott! Again with delay, sorry for that.
To be honest, in the last few days I was NOT able to work on your solution (unfortunately) - for the reasons above and also because at this week I have a lot of online math material to create/organize - but now, after reading a good part of your marvellous article, I understand the "whole" plan/process" even clearer, and I guess it´s more-than-fair to consider my question absolutely solved. You were/are simply great, no doubt!!
If I find any trouble in implementing the small bits I´ve not done yet, I will open another EE post and, of course, let you know posting the link here.
On the other hand, I PROMISE to enter another comment here when your solution is fully implemented in my site. :)
Thanks A LOT and may I have the luck to count on your expertise in other programming issues!
All the best and Kind Regards,
Fabio Skilnik (fskilnik)
P.S.: I am honoured to have created two EE posts that, in a sense, "motivated" you to (re)think about the whole matter and write a beautiful article!
To be honest, in the last few days I was NOT able to work on your solution (unfortunately) - for the reasons above and also because at this week I have a lot of online math material to create/organize - but now, after reading a good part of your marvellous article, I understand the "whole" plan/process" even clearer, and I guess it´s more-than-fair to consider my question absolutely solved. You were/are simply great, no doubt!!
If I find any trouble in implementing the small bits I´ve not done yet, I will open another EE post and, of course, let you know posting the link here.
On the other hand, I PROMISE to enter another comment here when your solution is fully implemented in my site. :)
Thanks A LOT and may I have the luck to count on your expertise in other programming issues!
All the best and Kind Regards,
Fabio Skilnik (fskilnik)
P.S.: I am honoured to have created two EE posts that, in a sense, "motivated" you to (re)think about the whole matter and write a beautiful article!
ASKER
Hi, Scott!
As promised, I came back to tell you that your solution was put on my site two days ago.
The only 2 differences between your full solution and what I´ve done are these:
1. The token fields were created in the "Users" table, not in the (certainly better) "login transaction table" as you suggest. In the future I intend to make this modification, also for the sake of (as you say): "... you can run a report of who logged in with the time stamp and IP. You can also view the current list of logged in users and if you like, remove their token and thus logging them out."
2. I have not used the hash function to avoid letting the explicit password from each user to be stored in the database (among other issues). Again I believe that your suggestion IS excellent, and I do intend to change my code in the near future.
Let me ask you something: when the lookupToken() function is called, this line:
>> foundToken = Request.Cookies("domaintok en")
will work even if the user does not allow cookies in his computer?
The reason for the question is the fact that one user told me that after logged in (from the homepage) he was redirected to the login page (not the homepage) when he tried to go from the first logged in page to another one.
If the problem is not cookie-related, could you imagine what the problem could be?
Thanks A LOT, as always!
Regards,
fskilnik.
As promised, I came back to tell you that your solution was put on my site two days ago.
The only 2 differences between your full solution and what I´ve done are these:
1. The token fields were created in the "Users" table, not in the (certainly better) "login transaction table" as you suggest. In the future I intend to make this modification, also for the sake of (as you say): "... you can run a report of who logged in with the time stamp and IP. You can also view the current list of logged in users and if you like, remove their token and thus logging them out."
2. I have not used the hash function to avoid letting the explicit password from each user to be stored in the database (among other issues). Again I believe that your suggestion IS excellent, and I do intend to change my code in the near future.
Let me ask you something: when the lookupToken() function is called, this line:
>> foundToken = Request.Cookies("domaintok
will work even if the user does not allow cookies in his computer?
The reason for the question is the fact that one user told me that after logged in (from the homepage) he was redirected to the login page (not the homepage) when he tried to go from the first logged in page to another one.
If the problem is not cookie-related, could you imagine what the problem could be?
Thanks A LOT, as always!
Regards,
fskilnik.
The user would have to allow cookies for this to work and that is probably the issue.
ASKER
Hi, Scott!
Thank you for the quick reply. Ok, I will let him know about it!
See you in my future EE posts, I hope! :)
Regards,
Fábio.
Thank you for the quick reply. Ok, I will let him know about it!
See you in my future EE posts, I hope! :)
Regards,
Fábio.
What you can do is on the log in page set a test cookie than try and read it. If you can't read it you can tell cookies are turned off. If that is the case, send a message on screen that cookies must be enabled.
response.cookies("test")="ok"
if request.cookies("test")<>"ok" then
response.write "Cookies must be enabled to use this site"
end if
ASKER
Excellent, Scott!
I will do that, for sure.
Thanks a lot (as usual)!!
Regards,
fskilnik.
I will do that, for sure.
Thanks a lot (as usual)!!
Regards,
fskilnik.
Passwords and cookies are stored as a salted sha256 hash. A hash is supposed to be one way meaning it can't easily be decrypted.
Each log in, a cookie is set with a token and that same token gets stored in the user table along with when you want it to expire.
Each page load, request the token from the cookie, then look it up in the user table, if found, make sure it is not expired. If good, then return the username and user level that can be used throughout the page.
The code below is only for demonstration, not tested and should not be used as is for your log ins.
SET PASSWORD FORM
Open in new window
UPDATE_USER_PASS.ASPOpen in new window
LOG IN FORM
Open in new window
LOGIN.ASPOpen in new window
AUTHORIZATIONOpen in new window
CONFIG.ASP
Open in new window