auth_token_test.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. package auth
  2. import (
  3. "testing"
  4. "time"
  5. "github.com/grafana/grafana/pkg/log"
  6. "github.com/grafana/grafana/pkg/models"
  7. "github.com/grafana/grafana/pkg/services/sqlstore"
  8. . "github.com/smartystreets/goconvey/convey"
  9. )
  10. func TestUserAuthToken(t *testing.T) {
  11. Convey("Test user auth token", t, func() {
  12. ctx := createTestContext(t)
  13. userAuthTokenService := ctx.tokenService
  14. userID := int64(10)
  15. t := time.Date(2018, 12, 13, 13, 45, 0, 0, time.UTC)
  16. now = func() time.Time {
  17. return t
  18. }
  19. Convey("When creating token", func() {
  20. token, err := userAuthTokenService.CreateToken(userID, "192.168.10.11:1234", "some user agent")
  21. So(err, ShouldBeNil)
  22. So(token, ShouldNotBeNil)
  23. So(token.AuthTokenSeen, ShouldBeFalse)
  24. Convey("When lookup unhashed token should return user auth token", func() {
  25. LookupToken, err := userAuthTokenService.LookupToken(token.UnhashedToken)
  26. So(err, ShouldBeNil)
  27. So(LookupToken, ShouldNotBeNil)
  28. So(LookupToken.UserId, ShouldEqual, userID)
  29. So(LookupToken.AuthTokenSeen, ShouldBeTrue)
  30. storedAuthToken, err := ctx.getAuthTokenByID(LookupToken.Id)
  31. So(err, ShouldBeNil)
  32. So(storedAuthToken, ShouldNotBeNil)
  33. So(storedAuthToken.AuthTokenSeen, ShouldBeTrue)
  34. })
  35. Convey("When lookup hashed token should return user auth token not found error", func() {
  36. LookupToken, err := userAuthTokenService.LookupToken(token.AuthToken)
  37. So(err, ShouldEqual, ErrAuthTokenNotFound)
  38. So(LookupToken, ShouldBeNil)
  39. })
  40. })
  41. Convey("expires correctly", func() {
  42. token, err := userAuthTokenService.CreateToken(userID, "192.168.10.11:1234", "some user agent")
  43. So(err, ShouldBeNil)
  44. So(token, ShouldNotBeNil)
  45. _, err = userAuthTokenService.LookupToken(token.UnhashedToken)
  46. So(err, ShouldBeNil)
  47. token, err = ctx.getAuthTokenByID(token.Id)
  48. So(err, ShouldBeNil)
  49. // set now (now - 23 hours)
  50. _, err = userAuthTokenService.RefreshToken(token, "192.168.10.11:1234", "some user agent")
  51. So(err, ShouldBeNil)
  52. _, err = userAuthTokenService.LookupToken(token.UnhashedToken)
  53. So(err, ShouldBeNil)
  54. stillGood, err := userAuthTokenService.LookupToken(token.UnhashedToken)
  55. So(err, ShouldBeNil)
  56. So(stillGood, ShouldNotBeNil)
  57. // set now (new - 2 hours)
  58. notGood, err := userAuthTokenService.LookupToken(token.UnhashedToken)
  59. So(err, ShouldEqual, ErrAuthTokenNotFound)
  60. So(notGood, ShouldBeNil)
  61. })
  62. Convey("can properly rotate tokens", func() {
  63. token, err := userAuthTokenService.CreateToken(userID, "192.168.10.11:1234", "some user agent")
  64. So(err, ShouldBeNil)
  65. So(token, ShouldNotBeNil)
  66. prevToken := token.AuthToken
  67. unhashedPrev := token.UnhashedToken
  68. refreshed, err := userAuthTokenService.RefreshToken(token, "192.168.10.12:1234", "a new user agent")
  69. So(err, ShouldBeNil)
  70. So(refreshed, ShouldBeFalse)
  71. ctx.markAuthTokenAsSeen(token.Id)
  72. token, err = ctx.getAuthTokenByID(token.Id)
  73. So(err, ShouldBeNil)
  74. // ability to auth using an old token
  75. now = func() time.Time {
  76. return t
  77. }
  78. refreshed, err = userAuthTokenService.RefreshToken(token, "192.168.10.12:1234", "a new user agent")
  79. So(err, ShouldBeNil)
  80. So(refreshed, ShouldBeTrue)
  81. unhashedToken := token.UnhashedToken
  82. token, err = ctx.getAuthTokenByID(token.Id)
  83. So(err, ShouldBeNil)
  84. token.UnhashedToken = unhashedToken
  85. So(token.RotatedAt, ShouldEqual, t.Unix())
  86. So(token.ClientIp, ShouldEqual, "192.168.10.12")
  87. So(token.UserAgent, ShouldEqual, "a new user agent")
  88. So(token.AuthTokenSeen, ShouldBeFalse)
  89. So(token.SeenAt, ShouldEqual, 0)
  90. So(token.PrevAuthToken, ShouldEqual, prevToken)
  91. lookedUp, err := userAuthTokenService.LookupToken(token.UnhashedToken)
  92. So(err, ShouldBeNil)
  93. So(lookedUp, ShouldNotBeNil)
  94. So(lookedUp.AuthTokenSeen, ShouldBeTrue)
  95. So(lookedUp.SeenAt, ShouldEqual, t.Unix())
  96. lookedUp, err = userAuthTokenService.LookupToken(unhashedPrev)
  97. So(err, ShouldBeNil)
  98. So(lookedUp, ShouldNotBeNil)
  99. So(lookedUp.Id, ShouldEqual, token.Id)
  100. now = func() time.Time {
  101. return t.Add(2 * time.Minute)
  102. }
  103. lookedUp, err = userAuthTokenService.LookupToken(unhashedPrev)
  104. So(err, ShouldBeNil)
  105. So(lookedUp, ShouldNotBeNil)
  106. lookedUp, err = ctx.getAuthTokenByID(lookedUp.Id)
  107. So(err, ShouldBeNil)
  108. So(lookedUp, ShouldNotBeNil)
  109. So(lookedUp.AuthTokenSeen, ShouldBeFalse)
  110. refreshed, err = userAuthTokenService.RefreshToken(token, "192.168.10.12:1234", "a new user agent")
  111. So(err, ShouldBeNil)
  112. So(refreshed, ShouldBeTrue)
  113. token, err = ctx.getAuthTokenByID(token.Id)
  114. So(err, ShouldBeNil)
  115. So(token, ShouldNotBeNil)
  116. So(token.SeenAt, ShouldEqual, 0)
  117. })
  118. Convey("keeps prev token valid for 1 minute after it is confirmed", func() {
  119. })
  120. Convey("will not mark token unseen when prev and current are the same", func() {
  121. })
  122. Reset(func() {
  123. now = time.Now
  124. })
  125. })
  126. }
  127. func createTestContext(t *testing.T) *testContext {
  128. t.Helper()
  129. sqlstore := sqlstore.InitTestDB(t)
  130. tokenService := &UserAuthTokenService{
  131. SQLStore: sqlstore,
  132. log: log.New("test-logger"),
  133. }
  134. RotateTime = 10 * time.Minute
  135. UrgentRotateTime = time.Minute
  136. return &testContext{
  137. sqlstore: sqlstore,
  138. tokenService: tokenService,
  139. }
  140. }
  141. type testContext struct {
  142. sqlstore *sqlstore.SqlStore
  143. tokenService *UserAuthTokenService
  144. }
  145. func (c *testContext) getAuthTokenByID(id int64) (*models.UserAuthToken, error) {
  146. sess := c.sqlstore.NewSession()
  147. var t models.UserAuthToken
  148. found, err := sess.ID(id).Get(&t)
  149. if err != nil || !found {
  150. return nil, err
  151. }
  152. return &t, nil
  153. }
  154. func (c *testContext) markAuthTokenAsSeen(id int64) (bool, error) {
  155. sess := c.sqlstore.NewSession()
  156. res, err := sess.Exec("UPDATE user_auth_token SET auth_token_seen = ? WHERE id = ?", c.sqlstore.Dialect.BooleanStr(true), id)
  157. if err != nil {
  158. return false, err
  159. }
  160. rowsAffected, err := res.RowsAffected()
  161. if err != nil {
  162. return false, err
  163. }
  164. return rowsAffected == 1, nil
  165. }