From 4452339bd174152c933c7d0e667860b7e90e38e2 Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Fri, 4 Nov 2016 15:20:31 +0000 Subject: [PATCH] Improve authentication blueprint --- web/auth.go | 99 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/web/auth.go b/web/auth.go index b4378b16..c05c3b7f 100644 --- a/web/auth.go +++ b/web/auth.go @@ -15,12 +15,16 @@ package web import ( + "fmt" + "bytes" "encoding/base64" "github.com/abcum/fibre" "github.com/abcum/surreal/cnf" "github.com/abcum/surreal/sql" + + "github.com/dgrijalva/jwt-go" ) func auth() fibre.MiddlewareFunc { @@ -33,18 +37,25 @@ func auth() fibre.MiddlewareFunc { conf := map[string]string{"NS": "", "DB": ""} c.Set("conf", conf) - // ------------------------------ - // Deny authentication - // ------------------------------ + // Start off with an authentication level + // which prevents running any sql queries, + // and denies access to all data. c.Set("kind", sql.AuthNO) - // ------------------------------ - // Root authentication - // ------------------------------ + // Check whether there is an Authorization + // header present, and if there is check + // whether it is a Basic Auth header. + + // Retrieve the HTTP Authorization header + // from the request, and continue. head := c.Request().Header().Get("Authorization") + // Check whether the Authorization header + // is a Basic Auth header, and if it is then + // process this as root authentication. + if head != "" && head[:5] == "Basic" { base, err := base64.StdEncoding.DecodeString(head[6:]) @@ -56,47 +67,75 @@ func auth() fibre.MiddlewareFunc { cred := bytes.SplitN(base, []byte(":"), 2) if len(cred) == 2 && bytes.Equal(cred[0], user) && bytes.Equal(cred[1], pass) { + + // ------------------------------ + // Root authentication + // ------------------------------ + c.Set("kind", sql.AuthKV) auth["NS"] = "*" // Anything allowed conf["NS"] = "" // Must specify auth["DB"] = "*" // Anything allowed conf["DB"] = "" // Must specify + return h(c) + } } } - // ------------------------------ - // Namespace authentication - // ------------------------------ + // Check whether the Authorization header + // is a Bearer Auth header, and if it is then + // process this as default authentication. - // c.Set("kind", sql.AuthNS) - // auth["NS"] = "SPECIFIED" // Not allowed to change - // conf["NS"] = "SPECIFIED" // Not allowed to change - // auth["DB"] = "*" // Anything allowed - // conf["DB"] = "" // Must specify + if head != "" && head[:6] == "Bearer" { - // ------------------------------ - // Database authentication - // ------------------------------ + token, err := jwt.Parse(head[7:], func(token *jwt.Token) (interface{}, error) { + if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { + return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) + } + return []byte(cnf.Settings.Auth.Token), nil + }) - // c.Set("kind", sql.AuthDB) - // auth["NS"] = "SPECIFIED" // Not allowed to change - // conf["NS"] = "SPECIFIED" // Not allowed to change - // auth["DB"] = "SPECIFIED" // Not allowed to change - // conf["DB"] = "SPECIFIED" // Not allowed to change + if err == nil && token.Valid { - // ------------------------------ - // Scoped authentication - // ------------------------------ + // ------------------------------ + // Namespace authentication + // ------------------------------ - // c.Set("kind", sql.AuthTB) - // auth["NS"] = "SPECIFIED" // Not allowed to change - // conf["NS"] = "SPECIFIED" // Not allowed to change - // auth["DB"] = "SPECIFIED" // Not allowed to change - // conf["DB"] = "SPECIFIED" // Not allowed to change + // c.Set("kind", sql.AuthNS) + // auth["NS"] = "SPECIFIED" // Not allowed to change + // conf["NS"] = "SPECIFIED" // Not allowed to change + // auth["DB"] = "*" // Anything allowed + // conf["DB"] = "" // Must specify + + // ------------------------------ + // Database authentication + // ------------------------------ + + // c.Set("kind", sql.AuthDB) + // auth["NS"] = "SPECIFIED" // Not allowed to change + // conf["NS"] = "SPECIFIED" // Not allowed to change + // auth["DB"] = "SPECIFIED" // Not allowed to change + // conf["DB"] = "SPECIFIED" // Not allowed to change + + // ------------------------------ + // Scoped authentication + // ------------------------------ + + // c.Set("kind", sql.AuthTB) + // auth["NS"] = "SPECIFIED" // Not allowed to change + // conf["NS"] = "SPECIFIED" // Not allowed to change + // auth["DB"] = "SPECIFIED" // Not allowed to change + // conf["DB"] = "SPECIFIED" // Not allowed to change + + return h(c) + + } + + } if c.Request().Header().Get("Upgrade") == "websocket" { return h(c)