rejetto forum

Software => HFS ~ HTTP File Server => HTML & templates => Topic started by: LeoNeeson on August 25, 2018, 03:05:25 AM

Title: Alternative login form for modern browsers
Post by: LeoNeeson on August 25, 2018, 03:05:25 AM
Thanks to danny and his idea (in this post (http://rejetto.com/forum/index.php?topic=12055.msg1062910#msg1062910)), and after spending several hours finding a solution and doing lot of tests, I think we finally have a working workaround solution for login from mobile browsers (that it even work on desktop browsers too).

1. In the "Virtual File System" box, right click on the first element (Home)
2. Properties
3. Diff template
4. Enter this text:
Code: [Select]
[unauthorized]
<h1>{.!Unauthorized.} {.!&#47; Please login&hellip;.}</h1>
{.!Either your user name and password do not match, or you are not permitted to access this resource..}<br>
{.!Please login to access to your account, and check if you have the correct permissions to continue..}<br>

<br>
<fieldset id='login'>
  <legend><img src="/~img27"> {.!Login.}</legend>
  <center>
    <input type='text' id='usr' size='15' placeholder=" Username" value=""><br>
    <input type='password' id='psw' size='15' placeholder=" Password" value=""><br>
    <input type='button' id='lognow' style="width:110px;" value="{.!Login.}" onclick="NewLogin();">
  </center>
</fieldset>
<br>

<script>
function NewLogin() {
  var xhr = new XMLHttpRequest();
  var ThisFolder = window.location;
  var ThisUser = document.getElementById("usr").value;
  var ThisPass = document.getElementById("psw").value;
  var LoginToken = ThisUser+':'+ThisPass;
  xhr.open("GET", "/~login", true);
  xhr.withCredentials = true;
  xhr.setRequestHeader("Authorization", 'Basic ' + btoa(LoginToken));
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
      if (window.location.href.indexOf("~login") != -1) {
        window.location.replace('/?success');
        } else {
          window.location.replace(ThisFolder);
      };
    }
    if (xhr.readyState == 4 && xhr.status == 401) {
      alert("Invalid credentials! \(Wrong username or password\)");
    }
  }
  xhr.send();
}
</script>

Please test it and report the results (remember to create an account first on HFS). I've literally wasted all my free afternoon, but I'm happy with the results!. It may not be perfect, so, feel free to adapt/correct/enhance the code... ;)

Cheers,
Leo.-
Title: Re: Alternative login form for modern browsers
Post by: bmartino1 on August 28, 2018, 03:33:10 PM
thank you leo, the code works fairly well.

I did attempt to add/change css and put form stuff in it as per dany request on what it might have... etc...

here is that code for refference.

Code: [Select]
[unauthorized]

<!-- I should be a EVENT Under the House - "Home icon / " Root Virtual File system!-->
<!-- include css file here-->
    <style> /* below line is write to use google font online  */
