login users based on token cookie

This commit is contained in:
bergquist 2019-01-16 14:53:59 +01:00
parent 8764fb5aa6
commit aba6148c43
6 changed files with 95 additions and 61 deletions

View File

@ -11,16 +11,8 @@ import (
"path"
"time"
"github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
macaron "gopkg.in/macaron.v1"
"github.com/grafana/grafana/pkg/api/live"
"github.com/grafana/grafana/pkg/api/routing"
httpstatic "github.com/grafana/grafana/pkg/api/static"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
@ -29,11 +21,15 @@ import (
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/cache"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/hooks"
"github.com/grafana/grafana/pkg/services/rendering"
"github.com/grafana/grafana/pkg/setting"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
macaron "gopkg.in/macaron.v1"
)
func init() {
@ -226,7 +222,7 @@ func (hs *HTTPServer) addMiddlewaresAndStaticRoutes() {
m.Use(hs.healthHandler)
m.Use(hs.metricsEndpoint)
m.Use(middleware.GetContextHandler())
m.Use(middleware.GetContextHandler(hs.AuthTokenService))
m.Use(middleware.Sessioner(&setting.SessionOptions, setting.SessionConnMaxLifetime))
m.Use(middleware.OrgRedirect())

View File

@ -42,10 +42,10 @@ func (hs *HTTPServer) LoginView(c *m.ReqContext) {
return
}
if !hs.tryLoginUsingRememberCookie(c) {
c.HTML(200, ViewIndex, viewData)
return
}
//if !hs.tryLoginUsingRememberCookie(c) {
c.HTML(200, ViewIndex, viewData)
return
//}
if redirectTo, _ := url.QueryUnescape(c.GetCookie("redirect_to")); len(redirectTo) > 0 {
c.SetCookie("redirect_to", "", -1, setting.AppSubUrl+"/")

View File

@ -3,15 +3,15 @@ package middleware
import (
"strconv"
"gopkg.in/macaron.v1"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/apikeygen"
"github.com/grafana/grafana/pkg/log"
m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/session"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
"gopkg.in/macaron.v1"
)
var (
@ -21,7 +21,7 @@ var (
ReqOrgAdmin = RoleAuth(m.ROLE_ADMIN)
)
func GetContextHandler() macaron.Handler {
func GetContextHandler(ats *auth.UserAuthTokenService) macaron.Handler {
return func(c *macaron.Context) {
ctx := &m.ReqContext{
Context: c,
@ -49,7 +49,8 @@ func GetContextHandler() macaron.Handler {
case initContextWithApiKey(ctx):
case initContextWithBasicAuth(ctx, orgId):
case initContextWithAuthProxy(ctx, orgId):
case initContextWithUserSessionCookie(ctx, orgId):
//case initContextWithUserSessionCookie(ctx, orgId):
case initContextWithToken(ctx, orgId, ats):
case initContextWithAnonymousUser(ctx):
}
@ -58,6 +59,11 @@ func GetContextHandler() macaron.Handler {
c.Map(ctx)
c.Next()
//if signed in with token
//ats.RefreshToken()
// update last seen every 5min
if ctx.ShouldUpdateLastSeenAt() {
ctx.Logger.Debug("Updating last user_seen_at", "user_id", ctx.UserId)
@ -88,6 +94,25 @@ func initContextWithAnonymousUser(ctx *m.ReqContext) bool {
return true
}
func initContextWithToken(ctx *m.ReqContext, orgID int64, ts *auth.UserAuthTokenService) bool {
user, err := ts.LookupToken(ctx)
if err != nil {
ctx.Logger.Info("failed to look up user based on cookie")
return false
}
query := m.GetSignedInUserQuery{UserId: user.UserId, OrgId: orgID}
if err := bus.Dispatch(&query); err != nil {
ctx.Logger.Error("Failed to get user with id", "userId", user.UserId, "error", err)
return false
}
ctx.SignedInUser = query.Result
ctx.IsSignedIn = true
return true
}
func initContextWithUserSessionCookie(ctx *m.ReqContext, orgId int64) bool {
// initialize session
if err := ctx.Session.Start(ctx.Context); err != nil {

View File

@ -9,7 +9,6 @@ import (
"github.com/grafana/grafana/pkg/bus"
m "github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting"
"gopkg.in/macaron.v1"
)

View File

@ -3,16 +3,17 @@ package auth
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"net/http"
"net/url"
"time"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
macaron "gopkg.in/macaron.v1"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)
func init() {
@ -42,7 +43,15 @@ func (s *UserAuthTokenService) UserAuthenticatedHook(user *models.User, c *model
}
c.Resp.Header().Del("Set-Cookie")
c.SetCookie(sessionCookieKey, userToken.unhashedToken, setting.AppSubUrl+"/", setting.Domain, false, true)
cookie := http.Cookie{
Name: sessionCookieKey,
Value: url.QueryEscape(userToken.unhashedToken),
HttpOnly: true,
Expires: time.Now().Add(time.Minute * 10),
Domain: setting.Domain,
}
c.Resp.Header().Add("Set-Cookie", cookie.String())
return nil
}
@ -51,27 +60,27 @@ func (s *UserAuthTokenService) UserSignedOutHook(c *models.ReqContext) {
c.SetCookie(sessionCookieKey, "", -1, setting.AppSubUrl+"/", setting.Domain, false, true)
}
func (s *UserAuthTokenService) RequestMiddleware() macaron.Handler {
return func(ctx *models.ReqContext) {
authToken := ctx.GetCookie(sessionCookieKey)
userToken, err := s.lookupToken(authToken)
if err != nil {
// func (s *UserAuthTokenService) RequestMiddleware() macaron.Handler {
// return func(ctx *models.ReqContext) {
// authToken := ctx.GetCookie(sessionCookieKey)
// userToken, err := s.LookupToken(authToken)
// if err != nil {
}
// }
ctx.Next()
// ctx.Next()
refreshed, err := s.refreshToken(userToken, ctx.RemoteAddr(), ctx.Req.UserAgent())
if err != nil {
// refreshed, err := s.RefreshToken(userToken, ctx.RemoteAddr(), ctx.Req.UserAgent())
// if err != nil {
}
// }
if refreshed {
ctx.Resp.Header().Del("Set-Cookie")
ctx.SetCookie(sessionCookieKey, userToken.unhashedToken, setting.AppSubUrl+"/", setting.Domain, false, true)
}
}
}
// if refreshed {
// ctx.Resp.Header().Del("Set-Cookie")
// ctx.SetCookie(sessionCookieKey, userToken.unhashedToken, setting.AppSubUrl+"/", setting.Domain, false, true)
// }
// }
// }
func (s *UserAuthTokenService) CreateToken(userId int64, clientIP, userAgent string) (*userAuthToken, error) {
clientIP = util.ParseIPAddress(clientIP)
@ -104,7 +113,12 @@ func (s *UserAuthTokenService) CreateToken(userId int64, clientIP, userAgent str
return &userToken, nil
}
func (s *UserAuthTokenService) lookupToken(unhashedToken string) (*userAuthToken, error) {
func (s *UserAuthTokenService) LookupToken(ctx *models.ReqContext) (*userAuthToken, error) {
unhashedToken := ctx.GetCookie(sessionCookieKey)
if unhashedToken == "" {
return nil, fmt.Errorf("session token cookie is empty")
}
hashedToken := hashToken(unhashedToken)
var userToken userAuthToken
@ -157,7 +171,7 @@ func (s *UserAuthTokenService) lookupToken(unhashedToken string) (*userAuthToken
return &userToken, nil
}
func (s *UserAuthTokenService) refreshToken(token *userAuthToken, clientIP, userAgent string) (bool, error) {
func (s *UserAuthTokenService) RefreshToken(token *userAuthToken, clientIP, userAgent string) (bool, error) {
// lookup token in db
// refresh token if needed

View File

@ -27,22 +27,22 @@ func TestUserAuthToken(t *testing.T) {
So(token.AuthTokenSeen, ShouldBeFalse)
Convey("When lookup unhashed token should return user auth token", func() {
lookupToken, err := userAuthTokenService.lookupToken(token.unhashedToken)
LookupToken, err := userAuthTokenService.LookupToken(token.unhashedToken)
So(err, ShouldBeNil)
So(lookupToken, ShouldNotBeNil)
So(lookupToken.UserId, ShouldEqual, userID)
So(lookupToken.AuthTokenSeen, ShouldBeTrue)
So(LookupToken, ShouldNotBeNil)
So(LookupToken.UserId, ShouldEqual, userID)
So(LookupToken.AuthTokenSeen, ShouldBeTrue)
storedAuthToken, err := ctx.getAuthTokenByID(lookupToken.Id)
storedAuthToken, err := ctx.getAuthTokenByID(LookupToken.Id)
So(err, ShouldBeNil)
So(storedAuthToken, ShouldNotBeNil)
So(storedAuthToken.AuthTokenSeen, ShouldBeTrue)
})
Convey("When lookup hashed token should return user auth token not found error", func() {
lookupToken, err := userAuthTokenService.lookupToken(token.AuthToken)
LookupToken, err := userAuthTokenService.LookupToken(token.AuthToken)
So(err, ShouldEqual, ErrAuthTokenNotFound)
So(lookupToken, ShouldBeNil)
So(LookupToken, ShouldBeNil)
})
})
@ -51,25 +51,25 @@ func TestUserAuthToken(t *testing.T) {
So(err, ShouldBeNil)
So(token, ShouldNotBeNil)
_, err = userAuthTokenService.lookupToken(token.unhashedToken)
_, err = userAuthTokenService.LookupToken(token.unhashedToken)
So(err, ShouldBeNil)
token, err = ctx.getAuthTokenByID(token.Id)
So(err, ShouldBeNil)
// set now (now - 23 hours)
_, err = userAuthTokenService.refreshToken(token, "192.168.10.11:1234", "some user agent")
_, err = userAuthTokenService.RefreshToken(token, "192.168.10.11:1234", "some user agent")
So(err, ShouldBeNil)
_, err = userAuthTokenService.lookupToken(token.unhashedToken)
_, err = userAuthTokenService.LookupToken(token.unhashedToken)
So(err, ShouldBeNil)
stillGood, err := userAuthTokenService.lookupToken(token.unhashedToken)
stillGood, err := userAuthTokenService.LookupToken(token.unhashedToken)
So(err, ShouldBeNil)
So(stillGood, ShouldNotBeNil)
// set now (new - 2 hours)
notGood, err := userAuthTokenService.lookupToken(token.unhashedToken)
notGood, err := userAuthTokenService.LookupToken(token.unhashedToken)
So(err, ShouldEqual, ErrAuthTokenNotFound)
So(notGood, ShouldBeNil)
})
@ -82,7 +82,7 @@ func TestUserAuthToken(t *testing.T) {
prevToken := token.AuthToken
unhashedPrev := token.unhashedToken
refreshed, err := userAuthTokenService.refreshToken(token, "192.168.10.12:1234", "a new user agent")
refreshed, err := userAuthTokenService.RefreshToken(token, "192.168.10.12:1234", "a new user agent")
So(err, ShouldBeNil)
So(refreshed, ShouldBeFalse)
@ -95,7 +95,7 @@ func TestUserAuthToken(t *testing.T) {
return t
}
refreshed, err = userAuthTokenService.refreshToken(token, "192.168.10.12:1234", "a new user agent")
refreshed, err = userAuthTokenService.RefreshToken(token, "192.168.10.12:1234", "a new user agent")
So(err, ShouldBeNil)
So(refreshed, ShouldBeTrue)
@ -112,13 +112,13 @@ func TestUserAuthToken(t *testing.T) {
So(token.SeenAt, ShouldEqual, 0)
So(token.PrevAuthToken, ShouldEqual, prevToken)
lookedUp, err := userAuthTokenService.lookupToken(token.unhashedToken)
lookedUp, err := userAuthTokenService.LookupToken(token.unhashedToken)
So(err, ShouldBeNil)
So(lookedUp, ShouldNotBeNil)
So(lookedUp.AuthTokenSeen, ShouldBeTrue)
So(lookedUp.SeenAt, ShouldEqual, t.Unix())
lookedUp, err = userAuthTokenService.lookupToken(unhashedPrev)
lookedUp, err = userAuthTokenService.LookupToken(unhashedPrev)
So(err, ShouldBeNil)
So(lookedUp, ShouldNotBeNil)
So(lookedUp.Id, ShouldEqual, token.Id)
@ -127,7 +127,7 @@ func TestUserAuthToken(t *testing.T) {
return t.Add(2 * time.Minute)
}
lookedUp, err = userAuthTokenService.lookupToken(unhashedPrev)
lookedUp, err = userAuthTokenService.LookupToken(unhashedPrev)
So(err, ShouldBeNil)
So(lookedUp, ShouldNotBeNil)
@ -136,7 +136,7 @@ func TestUserAuthToken(t *testing.T) {
So(lookedUp, ShouldNotBeNil)
So(lookedUp.AuthTokenSeen, ShouldBeFalse)
refreshed, err = userAuthTokenService.refreshToken(token, "192.168.10.12:1234", "a new user agent")
refreshed, err = userAuthTokenService.RefreshToken(token, "192.168.10.12:1234", "a new user agent")
So(err, ShouldBeNil)
So(refreshed, ShouldBeTrue)