parent
b9462e72a4
commit
91bb9ccae6
35
home/auth.go
35
home/auth.go
|
@ -224,19 +224,10 @@ func getSession(u *User) []byte {
|
||||||
return hash[:]
|
return hash[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleLogin(w http.ResponseWriter, r *http.Request) {
|
func httpCookie(req loginJSON) string {
|
||||||
req := loginJSON{}
|
|
||||||
err := json.NewDecoder(r.Body).Decode(&req)
|
|
||||||
if err != nil {
|
|
||||||
httpError(w, http.StatusBadRequest, "json decode: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
u := config.auth.UserFind(req.Name, req.Password)
|
u := config.auth.UserFind(req.Name, req.Password)
|
||||||
if len(u.Name) == 0 {
|
if len(u.Name) == 0 {
|
||||||
time.Sleep(1 * time.Second)
|
return ""
|
||||||
httpError(w, http.StatusBadRequest, "invalid login or password")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sess := getSession(&u)
|
sess := getSession(&u)
|
||||||
|
@ -250,8 +241,25 @@ func handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
expireSess := uint32(now.Unix()) + expireTime*60*60
|
expireSess := uint32(now.Unix()) + expireTime*60*60
|
||||||
config.auth.storeSession(sess, expireSess)
|
config.auth.storeSession(sess, expireSess)
|
||||||
|
|
||||||
s := fmt.Sprintf("session=%s; Path=/; HttpOnly; Expires=%s", hex.EncodeToString(sess), expstr)
|
return fmt.Sprintf("session=%s; Path=/; HttpOnly; Expires=%s", hex.EncodeToString(sess), expstr)
|
||||||
w.Header().Set("Set-Cookie", s)
|
}
|
||||||
|
|
||||||
|
func handleLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
req := loginJSON{}
|
||||||
|
err := json.NewDecoder(r.Body).Decode(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpError(w, http.StatusBadRequest, "json decode: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cookie := httpCookie(req)
|
||||||
|
if len(cookie) == 0 {
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
httpError(w, http.StatusBadRequest, "invalid login or password")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Set-Cookie", cookie)
|
||||||
|
|
||||||
w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate")
|
w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate")
|
||||||
w.Header().Set("Pragma", "no-cache")
|
w.Header().Set("Pragma", "no-cache")
|
||||||
|
@ -324,7 +332,6 @@ func optionalAuth(handler func(http.ResponseWriter, *http.Request)) func(http.Re
|
||||||
if err == nil {
|
if err == nil {
|
||||||
r := config.auth.CheckSession(cookie.Value)
|
r := config.auth.CheckSession(cookie.Value)
|
||||||
if r == 0 {
|
if r == 0 {
|
||||||
|
|
||||||
ok = true
|
ok = true
|
||||||
} else if r < 0 {
|
} else if r < 0 {
|
||||||
log.Debug("Auth: invalid cookie value: %s", cookie)
|
log.Debug("Auth: invalid cookie value: %s", cookie)
|
||||||
|
|
|
@ -2,6 +2,8 @@ package home
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -10,19 +12,25 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAuth(t *testing.T) {
|
func prepareTestDir() string {
|
||||||
config.ourWorkingDir = "."
|
const dir = "./agh-test"
|
||||||
fn := filepath.Join(config.getDataDir(), "sessions.db")
|
_ = os.RemoveAll(dir)
|
||||||
|
_ = os.MkdirAll(dir, 0755)
|
||||||
|
return dir
|
||||||
|
}
|
||||||
|
|
||||||
_ = os.RemoveAll(config.getDataDir())
|
func TestAuth(t *testing.T) {
|
||||||
defer func() { _ = os.RemoveAll(config.getDataDir()) }()
|
dir := prepareTestDir()
|
||||||
|
defer func() { _ = os.RemoveAll(dir) }()
|
||||||
|
fn := filepath.Join(dir, "sessions.db")
|
||||||
|
|
||||||
users := []User{
|
users := []User{
|
||||||
User{Name: "name", PasswordHash: "$2y$05$..vyzAECIhJPfaQiOK17IukcQnqEgKJHy0iETyYqxn3YXJl8yZuo2"},
|
User{Name: "name", PasswordHash: "$2y$05$..vyzAECIhJPfaQiOK17IukcQnqEgKJHy0iETyYqxn3YXJl8yZuo2"},
|
||||||
}
|
}
|
||||||
|
a := InitAuth(fn, nil)
|
||||||
|
|
||||||
os.MkdirAll(config.getDataDir(), 0755)
|
user := User{Name: "name"}
|
||||||
a := InitAuth(fn, users)
|
a.UserAdd(&user, "password")
|
||||||
|
|
||||||
assert.True(t, a.CheckSession("notfound") == -1)
|
assert.True(t, a.CheckSession("notfound") == -1)
|
||||||
a.RemoveSession("notfound")
|
a.RemoveSession("notfound")
|
||||||
|
@ -59,3 +67,103 @@ func TestAuth(t *testing.T) {
|
||||||
a.Close()
|
a.Close()
|
||||||
os.Remove(fn)
|
os.Remove(fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// implements http.ResponseWriter
|
||||||
|
type testResponseWriter struct {
|
||||||
|
hdr http.Header
|
||||||
|
statusCode int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *testResponseWriter) Header() http.Header {
|
||||||
|
return w.hdr
|
||||||
|
}
|
||||||
|
func (w *testResponseWriter) Write([]byte) (int, error) {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
func (w *testResponseWriter) WriteHeader(statusCode int) {
|
||||||
|
w.statusCode = statusCode
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAuthHTTP(t *testing.T) {
|
||||||
|
dir := prepareTestDir()
|
||||||
|
defer func() { _ = os.RemoveAll(dir) }()
|
||||||
|
fn := filepath.Join(dir, "sessions.db")
|
||||||
|
|
||||||
|
users := []User{
|
||||||
|
User{Name: "name", PasswordHash: "$2y$05$..vyzAECIhJPfaQiOK17IukcQnqEgKJHy0iETyYqxn3YXJl8yZuo2"},
|
||||||
|
}
|
||||||
|
config.auth = InitAuth(fn, users)
|
||||||
|
|
||||||
|
handlerCalled := false
|
||||||
|
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
handlerCalled = true
|
||||||
|
}
|
||||||
|
handler2 := optionalAuth(handler)
|
||||||
|
w := testResponseWriter{}
|
||||||
|
w.hdr = make(http.Header)
|
||||||
|
r := http.Request{}
|
||||||
|
r.Header = make(http.Header)
|
||||||
|
r.Method = "GET"
|
||||||
|
|
||||||
|
// get / - we're redirected to login page
|
||||||
|
r.URL = &url.URL{Path: "/"}
|
||||||
|
handlerCalled = false
|
||||||
|
handler2(&w, &r)
|
||||||
|
assert.True(t, w.statusCode == http.StatusFound)
|
||||||
|
assert.True(t, w.hdr.Get("Location") != "")
|
||||||
|
assert.True(t, !handlerCalled)
|
||||||
|
|
||||||
|
// go to login page
|
||||||
|
loginURL := w.hdr.Get("Location")
|
||||||
|
r.URL = &url.URL{Path: loginURL}
|
||||||
|
handlerCalled = false
|
||||||
|
handler2(&w, &r)
|
||||||
|
assert.True(t, handlerCalled)
|
||||||
|
|
||||||
|
// perform login
|
||||||
|
cookie := httpCookie(loginJSON{Name: "name", Password: "password"})
|
||||||
|
assert.True(t, cookie != "")
|
||||||
|
|
||||||
|
// get /
|
||||||
|
handler2 = optionalAuth(handler)
|
||||||
|
w.hdr = make(http.Header)
|
||||||
|
r.Header.Set("Cookie", cookie)
|
||||||
|
r.URL = &url.URL{Path: "/"}
|
||||||
|
handlerCalled = false
|
||||||
|
handler2(&w, &r)
|
||||||
|
assert.True(t, handlerCalled)
|
||||||
|
r.Header.Del("Cookie")
|
||||||
|
|
||||||
|
// get / with basic auth
|
||||||
|
handler2 = optionalAuth(handler)
|
||||||
|
w.hdr = make(http.Header)
|
||||||
|
r.URL = &url.URL{Path: "/"}
|
||||||
|
r.SetBasicAuth("name", "password")
|
||||||
|
handlerCalled = false
|
||||||
|
handler2(&w, &r)
|
||||||
|
assert.True(t, handlerCalled)
|
||||||
|
r.Header.Del("Authorization")
|
||||||
|
|
||||||
|
// get login page with a valid cookie - we're redirected to /
|
||||||
|
handler2 = optionalAuth(handler)
|
||||||
|
w.hdr = make(http.Header)
|
||||||
|
r.Header.Set("Cookie", cookie)
|
||||||
|
r.URL = &url.URL{Path: loginURL}
|
||||||
|
handlerCalled = false
|
||||||
|
handler2(&w, &r)
|
||||||
|
assert.True(t, w.hdr.Get("Location") != "")
|
||||||
|
assert.True(t, !handlerCalled)
|
||||||
|
r.Header.Del("Cookie")
|
||||||
|
|
||||||
|
// get login page with an invalid cookie
|
||||||
|
handler2 = optionalAuth(handler)
|
||||||
|
w.hdr = make(http.Header)
|
||||||
|
r.Header.Set("Cookie", "bad")
|
||||||
|
r.URL = &url.URL{Path: loginURL}
|
||||||
|
handlerCalled = false
|
||||||
|
handler2(&w, &r)
|
||||||
|
assert.True(t, handlerCalled)
|
||||||
|
r.Header.Del("Cookie")
|
||||||
|
|
||||||
|
config.auth.Close()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue