diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index a0a65d73244..cadf6896bf4 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -21,7 +21,6 @@ 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/authtoken" "github.com/grafana/grafana/pkg/services/cache" "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/hooks" @@ -48,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 authtoken.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 models.UserTokenService `inject:""` } func (hs *HTTPServer) Init() error { diff --git a/pkg/api/login.go b/pkg/api/login.go index 48f8f237884..106a48dd6a8 100644 --- a/pkg/api/login.go +++ b/pkg/api/login.go @@ -5,8 +5,6 @@ import ( "net/http" "net/url" - "github.com/grafana/grafana/pkg/services/auth/authtoken" - "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/log" @@ -141,7 +139,7 @@ func (hs *HTTPServer) loginUserWithUser(user *m.User, c *m.ReqContext) { } func (hs *HTTPServer) Logout(c *m.ReqContext) { - if err := hs.AuthTokenService.RevokeToken(c.UserToken); err != nil && err != authtoken.ErrAuthTokenNotFound { + if err := hs.AuthTokenService.RevokeToken(c.UserToken); err != nil && err != m.ErrUserTokenNotFound { hs.log.Error("failed to revoke auth token", "error", err) } diff --git a/pkg/middleware/middleware.go b/pkg/middleware/middleware.go index 762a12d09d2..fa335eb10d9 100644 --- a/pkg/middleware/middleware.go +++ b/pkg/middleware/middleware.go @@ -10,7 +10,6 @@ import ( "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/authtoken" "github.com/grafana/grafana/pkg/services/session" "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/util" @@ -24,7 +23,7 @@ var ( ReqOrgAdmin = RoleAuth(m.ROLE_ADMIN) ) -func GetContextHandler(ats authtoken.UserAuthTokenService) macaron.Handler { +func GetContextHandler(ats m.UserTokenService) macaron.Handler { return func(c *macaron.Context) { ctx := &m.ReqContext{ Context: c, @@ -169,7 +168,7 @@ func initContextWithBasicAuth(ctx *m.ReqContext, orgId int64) bool { return true } -func initContextWithToken(authTokenService authtoken.UserAuthTokenService, ctx *m.ReqContext, orgID int64) bool { +func initContextWithToken(authTokenService m.UserTokenService, ctx *m.ReqContext, orgID int64) bool { rawToken := ctx.GetCookie(setting.LoginCookieName) if rawToken == "" { return false diff --git a/pkg/middleware/middleware_test.go b/pkg/middleware/middleware_test.go index 5852f9d0bcd..7908be6f225 100644 --- a/pkg/middleware/middleware_test.go +++ b/pkg/middleware/middleware_test.go @@ -11,7 +11,6 @@ import ( msession "github.com/go-macaron/session" "github.com/grafana/grafana/pkg/bus" m "github.com/grafana/grafana/pkg/models" - "github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/auth/authtoken" "github.com/grafana/grafana/pkg/services/session" "github.com/grafana/grafana/pkg/setting" @@ -157,8 +156,8 @@ func TestMiddlewareContext(t *testing.T) { return nil }) - sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (*auth.UserToken, error) { - return &auth.UserToken{ + sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (*m.UserToken, error) { + return &m.UserToken{ UserId: 12, UnhashedToken: unhashedToken, }, nil @@ -186,14 +185,14 @@ func TestMiddlewareContext(t *testing.T) { return nil }) - sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (*auth.UserToken, error) { - return &auth.UserToken{ + sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (*m.UserToken, error) { + return &m.UserToken{ UserId: 12, UnhashedToken: "", }, nil } - sc.userAuthTokenService.tryRotateTokenProvider = func(userToken *auth.UserToken, clientIP, userAgent string) (bool, error) { + sc.userAuthTokenService.tryRotateTokenProvider = func(userToken *m.UserToken, clientIP, userAgent string) (bool, error) { userToken.UnhashedToken = "rotated" return true, nil } @@ -228,7 +227,7 @@ func TestMiddlewareContext(t *testing.T) { middlewareScenario("Invalid/expired auth token in cookie", func(sc *scenarioContext) { sc.withTokenSessionCookie("token") - sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (*auth.UserToken, error) { + sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (*m.UserToken, error) { return nil, authtoken.ErrAuthTokenNotFound } @@ -680,47 +679,47 @@ type scenarioFunc func(c *scenarioContext) type handlerFunc func(c *m.ReqContext) type fakeUserAuthTokenService struct { - createTokenProvider func(userId int64, clientIP, userAgent string) (*auth.UserToken, error) - tryRotateTokenProvider func(token *auth.UserToken, clientIP, userAgent string) (bool, error) - lookupTokenProvider func(unhashedToken string) (*auth.UserToken, error) - revokeTokenProvider func(token *auth.UserToken) error + createTokenProvider func(userId int64, clientIP, userAgent string) (*m.UserToken, error) + tryRotateTokenProvider func(token *m.UserToken, clientIP, userAgent string) (bool, error) + lookupTokenProvider func(unhashedToken string) (*m.UserToken, error) + revokeTokenProvider func(token *m.UserToken) error } func newFakeUserAuthTokenService() *fakeUserAuthTokenService { return &fakeUserAuthTokenService{ - createTokenProvider: func(userId int64, clientIP, userAgent string) (*auth.UserToken, error) { - return &auth.UserToken{ + createTokenProvider: func(userId int64, clientIP, userAgent string) (*m.UserToken, error) { + return &m.UserToken{ UserId: 0, UnhashedToken: "", }, nil }, - tryRotateTokenProvider: func(token *auth.UserToken, clientIP, userAgent string) (bool, error) { + tryRotateTokenProvider: func(token *m.UserToken, clientIP, userAgent string) (bool, error) { return false, nil }, - lookupTokenProvider: func(unhashedToken string) (*auth.UserToken, error) { - return &auth.UserToken{ + lookupTokenProvider: func(unhashedToken string) (*m.UserToken, error) { + return &m.UserToken{ UserId: 0, UnhashedToken: "", }, nil }, - revokeTokenProvider: func(token *auth.UserToken) error { + revokeTokenProvider: func(token *m.UserToken) error { return nil }, } } -func (s *fakeUserAuthTokenService) CreateToken(userId int64, clientIP, userAgent string) (*auth.UserToken, error) { +func (s *fakeUserAuthTokenService) CreateToken(userId int64, clientIP, userAgent string) (*m.UserToken, error) { return s.createTokenProvider(userId, clientIP, userAgent) } -func (s *fakeUserAuthTokenService) LookupToken(unhashedToken string) (*auth.UserToken, error) { +func (s *fakeUserAuthTokenService) LookupToken(unhashedToken string) (*m.UserToken, error) { return s.lookupTokenProvider(unhashedToken) } -func (s *fakeUserAuthTokenService) TryRotateToken(token *auth.UserToken, clientIP, userAgent string) (bool, error) { +func (s *fakeUserAuthTokenService) TryRotateToken(token *m.UserToken, clientIP, userAgent string) (bool, error) { return s.tryRotateTokenProvider(token, clientIP, userAgent) } -func (s *fakeUserAuthTokenService) RevokeToken(token *auth.UserToken) error { +func (s *fakeUserAuthTokenService) RevokeToken(token *m.UserToken) error { return s.revokeTokenProvider(token) } diff --git a/pkg/middleware/org_redirect_test.go b/pkg/middleware/org_redirect_test.go index 0cc88016f3a..e01d1a68d21 100644 --- a/pkg/middleware/org_redirect_test.go +++ b/pkg/middleware/org_redirect_test.go @@ -3,8 +3,6 @@ package middleware import ( "testing" - "github.com/grafana/grafana/pkg/services/auth" - "fmt" "github.com/grafana/grafana/pkg/bus" @@ -26,8 +24,8 @@ func TestOrgRedirectMiddleware(t *testing.T) { return nil }) - sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (*auth.UserToken, error) { - return &auth.UserToken{ + sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (*m.UserToken, error) { + return &m.UserToken{ UserId: 0, UnhashedToken: "", }, nil @@ -52,8 +50,8 @@ func TestOrgRedirectMiddleware(t *testing.T) { return nil }) - sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (*auth.UserToken, error) { - return &auth.UserToken{ + sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (*m.UserToken, error) { + return &m.UserToken{ UserId: 12, UnhashedToken: "", }, nil diff --git a/pkg/middleware/quota_test.go b/pkg/middleware/quota_test.go index df2bf930426..e2a6ef63377 100644 --- a/pkg/middleware/quota_test.go +++ b/pkg/middleware/quota_test.go @@ -5,7 +5,6 @@ import ( "github.com/grafana/grafana/pkg/bus" 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/smartystreets/goconvey/convey" @@ -81,8 +80,8 @@ func TestMiddlewareQuota(t *testing.T) { return nil }) - sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (*auth.UserToken, error) { - return &auth.UserToken{ + sc.userAuthTokenService.lookupTokenProvider = func(unhashedToken string) (*m.UserToken, error) { + return &m.UserToken{ UserId: 12, UnhashedToken: "", }, nil diff --git a/pkg/models/context.go b/pkg/models/context.go index bba0024c0f2..b0c6ec9226d 100644 --- a/pkg/models/context.go +++ b/pkg/models/context.go @@ -4,7 +4,6 @@ import ( "strings" "github.com/grafana/grafana/pkg/log" - "github.com/grafana/grafana/pkg/services/auth" "github.com/grafana/grafana/pkg/services/session" "github.com/grafana/grafana/pkg/setting" "github.com/prometheus/client_golang/prometheus" @@ -14,7 +13,7 @@ import ( type ReqContext struct { *macaron.Context *SignedInUser - UserToken *auth.UserToken + UserToken *UserToken // This should only be used by the auth_proxy Session session.SessionStore diff --git a/pkg/models/user_token.go b/pkg/models/user_token.go new file mode 100644 index 00000000000..c8084cf1eba --- /dev/null +++ b/pkg/models/user_token.go @@ -0,0 +1,32 @@ +package models + +import "errors" + +// Typed errors +var ( + ErrUserTokenNotFound = errors.New("user token not found") +) + +// UserToken represents a user token +type UserToken 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 +} + +// UserTokenService are used for generating and validating user tokens +type UserTokenService interface { + CreateToken(userId int64, clientIP, userAgent string) (*UserToken, error) + LookupToken(unhashedToken string) (*UserToken, error) + TryRotateToken(token *UserToken, clientIP, userAgent string) (bool, error) + RevokeToken(token *UserToken) error +} diff --git a/pkg/services/auth/auth.go b/pkg/services/auth/auth.go index 727ceffff79..8832b06d188 100644 --- a/pkg/services/auth/auth.go +++ b/pkg/services/auth/auth.go @@ -1,16 +1 @@ package auth - -type UserToken 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 -} diff --git a/pkg/services/auth/authtoken/auth_token.go b/pkg/services/auth/authtoken/auth_token.go index a993a37dbf3..eedf38e8141 100644 --- a/pkg/services/auth/authtoken/auth_token.go +++ b/pkg/services/auth/authtoken/auth_token.go @@ -5,11 +5,10 @@ import ( "encoding/hex" "time" - "github.com/grafana/grafana/pkg/services/auth" - "github.com/grafana/grafana/pkg/infra/serverlock" "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" @@ -40,7 +39,7 @@ func (s *UserAuthTokenServiceImpl) Init() error { return nil } -func (s *UserAuthTokenServiceImpl) CreateToken(userId int64, clientIP, userAgent string) (*auth.UserToken, error) { +func (s *UserAuthTokenServiceImpl) CreateToken(userId int64, clientIP, userAgent string) (*models.UserToken, error) { clientIP = util.ParseIPAddress(clientIP) token, err := util.RandomHex(16) if err != nil { @@ -72,13 +71,13 @@ func (s *UserAuthTokenServiceImpl) CreateToken(userId int64, clientIP, userAgent s.log.Debug("user auth token created", "tokenId", userAuthToken.Id, "userId", userAuthToken.UserId, "clientIP", userAuthToken.ClientIp, "userAgent", userAuthToken.UserAgent, "authToken", userAuthToken.AuthToken) - var userToken auth.UserToken + var userToken models.UserToken err = userAuthToken.toUserToken(&userToken) return &userToken, err } -func (s *UserAuthTokenServiceImpl) LookupToken(unhashedToken string) (*auth.UserToken, error) { +func (s *UserAuthTokenServiceImpl) LookupToken(unhashedToken string) (*models.UserToken, error) { hashedToken := hashToken(unhashedToken) if setting.Env == setting.DEV { s.log.Debug("looking up token", "unhashed", unhashedToken, "hashed", hashedToken) @@ -137,13 +136,13 @@ func (s *UserAuthTokenServiceImpl) LookupToken(unhashedToken string) (*auth.User model.UnhashedToken = unhashedToken - var userToken auth.UserToken + var userToken models.UserToken err = model.toUserToken(&userToken) return &userToken, err } -func (s *UserAuthTokenServiceImpl) TryRotateToken(token *auth.UserToken, clientIP, userAgent string) (bool, error) { +func (s *UserAuthTokenServiceImpl) TryRotateToken(token *models.UserToken, clientIP, userAgent string) (bool, error) { if token == nil { return false, nil } @@ -202,7 +201,7 @@ func (s *UserAuthTokenServiceImpl) TryRotateToken(token *auth.UserToken, clientI return false, nil } -func (s *UserAuthTokenServiceImpl) RevokeToken(token *auth.UserToken) error { +func (s *UserAuthTokenServiceImpl) RevokeToken(token *models.UserToken) error { if token == nil { return ErrAuthTokenNotFound } diff --git a/pkg/services/auth/authtoken/auth_token_test.go b/pkg/services/auth/authtoken/auth_token_test.go index a1b70db60fb..3021b0efa4b 100644 --- a/pkg/services/auth/authtoken/auth_token_test.go +++ b/pkg/services/auth/authtoken/auth_token_test.go @@ -9,7 +9,7 @@ import ( "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/log" - "github.com/grafana/grafana/pkg/services/auth" + "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/sqlstore" . "github.com/smartystreets/goconvey/convey" ) @@ -163,7 +163,7 @@ func TestUserAuthToken(t *testing.T) { model, err := ctx.getAuthTokenByID(userToken.Id) So(err, ShouldBeNil) - var tok auth.UserToken + var tok models.UserToken model.toUserToken(&tok) getTime = func() time.Time { @@ -345,7 +345,7 @@ func TestUserAuthToken(t *testing.T) { }) Convey("When populating userAuthToken from UserToken should copy all properties", func() { - ut := auth.UserToken{ + ut := models.UserToken{ Id: 1, UserId: 2, AuthToken: "a", @@ -397,7 +397,7 @@ func TestUserAuthToken(t *testing.T) { So(err, ShouldBeNil) uatMap := uatJSON.MustMap() - var ut auth.UserToken + var ut models.UserToken err = uat.toUserToken(&ut) So(err, ShouldBeNil) utBytes, err := json.Marshal(ut) diff --git a/pkg/services/auth/authtoken/model.go b/pkg/services/auth/authtoken/model.go index 730f615e294..64123f02bc6 100644 --- a/pkg/services/auth/authtoken/model.go +++ b/pkg/services/auth/authtoken/model.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - "github.com/grafana/grafana/pkg/services/auth" + "github.com/grafana/grafana/pkg/models" ) // Typed errors @@ -27,13 +27,13 @@ type userAuthToken struct { UnhashedToken string `xorm:"-"` } -func userAuthTokenFromUserToken(ut *auth.UserToken) *userAuthToken { +func userAuthTokenFromUserToken(ut *models.UserToken) *userAuthToken { var uat userAuthToken uat.fromUserToken(ut) return &uat } -func (uat *userAuthToken) fromUserToken(ut *auth.UserToken) { +func (uat *userAuthToken) fromUserToken(ut *models.UserToken) { uat.Id = ut.Id uat.UserId = ut.UserId uat.AuthToken = ut.AuthToken @@ -48,7 +48,7 @@ func (uat *userAuthToken) fromUserToken(ut *auth.UserToken) { uat.UnhashedToken = ut.UnhashedToken } -func (uat *userAuthToken) toUserToken(ut *auth.UserToken) error { +func (uat *userAuthToken) toUserToken(ut *models.UserToken) error { if uat == nil { return fmt.Errorf("needs pointer to userAuthToken struct") } @@ -68,11 +68,3 @@ func (uat *userAuthToken) toUserToken(ut *auth.UserToken) error { return nil } - -// UserAuthTokenService are used for generating and validating user auth tokens -type UserAuthTokenService interface { - CreateToken(userId int64, clientIP, userAgent string) (*auth.UserToken, error) - LookupToken(unhashedToken string) (*auth.UserToken, error) - TryRotateToken(token *auth.UserToken, clientIP, userAgent string) (bool, error) - RevokeToken(token *auth.UserToken) error -}