Browse Source

extract auth token interface and remove auth token from context

Marcus Efraimsson 7 years ago
parent
commit
4096449aec

+ 8 - 8
pkg/api/http_server.go

@@ -47,14 +47,14 @@ type HTTPServer struct {
 	streamManager *live.StreamManager
 	httpSrv       *http.Server
 
-	RouteRegister    routing.RouteRegister      `inject:""`
-	Bus              bus.Bus                    `inject:""`
-	RenderService    rendering.Service          `inject:""`
-	Cfg              *setting.Cfg               `inject:""`
-	HooksService     *hooks.HooksService        `inject:""`
-	CacheService     *cache.CacheService        `inject:""`
-	DatasourceCache  datasources.CacheService   `inject:""`
-	AuthTokenService *auth.UserAuthTokenService `inject:""`
+	RouteRegister    routing.RouteRegister     `inject:""`
+	Bus              bus.Bus                   `inject:""`
+	RenderService    rendering.Service         `inject:""`
+	Cfg              *setting.Cfg              `inject:""`
+	HooksService     *hooks.HooksService       `inject:""`
+	CacheService     *cache.CacheService       `inject:""`
+	DatasourceCache  datasources.CacheService  `inject:""`
+	AuthTokenService auth.UserAuthTokenService `inject:""`
 }
 
 func (hs *HTTPServer) Init() error {

+ 1 - 1
pkg/middleware/middleware.go

@@ -21,7 +21,7 @@ var (
 	ReqOrgAdmin     = RoleAuth(m.ROLE_ADMIN)
 )
 
-func GetContextHandler(ats *auth.UserAuthTokenService) macaron.Handler {
+func GetContextHandler(ats auth.UserAuthTokenService) macaron.Handler {
 	return func(c *macaron.Context) {
 		ctx := &m.ReqContext{
 			Context:        c,

+ 0 - 16
pkg/models/context.go

@@ -10,25 +10,9 @@ import (
 	"gopkg.in/macaron.v1"
 )
 
-type UserAuthToken struct {
-	Id            int64
-	UserId        int64
-	AuthToken     string
-	PrevAuthToken string
-	UserAgent     string
-	ClientIp      string
-	AuthTokenSeen bool
-	SeenAt        int64
-	RotatedAt     int64
-	CreatedAt     int64
-	UpdatedAt     int64
-	UnhashedToken string `xorm:"-"`
-}
-
 type ReqContext struct {
 	*macaron.Context
 	*SignedInUser
-	UserToken *UserAuthToken
 
 	Session session.SessionStore
 

+ 26 - 23
pkg/services/auth/auth_token.go

@@ -18,67 +18,72 @@ import (
 )
 
 func init() {
-	registry.RegisterService(&UserAuthTokenService{})
+	registry.RegisterService(&UserAuthTokenServiceImpl{})
 }
 
 var (
 	getTime          = time.Now
-	RotateTime       = 30 * time.Second
-	UrgentRotateTime = 10 * time.Second
+	RotateTime       = 2 * time.Minute
+	UrgentRotateTime = 20 * time.Second
 	oneYearInSeconds = 31557600 //used as default maxage for session cookies. We validate/rotate them more often.
 )
 
 // UserAuthTokenService are used for generating and validating user auth tokens
-type UserAuthTokenService struct {
+type UserAuthTokenService interface {
+	InitContextWithToken(ctx *models.ReqContext, orgID int64) bool
+	UserAuthenticatedHook(user *models.User, c *models.ReqContext) error
+	UserSignedOutHook(c *models.ReqContext)
+}
+
+type UserAuthTokenServiceImpl struct {
 	SQLStore          *sqlstore.SqlStore            `inject:""`
 	ServerLockService *serverlock.ServerLockService `inject:""`
 	log               log.Logger
 }
 
 // Init this service
-func (s *UserAuthTokenService) Init() error {
+func (s *UserAuthTokenServiceImpl) Init() error {
 	s.log = log.New("auth")
 	return nil
 }
 
-func (s *UserAuthTokenService) InitContextWithToken(ctx *models.ReqContext, orgID int64) bool {
+func (s *UserAuthTokenServiceImpl) InitContextWithToken(ctx *models.ReqContext, orgID int64) bool {
 	//auth User
 	unhashedToken := ctx.GetCookie(setting.SessionOptions.CookieName)
 	if unhashedToken == "" {
 		return false
 	}
 
-	user, err := s.LookupToken(unhashedToken)
+	userToken, err := s.LookupToken(unhashedToken)
 	if err != nil {
 		ctx.Logger.Info("failed to look up user based on cookie", "error", err)
 		return false
 	}
 
-	query := models.GetSignedInUserQuery{UserId: user.UserId, OrgId: orgID}
+	query := models.GetSignedInUserQuery{UserId: userToken.UserId, OrgId: orgID}
 	if err := bus.Dispatch(&query); err != nil {
-		ctx.Logger.Error("Failed to get user with id", "userId", user.UserId, "error", err)
+		ctx.Logger.Error("Failed to get user with id", "userId", userToken.UserId, "error", err)
 		return false
 	}
 
 	ctx.SignedInUser = query.Result
 	ctx.IsSignedIn = true
-	ctx.UserToken = user
 
 	//rotate session token if needed.
-	rotated, err := s.RefreshToken(ctx.UserToken, ctx.RemoteAddr(), ctx.Req.UserAgent())
+	rotated, err := s.RefreshToken(userToken, ctx.RemoteAddr(), ctx.Req.UserAgent())
 	if err != nil {
-		ctx.Logger.Error("failed to rotate token", "error", err, "user.id", user.UserId, "user_token.id", user.Id)
+		ctx.Logger.Error("failed to rotate token", "error", err, "userId", userToken.UserId, "tokenId", userToken.Id)
 		return true
 	}
 
 	if rotated {
-		s.writeSessionCookie(ctx, ctx.UserToken.UnhashedToken, oneYearInSeconds)
+		s.writeSessionCookie(ctx, userToken.UnhashedToken, oneYearInSeconds)
 	}
 
 	return true
 }
 
-func (s *UserAuthTokenService) writeSessionCookie(ctx *models.ReqContext, value string, maxAge int) {
+func (s *UserAuthTokenServiceImpl) writeSessionCookie(ctx *models.ReqContext, value string, maxAge int) {
 	ctx.Logger.Info("new token", "unhashed token", value)
 
 	ctx.Resp.Header().Del("Set-Cookie")
@@ -94,23 +99,21 @@ func (s *UserAuthTokenService) writeSessionCookie(ctx *models.ReqContext, value
 	http.SetCookie(ctx.Resp, &cookie)
 }
 
-func (s *UserAuthTokenService) UserAuthenticatedHook(user *models.User, c *models.ReqContext) error {
+func (s *UserAuthTokenServiceImpl) UserAuthenticatedHook(user *models.User, c *models.ReqContext) error {
 	userToken, err := s.CreateToken(user.Id, c.RemoteAddr(), c.Req.UserAgent())
 	if err != nil {
 		return err
 	}
 
-	c.UserToken = userToken
-
 	s.writeSessionCookie(c, userToken.UnhashedToken, oneYearInSeconds)
 	return nil
 }
 
-func (s *UserAuthTokenService) UserSignedOutHook(c *models.ReqContext) {
+func (s *UserAuthTokenServiceImpl) UserSignedOutHook(c *models.ReqContext) {
 	s.writeSessionCookie(c, "", -1)
 }
 
-func (s *UserAuthTokenService) CreateToken(userId int64, clientIP, userAgent string) (*models.UserAuthToken, error) {
+func (s *UserAuthTokenServiceImpl) CreateToken(userId int64, clientIP, userAgent string) (*userAuthToken, error) {
 	clientIP = util.ParseIPAddress(clientIP)
 	token, err := util.RandomHex(16)
 	if err != nil {
@@ -121,7 +124,7 @@ func (s *UserAuthTokenService) CreateToken(userId int64, clientIP, userAgent str
 
 	now := getTime().Unix()
 
-	userToken := models.UserAuthToken{
+	userToken := userAuthToken{
 		UserId:        userId,
 		AuthToken:     hashedToken,
 		PrevAuthToken: hashedToken,
@@ -143,11 +146,11 @@ func (s *UserAuthTokenService) CreateToken(userId int64, clientIP, userAgent str
 	return &userToken, nil
 }
 
-func (s *UserAuthTokenService) LookupToken(unhashedToken string) (*models.UserAuthToken, error) {
+func (s *UserAuthTokenServiceImpl) LookupToken(unhashedToken string) (*userAuthToken, error) {
 	hashedToken := hashToken(unhashedToken)
 	expireBefore := getTime().Add(time.Duration(-86400*setting.LogInRememberDays) * time.Second).Unix()
 
-	var userToken models.UserAuthToken
+	var userToken userAuthToken
 	exists, err := s.SQLStore.NewSession().Where("(auth_token = ? OR prev_auth_token = ?) AND created_at > ?", hashedToken, hashedToken, expireBefore).Get(&userToken)
 	if err != nil {
 		return nil, err
@@ -198,7 +201,7 @@ func (s *UserAuthTokenService) LookupToken(unhashedToken string) (*models.UserAu
 	return &userToken, nil
 }
 
-func (s *UserAuthTokenService) RefreshToken(token *models.UserAuthToken, clientIP, userAgent string) (bool, error) {
+func (s *UserAuthTokenServiceImpl) RefreshToken(token *userAuthToken, clientIP, userAgent string) (bool, error) {
 	if token == nil {
 		return false, nil
 	}

+ 4 - 5
pkg/services/auth/auth_token_test.go

@@ -7,7 +7,6 @@ import (
 	"github.com/grafana/grafana/pkg/setting"
 
 	"github.com/grafana/grafana/pkg/log"
-	"github.com/grafana/grafana/pkg/models"
 	"github.com/grafana/grafana/pkg/services/sqlstore"
 	. "github.com/smartystreets/goconvey/convey"
 )
@@ -290,7 +289,7 @@ func createTestContext(t *testing.T) *testContext {
 	t.Helper()
 
 	sqlstore := sqlstore.InitTestDB(t)
-	tokenService := &UserAuthTokenService{
+	tokenService := &UserAuthTokenServiceImpl{
 		SQLStore: sqlstore,
 		log:      log.New("test-logger"),
 	}
@@ -307,12 +306,12 @@ func createTestContext(t *testing.T) *testContext {
 
 type testContext struct {
 	sqlstore     *sqlstore.SqlStore
-	tokenService *UserAuthTokenService
+	tokenService *UserAuthTokenServiceImpl
 }
 
-func (c *testContext) getAuthTokenByID(id int64) (*models.UserAuthToken, error) {
+func (c *testContext) getAuthTokenByID(id int64) (*userAuthToken, error) {
 	sess := c.sqlstore.NewSession()
-	var t models.UserAuthToken
+	var t userAuthToken
 	found, err := sess.ID(id).Get(&t)
 	if err != nil || !found {
 		return nil, err

+ 14 - 14
pkg/services/auth/model.go

@@ -9,17 +9,17 @@ var (
 	ErrAuthTokenNotFound = errors.New("User auth token not found")
 )
 
-// type userAuthToken struct {
-// 	Id            int64
-// 	UserId        int64
-// 	AuthToken     string
-// 	PrevAuthToken string
-// 	UserAgent     string
-// 	ClientIp      string
-// 	AuthTokenSeen bool
-// 	SeenAt        int64
-// 	RotatedAt     int64
-// 	CreatedAt     int64
-// 	UpdatedAt     int64
-// 	unhashedToken string `xorm:"-"`
-// }
+type userAuthToken struct {
+	Id            int64
+	UserId        int64
+	AuthToken     string
+	PrevAuthToken string
+	UserAgent     string
+	ClientIp      string
+	AuthTokenSeen bool
+	SeenAt        int64
+	RotatedAt     int64
+	CreatedAt     int64
+	UpdatedAt     int64
+	UnhashedToken string `xorm:"-"`
+}

+ 2 - 2
pkg/services/auth/session_cleanup.go

@@ -5,7 +5,7 @@ import (
 	"time"
 )
 
-func (srv *UserAuthTokenService) Run(ctx context.Context) error {
+func (srv *UserAuthTokenServiceImpl) Run(ctx context.Context) error {
 	ticker := time.NewTicker(time.Hour * 12)
 	deleteSessionAfter := time.Hour * 24 * 7 * 30
 
@@ -22,7 +22,7 @@ func (srv *UserAuthTokenService) Run(ctx context.Context) error {
 	}
 }
 
-func (srv *UserAuthTokenService) deleteOldSession(deleteSessionAfter time.Duration) (int64, error) {
+func (srv *UserAuthTokenServiceImpl) deleteOldSession(deleteSessionAfter time.Duration) (int64, error) {
 	sql := `DELETE from user_auth_token WHERE rotated_at < ?`
 
 	deleteBefore := getTime().Add(-deleteSessionAfter)

+ 1 - 2
pkg/services/auth/session_cleanup_test.go

@@ -5,7 +5,6 @@ import (
 	"testing"
 	"time"
 
-	"github.com/grafana/grafana/pkg/models"
 	. "github.com/smartystreets/goconvey/convey"
 )
 
@@ -15,7 +14,7 @@ func TestUserAuthTokenCleanup(t *testing.T) {
 		ctx := createTestContext(t)
 
 		insertToken := func(token string, prev string, rotatedAt int64) {
-			ut := models.UserAuthToken{AuthToken: token, PrevAuthToken: prev, RotatedAt: rotatedAt, UserAgent: "", ClientIp: ""}
+			ut := userAuthToken{AuthToken: token, PrevAuthToken: prev, RotatedAt: rotatedAt, UserAgent: "", ClientIp: ""}
 			_, err := ctx.sqlstore.NewSession().Insert(&ut)
 			So(err, ShouldBeNil)
 		}