auth_token_test.go 5.7 KB

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