@import url(http://fonts.googleapis.com/css?family=Ubuntu);
 
h2{
 background-color: #FEFFED;
 padding: 30px 35px;
 margin: -10px -50px;
 /*text-align:center; */
 border-radius: 10px 10px 0 0;
}
 
hr{
 margin: 10px -50px;
 border: 0;
 border-top: 1px solid #ccc;
 margin-bottom: 40px;
}
 
div.container{
 width: 900px;
 height: 610px;
 margin:35px auto;
 font-family: 'Ubuntu', sans-serif;
}
 
div.main{
 width: 300px;
 padding: 10px 50px 25px;
 /* border: 2px solid gray; */
 border-radius: 10px;
 font-family: raleway;
 float:left;
 margin-top:50px;
}
 
input[type=text],input[type=password]{
 width: 150px;
 height: 40px;
 padding: 5px;
 margin-bottom: 25px;
 margin-top: 5px;
 border: 2px solid #ccc;
 color: #4f4f4f;
 font-size: 16px;
 border-radius: 5px;
}

label{
 color: #464646;
 text-shadow: 0 1px 0 #fff;
 font-size: 14px;
 font-weight: bold;
}

center{
 font-size:32px;
}

.note{
 color:red;
}
 
.valid{
 color:green;
}

.back{
 text-decoration: none;
 border: 1px solid rgb(0, 143, 255);
 background-color: rgb(0, 214, 255);
 padding: 3px 20px;
 border-radius: 2px;
 color: black;
}
 
input[type=button]{
 font-size: 16px;
 background: linear-gradient(#ffbc00 5%, #ffdd7f 100%);
 border: 1px solid #e5a900;
 color: #4E4D4B;
 font-weight: bold;
 cursor: pointer;
 width: 150px;
 border-radius: 5px;
 padding: 10px 0;
 outline:none;
}
 
input[type=button]:hover{
 background: linear-gradient(#ffdd7f 5%, #ffbc00 100%);
}

.fugo{
 float:right;
} </style>

<script>
function NewLogin() {
  var xhr = new XMLHttpRequest();
  var ThisFolder = window.location;
  var ThisUser = document.getElementById("usr").value;
  var ThisPass = document.getElementById("psw").value;
  var LoginToken = ThisUser+':'+ThisPass;
  xhr.open("GET", "/~login", true);
  xhr.withCredentials = true;
  xhr.setRequestHeader("Authorization", 'Basic ' + btoa(LoginToken));
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
      if (window.location.href.indexOf("~login") != -1) {
        window.location.replace('/?success');
        } else {
          window.location.replace(ThisFolder);
      };
    }
    if (xhr.readyState == 4 && xhr.status == 401) {
      alert("Invalid credentials! \(Wrong username or password\)");
    }
  }
  xhr.send();
}
</script>
<h1>{.!Unauthorized.} {.!&#47; Please login&hellip;.}</h1>
{.!Either your user name and password do not match, or you are not permitted to access this resource..}<br>
{.!Please login to access to your account, and check if you have the correct permissions to continue..}<br>
<br>

<div class="container">
  <div class="main">
  <div align="left">
<!-- <h2>Login Form</h2><hr/> -->
<!-- <form id="form_id" name="myform"> -->
<fieldset id='login'>
  <legend><img src="/~img27"> {.!Login.}</legend>
  <center>
  <label for="uname">User Name :</label></br>
    <input type='text' class="form-control" id='usr' tabindex="1" size='15' placeholder=" Username" value="" required><br>
    <span class='error-message' id='uname-error'></span>

<label>Password :</label></br>
<input type='password' class="form-control" id='psw' tabindex="2" size='15' placeholder=" Password" value="" required><br>
    <span class='error-message' id='pw-error'></span>

<input type='button' tabindex="3" class="btn btn-default" id='lognow' style="width:110px;" value="{.!Login.}" onclick="NewLogin();">
    <span class='error-message' id='submit-error'></span>

<!--    <label><input type="checkbox" checked="checked" name="remember"> Remember me </label> -->
<!-- <button type="button" class="cancelbtn">Cancel</button> <span class="psw">Forgot <a href="#">password?</a></span> -->
<!-- </form> -->

 </center>
</fieldset>
</div>
  </div>
</div>
<br>
</br>
<!-- Did I work? -->
<p> User: %user% @ IP: %ip% </p>
</div>

i had did a test of 2 vitural folder eacch with 1 acount acess split between 2 accounts.

the unathoruzed code will log you in 1 for that folder (it doen't keep you loged in if i leave to another area.)

also the only way i could eror was to click ont he resouce and hit cancle
thus i hit the even t created 404 login.
but you err wrong credential broungh back the default login box (had to hit cancle) before i saw the alert.

other wise, exclent code, and thank you for this.

Also looks like o need to relearn the xml httl request and HTML code :/
https://stackoverflow.com/questions/28238514/login-form-valiation-using-xmlhttprequest
Title: Alternative login form v2.0 released!
Post by: LeoNeeson on April 25, 2020, 10:46:57 PM
BREAKING NEWS!! :D v2.0 released! (see below)



For a long time I was convinced that having a form-based 'login' and a truly working 'logout' (totally independent of which browser you use), was something technically impossible to accomplish, just because a limitation of the Basic Authentication (https://en.wikipedia.org/wiki/Basic_access_authentication) scheme (which HFS makes use).

Although this remains to be true (Basic Auth scheme impose limitations), recently I've discovered that HFS also supports "Digest access authentication (https://en.wikipedia.org/wiki/Digest_access_authentication)" (besides the "Basic access authentication (https://en.wikipedia.org/wiki/Basic_access_authentication)"). This lets HFS manage logins much better, since it makes use of a "session ID" cookie (named HFS_SID_), which gives us a possibility of having a true logout system. 8)

But, after days of testings, I've found a bug (or an imperfect implementation in the code) that is preventing HFS to forget a previously logged-in session (this breaks the logout system), and was reported HERE (http://rejetto.com/forum/index.php?topic=13286.0). I'm always talking about using a form-based login and not the internal browser popup login (to test this, you have to click cancel on that popup (https://i.stack.imgur.com/ZMBql.png)).

Summarizing: we could have a true logout, when this bug is fixed, and optionally, we will also need to modify the template to avoid opening the browser's login popup, since we will handle the login, only through Ajax (I've also posted there an idea to fix that too).



ยป How to install:
1. Be sure of use the default login of HFS v2.3m (http://downloads.sourceforge.net/hfs/hfs2.3m.zip) or the legacy template (http://rejetto.com/forum/index.php?topic=13082.0).*
2. In the "Virtual File System" box, right click on the first element (Home)
3. Properties
4. Diff template
5. Enter the text contained on Unauthorized-2.txt
* = Note: this diff-template could also work with another templates, but it's unstested.



Differences with v1.0
- Using now a POST request, which is more secure than GET method.
- Enhanced password security, by using Digest scheme instead of Basic Auth.
(jQuery-free, pure plain JavaScript with no dependencies other than md5.js)

Please report back if you find problems, or want to leave any suggestions or opinions about this. :)

Cheers,
Leo.-
Title: Re: Alternative login form for modern browsers
Post by: NaitLee on May 04, 2020, 11:52:40 AM
Successfully introduced this new login system to my template just now! Please wait for my next update!

Hint: If you put a login form below the [unauthorized] section, you can also add this to your template:

Code: [Select]
[login0]
{.$unauthorized.}

Then view http://127.0.0.1/~login0 (must root, not subfolders), you get your login form without showing the browser's one! ;)
And then you can replace all <a href="~login"> to <a href="/~login0">. Have fun!
Title: Re: Alternative login form for modern browsers
Post by: LeoNeeson on May 05, 2020, 05:25:44 AM
@NaitLee: Thanks for your suggestion. :) I had something similar on my mind, but instead of using ~login0, using ~signin which is an alternate terminology for login.
Title: Re: Alternative login form for modern browsers
Post by: Rapid on May 07, 2020, 05:53:40 AM
Hi Leo!
Could you make a new version for 2.4?
As 2.4 has new functions like MD5 - it would be nice to compare if it work as expected.

I'm using a HW AES, so it should work much faster than JS function.

And I can't find "Logout" button using default 2.4's template.

Found "logout" button.

Very strange logic. When I put just  any login name, it saves as %user%
Title: Re: Alternative login form for modern browsers
Post by: Mars on May 07, 2020, 04:21:05 PM
for an md5 macro, you must first add OverbyteicsMD5 in 'uses', optionally OverbyteicsSha1
then we add the necessary macros

in this case we take the opportunity to introduce the 64 and sha1 encoding macros available easily

Code: [Select]
    if name = 'encode md5' then  // only for text strings, otherwise use 'md5 file' for binary files
      result:=strMD5(p);

    if name = 'encode sha1' then
      result:=SHA1ofStr(p);

    if name = 'encode 64' then
      result:=base64encode(p);

    if name = 'decode 64' then
      result:=base64decode(p);

// just above these macros
    if name = 'encodeuri' then
      encodeuri();

    if name = 'decodeuri' then
      result:=decodeURL(p);

But to satisfy the rebetto who loves the minimum evolution, we could make a variant allowing an evolution by grouping everything in a macro with various parameters but that could complicate the writing

{.encode|[md5,64,sha1,...]| ..... .}
{.decode|[64,...]| ..... .}
Title: Re: Alternative login form for modern browsers
Post by: Rapid on May 07, 2020, 05:32:41 PM
Hi Mars,

From whatsnew of 2.4:

Quote
VER 2.4
propaganda
  New mobile-friendly template
/propaganda
+ new default template
+ {.set item|name.}
+ {.get item|icon.}
+ {.set cfg.}
+ cache for jquery and template sections
+ new template commands: base64, base64decode, md5, sha1
...
Title: Re: Alternative login form for modern browsers
Post by: LeoNeeson on May 08, 2020, 12:14:05 AM
Hi Rapid! I will split my answer, to make it more easier to understand...

Could you make a new version for 2.4?
I could try to do it, but on the next week I'll have very little free time (next Monday I will start to work again), so that could take me some days/weeks, please be patient. Currently, this (http://rejetto.com/forum/index.php?topic=13054.msg1065523#msg1065523) is meant to work with the default template (http://rejetto.com/forum/index.php?topic=13082.0) of HFS v2.3m (which you can install on the latest v2.4, and it should work normally).

As 2.4 has new functions like MD5 - it would be nice to compare if it work as expected.
I must explain something: as you may already know (since you are a programmer), HFS internally had the MD5 function since 10 years ago (it's not something new), but recently on v2.4, a MD5's macro was added (which enables you to use it on a template). This was added along with Base64 (and it was discussed here (http://rejetto.com/forum/index.php?topic=13081.msg1064168#msg1064168)).

But for the login you can NOT use the MD5's macro, since macros are executed only at server level. And the MD5 hashing of the login password must be done at client level, before you sent it to the server (so we must use JavaScript to do the MD5 hashing).

You could test the "new" macro functions of HFS v2.4 (for Base64, MD5, SHA1), but the hashing macros are not useful to the login. For example, see this 'diff template' that show those macros (source (http://rejetto.com/forum/index.php?topic=13081.msg1064182#msg1064182)):

Code: [Select]
[]
<html><body>
{.set|encodedTest| {.base64|this object will store some %symbols% in the javascript space, so that libs can read them.}.}
{.^encodedTest.}
<hr>
The MD5 of "abc" is: {.md5|abc.}
<hr>
MD5 of "encodedTest" variable content: {.md5|{.^encodedTest.}.}
<hr>
SHA1 of "encodedTest" variable content: {.sha1|{.^encodedTest.}.}
<hr>
{.base64decode|{.^encodedTest.}.}
<hr>
{.base64decode|VGhpcyBpcyBhIHNhbXBsZSB0ZXh0.}
<hr>
{.base64decode|dGhpcyBvYmplY3Qgd2lsbCBzdG9yZSBzb21lICVzeW1ib2xzJSBpbiB0aGUgamF2YXNjcmlwdCBzcGFjZSwgc28gdGhhdCBsaWJzIGNhbiByZWFkIHRoZW0= .}
<hr>
</body></html>

(This was only tested with HFS v2.4 RC4, not RC5)

And I can't find "Logout" button using default 2.4's template.
If you are trying to test the logout, at the moment, you must install the old template of HFS v2.3m (http://rejetto.com/forum/index.php?topic=13082.0). What is being discussed here (http://rejetto.com/forum/index.php?topic=13286.msg1065522#msg1065522) is totally independent of the template, since there we discuss the logout function at server level. If you want to use the logout button on the default 2.4's template, you will have to wait some days until I complete it the adaptation. Stay tuned for news/updates (perhaps some other user, like DJ (http://rejetto.com/forum/index.php?action=profile;u=32265), could to this faster than me, since he is expert on modern templates).

(In the next few days I will be less active in the forum, but I will still be on the lookout for anything new here)
Cheers,
Leo.-
Title: Re: Alternative login form for modern browsers
Post by: Rapid on May 08, 2020, 06:46:08 AM
Quote
But for the login you can NOT use the MD5's macro
You are totally right! Sorry.
Title: Re: Alternative login form for modern browsers
Post by: rejetto on May 10, 2020, 09:57:33 AM
leo is right, you MAY use the server-side md5, but that would break the security and make the md5 a waste of time :)

Modern browsers have sha1 and sha256 but not md5

Code: [Select]
function digest(data, method='SHA-1') {
  return Array.from(new Uint8Array(await crypto.subtle.digest(method, new TextEncoder().encode(data))))
      .map(b => b.toString(16).padStart(2, '0')).join('')
}

digestMessage('test').then(x=> console.log(x))

also, md5 today is considered not very strong, so i think we should go for sha1 or sha256.
compatibility seems quite good
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#Browser_compatibility

templates who want to have the feature on older browser can use this
https://github.com/geraintluff/sha256/blob/gh-pages/sha256.min.js
otherwise they can just send plain-text.

new delphi has all of these already embedded.
http://docwiki.embarcadero.com/Libraries/Rio/en/System.Hash.THashSHA2
Title: Re: Alternative login form for modern browsers
Post by: rejetto on May 10, 2020, 10:14:53 AM
Code: [Select]
      if goodPassword(data.postVars.values['__PASSWORD_SHA256'], strSHA256)
      or goodPassword(data.postVars.values['__PASSWORD_MD5'], strMD5)
      or (data.postVars.values['__PASSWORD'] = data.account.pwd) then

next release ;-)
Title: Re: Alternative login form for modern browsers
Post by: Mars on May 10, 2020, 02:54:51 PM
Why stop now while everything is going so well  ;)

      if goodPassword(data.postVars.values['__PASSWORD_SHA256'], strSHA256)
      or goodPassword(data.postVars.values['__PASSWORD_MD5'], strMD5)
      or goodPassword(data.postVars.values['__PASSWORD_B64'], strB64)
      or (data.postVars.values['__PASSWORD'] = data.account.pwd) then

https://www.base64encoder.io/javascript/

we could even avoid indicating the type of encryption when sending the form in case of interception of frames
     if goodPassword(data.postVars.values['__PASSWORD'], strSHA256)
      or goodPassword(data.postVars.values['__PASSWORD'], strMD5)
      or goodPassword(data.postVars.values['__PASSWORD'], strB64)
      or (data.postVars.values['__PASSWORD'] = data.account.pwd) then
Title: Re: Alternative login form for modern browsers
Post by: rejetto on May 10, 2020, 04:26:05 PM
there's no need for base64, and it's not hashing, no security.
i explained reasons for sha256
Title: Re: Alternative login form for modern browsers
Post by: rejetto on May 10, 2020, 06:34:50 PM
SHA256 available in https://github.com/rejetto/hfs2/releases/tag/v2.4-alpha06
Title: Re: Alternative login form for modern browsers
Post by: rejetto on May 12, 2020, 09:40:30 AM
guys, i want to make this system the new standard, not just an extra as initially designed.
i want to have better names instead of the __USER.
I'm going to use the existing ?mode in the url, so we'll have mode=login and mode=logout
no __AJAX anymore
in POST data (in the future maybe also in GET) the names for the login will be simply: user, password, passwordMD5, passwordSHA256
logout needs needs no user

the default template will use this.
Title: Re: Alternative login form for modern browsers
Post by: Rapid on May 15, 2020, 08:42:33 AM
Hi Rejetto!

I think, that for security reasons saving in preferences password or MD5(password) or SHA256(password) are all equally bad.
For MD5 we had rainbow tables, and maybe for sha256 will be something similar.

Saved should be only password hashed with salt.

For example there is experimental RFC: https://tools.ietf.org/html/rfc7804
According HFS, salt can be generated one per VFS.

Could you make switch for sha256 function? Like if protocol is https than use browsers implementation? I think it should be more optimized than js version
Title: Re: Alternative login form for modern browsers
Post by: rejetto on May 15, 2020, 02:03:18 PM
hi Rapid, i see your point, and there's some truth.
Anyway, hashing would be better than the simple base64 encoding we have now, and that's what i could introduce with little work.

People here have to understand that we are discussing server storage security, in case you get access to settings on the server. We are not discussing login security.

Back to our point, let's see... if in the future we'll have also a 'salt', the server will have to pass it to the client (along with the session), and the piece of scheme hash(pwd) will become hash(pwd+salt).
We can consider it being already like this, with salt as empty string. The current scheme seems to be compatible with this future requirement, and templates can already be build this way to be future proof.
I hope I was clear enough on this, and that you agree with its consistency. Thanks for making me think on this, i didn't  before.

Quote
Could you make switch for sha256 function? Like if protocol is https than use browsers implementation? I think it should be more optimized than js version

more code to optimize what? 1ms total on the browser's CPU ? :)
Title: Re: Alternative login form for modern browsers
Post by: LeoNeeson on May 16, 2020, 05:22:34 AM
Saved should be only password hashed with salt.
and that's what i could introduce with little work.
I agree and understand on the security points (and I already know we are talking about the server side, not the client side), but I have 2 considerations to suggest you keep in mind:

1) make this optional (I'm talking about saving password hashed with salt), why? because what happens if the user lost his password, or if you use this only between family members (and then need to remember someone his password). Reset password could be handy, but it's cumbersome if HFS is used only between trusted members.
2) if this is implemented, I'm having an idea to suggest about having a way to manage sessions. I will describe this idea much better on a future post this weekend, now it's late and don't have time to leave the whole idea on how this works (my idea doesn't affect directly this, it's a supplementary thing, so, if you want to work on this, don't wait for my comment).

That said, I'm not against this (on the contrary, I think it's a cool feature for those who need it) :)
Cheers,
Leo.-