Token-based authentication implemented

This commit is contained in:
Deluan 2016-03-24 19:00:28 -04:00
parent ea46c0a427
commit f58c5aa5a3
2 changed files with 39 additions and 11 deletions

View File

@ -1,10 +1,10 @@
package api
import (
"crypto/md5"
"encoding/hex"
"strings"
"fmt"
"strings"
"github.com/astaxie/beego"
"github.com/deluan/gosonic/api/responses"
@ -25,7 +25,7 @@ func Validate(controller BaseAPIController) {
}
func checkParameters(c BaseAPIController) {
requiredParameters := []string{"u", "p", "v", "c"}
requiredParameters := []string{"u", "v", "c"}
for _, p := range requiredParameters {
if c.GetString(p) == "" {
@ -33,18 +33,35 @@ func checkParameters(c BaseAPIController) {
abortRequest(c, responses.ErrorMissingParameter)
}
}
if c.GetString("p") == "" && (c.GetString("s") == "" || c.GetString("t") == "") {
logWarn(c, "Missing authentication information")
}
}
func authenticate(c BaseAPIController) {
password := beego.AppConfig.String("password")
user := c.GetString("u")
pass := c.GetString("p")
if strings.HasPrefix(pass, "enc:") {
e := strings.TrimPrefix(pass, "enc:")
if dec, err := hex.DecodeString(e); err == nil {
pass = string(dec)
salt := c.GetString("s")
token := c.GetString("t")
valid := false
switch {
case pass != "":
if strings.HasPrefix(pass, "enc:") {
e := strings.TrimPrefix(pass, "enc:")
if dec, err := hex.DecodeString(e); err == nil {
pass = string(dec)
}
}
valid = (pass == password)
case token != "":
t := fmt.Sprintf("%x", md5.Sum([]byte(password+salt)))
valid = (t == token)
}
if user != beego.AppConfig.String("user") || pass != beego.AppConfig.String("password") {
if user != beego.AppConfig.String("user") || !valid {
logWarn(c, fmt.Sprintf(`Invalid login for user "%s"`, user))
abortRequest(c, responses.ErrorAuthenticationFail)
}

View File

@ -2,6 +2,7 @@ package api_test
import (
"encoding/xml"
"fmt"
"testing"
"github.com/deluan/gosonic/api/responses"
@ -32,7 +33,7 @@ func TestCheckParams(t *testing.T) {
func TestAuthentication(t *testing.T) {
tests.Init(t, false)
Convey("Subject: Authentication\n", t, func() {
Convey("Subject: Authentication", t, func() {
_, w := Get("/rest/ping.view?u=INVALID&p=INVALID&c=test&v=1.0.0", "TestAuthentication")
Convey("Status code should be 200", func() {
So(w.Code, ShouldEqual, 200)
@ -46,7 +47,7 @@ func TestAuthentication(t *testing.T) {
So(v.Status, ShouldEqual, "fail")
})
})
Convey("Subject: Authentication Valid\n", t, func() {
Convey("Subject: Authentication Valid", t, func() {
_, w := Get("/rest/ping.view?u=deluan&p=wordpass&c=test&v=1.0.0", "TestAuthentication")
Convey("The status should be 'ok'", func() {
v := responses.Subsonic{}
@ -54,7 +55,7 @@ func TestAuthentication(t *testing.T) {
So(v.Status, ShouldEqual, "ok")
})
})
Convey("Subject: Password encoded\n", t, func() {
Convey("Subject: Password encoded", t, func() {
_, w := Get("/rest/ping.view?u=deluan&p=enc:776f726470617373&c=test&v=1.0.0", "TestAuthentication")
Convey("The status should be 'ok'", func() {
v := responses.Subsonic{}
@ -62,4 +63,14 @@ func TestAuthentication(t *testing.T) {
So(v.Status, ShouldEqual, "ok")
})
})
Convey("Subject: Token-based authentication", t, func() {
salt := "retnlmjetrymazgkt"
token := "23b342970e25c7928831c3317edd0b67"
_, w := Get(fmt.Sprintf("/rest/ping.view?u=deluan&s=%s&t=%s&c=test&v=1.0.0", salt, token), "TestAuthentication")
Convey("The status should be 'ok'", func() {
v := responses.Subsonic{}
xml.Unmarshal(w.Body.Bytes(), &v)
So(v.Status, ShouldEqual, "ok")
})
})
}