Skip to content

Commit

Permalink
feature: password validation
Browse files Browse the repository at this point in the history
  • Loading branch information
fang committed Apr 19, 2024
1 parent c01c6d8 commit 63db276
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 17 deletions.
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ I use nginx in front of a variety of web services to handle SSL termination (usi

In this case, the auth endpoint is reverse proxied to the simple script in this repo, which does things like token checking and presenting a login form.

In addition, this version supports password verification, and the password is transmitted through encryption to ensure data security.

## Example Configuration

In something like `/etc/nginx/sites-enabled/default`
Expand Down Expand Up @@ -52,15 +54,17 @@ server {
```
simpleotp_go --help
-cookie string
cookie name
cookie name
-login-stop int
frequency of login, default 2 seconds
frequency of login, default 2 seconds
-max-age int
max age for cookie and jwt, default 1800 seconds
max age for cookie and jwt, default 1800 seconds
-password string
password for secret hash
-port int
listen port default 8000
listen port default 8000
-secret string
TOTP secret key
TOTP secret key
```


Expand All @@ -71,6 +75,7 @@ Configurations are also loaded from env.
3. PORT
4. MAX_AGE
5. LOGIN_STOP
6. PASSWORD

```
Expand Down
25 changes: 25 additions & 0 deletions internal/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"log"
"net/http"
"strconv"
"time"

"github.com/pquerna/otp/totp"
Expand Down Expand Up @@ -32,6 +33,19 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
_ = r.ParseForm()
code := r.PostForm.Get("code")

if Password != "" { // check hash with password
hash := r.PostForm.Get("hash")
hash64, _ := strconv.ParseInt(hash, 10, 32)
localHash := simpleHash(Password + code)

if hash64 != localHash {
log.Println("login failed for hash check")
w.Header().Set("Content-Type", "text/html")
_, _ = w.Write([]byte(rendorLoginFormTpl("Login failed")))
return
}
}

originalURI := r.URL.RawQuery
if originalURI == "" {
originalURI = "/"
Expand Down Expand Up @@ -91,3 +105,14 @@ func CheckAuthHandler(w http.ResponseWriter, r *http.Request) {
log.Print("auth failed ", err)
w.WriteHeader(http.StatusUnauthorized)
}

// simpleHash
func simpleHash(input string) int64 {
var hash int32 = 0
for i := 0; i < len(input); i++ {
char := input[i]
hash = (hash<<5 + hash) + int32(char)
hash &= hash
}
return int64(hash)
}
6 changes: 6 additions & 0 deletions internal/init_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var (
Port int
MaxAge int
LoginStopSeconds int
Password string
)

var (
Expand All @@ -26,6 +27,7 @@ func InitParams() {
flag.IntVar(&Port, "port", 0, "listen port default 8000")
flag.IntVar(&MaxAge, "max-age", 0, "max age for cookie and jwt, default 1800 seconds")
flag.IntVar(&LoginStopSeconds, "login-stop", 0, "frequency of login, default 2 seconds")
flag.StringVar(&Password, "password", "", "password for secret hash")

flag.Parse()

Expand Down Expand Up @@ -56,6 +58,10 @@ func overrideFromEnv() {
if LoginStopSeconds == 0 {
LoginStopSeconds, _ = strconv.Atoi(os.Getenv("LOGIN_STOP"))
}

if Password == "" {
Password = os.Getenv("PASSWORD")
}
}

func overrideFromDefault() {
Expand Down
53 changes: 53 additions & 0 deletions internal/simpleHash_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package internal

import (
"testing"
)

func Test_simpleHash(t *testing.T) {
type args struct {
input string
}
tests := []struct {
args args
want int64
}{
{
args: args{
input: "",
},
want: 0,
},
{
args: args{
input: "3of9",
},
want: 1957089,
},
{
args: args{
input: "aaa",
},
want: 108931,
},
{
args: args{
input: "aaa123",
},
want: -380258887,
},
{
args: args{
input: "fsdfds4",
},
want: -1086280018,
},
}
for _, tt := range tests {
t.Run(tt.args.input, func(t *testing.T) {
if got := simpleHash(tt.args.input); got != tt.want {
t.Errorf("simpleHash() = %v, want %v", got, tt.want)
}
})
}
}
46 changes: 34 additions & 12 deletions internal/tpls.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ input {
border-radius: 4px;
}
input[type="text"] {
.text {
width: 100%;
padding: 0 0 0 10px;
margin: 0;
Expand All @@ -69,17 +69,12 @@ input[type="text"] {
display: inline-block;
background: none;
}
input[type="text"]:focus {
.text:focus {
border-color: #3ca9e2;
}
input[type="text"]:focus:invalid {
color: #cc1e2b;
border-color: #cc1e2b;
}
input[type="text"]:valid ~ .validation span:first-child,
input[type="text"]:valid ~ .validation span:last-child,
input[type="submit"] {
input[type="button"] {
border: none;
display: block;
background-color: #3ca9e2;
Expand All @@ -95,7 +90,7 @@ input[type="submit"] {
cursor: pointer;
text-align: center;
}
input[type="submit"]:hover {
input[type="button"]:hover {
background-color: #329dd5;
-webkit-transition: all 0.2s ease;
transition: all 0.2s ease;
Expand All @@ -110,15 +105,42 @@ input[type="submit"]:hover {
border-radius: 0 0 4px 4px;
}
</style>
<script>
function simpleHash(input) {
let hash = 0;
if (input.length === 0) {
return hash;
}
for (let i = 0; i < input.length; i++) {
const char = input.charCodeAt(i);
hash = ((hash << 5) + hash) + char;
hash = hash & hash; // Convert to 32bit integer
}
return hash;
}
function doLogin() {
var form = document.forms[0]
form.hash.value = simpleHash(form.pass.value + form.code.value)
form.pass.value = ""
form.submit()
return false
}
</script>
<body>
<div id="login-form-wrap">
<form id="login-form" action="" method="POST">
<p>
<input type="text" id="username" name="code" placeholder="OTOP Code">
<input class="text" type="text" id="username" name="code" placeholder="OTOP Code">
</p>
<p>
<input class="text" type="password" id="password" name="pass" placeholder="Password">
</p>
<p>
<input type="submit" id="login" value="Login">
<input type="hidden" name="hash" value="">
<input type="button" id="login" value="Login" onclick="return doLogin()">
</p>
</form>
<div id="alert-wrap">
Expand Down

0 comments on commit 63db276

Please sign in to comment.