gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package auth_test
  4. import (
  5. "testing"
  6. auth_model "code.gitea.io/gitea/models/auth"
  7. "code.gitea.io/gitea/models/unittest"
  8. "github.com/stretchr/testify/assert"
  9. )
  10. func TestOAuth2Application_GenerateClientSecret(t *testing.T) {
  11. assert.NoError(t, unittest.PrepareTestDatabase())
  12. app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
  13. secret, err := app.GenerateClientSecret(t.Context())
  14. assert.NoError(t, err)
  15. assert.NotEmpty(t, secret)
  16. unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1, ClientSecret: app.ClientSecret})
  17. }
  18. func BenchmarkOAuth2Application_GenerateClientSecret(b *testing.B) {
  19. assert.NoError(b, unittest.PrepareTestDatabase())
  20. app := unittest.AssertExistsAndLoadBean(b, &auth_model.OAuth2Application{ID: 1})
  21. for b.Loop() {
  22. _, _ = app.GenerateClientSecret(b.Context())
  23. }
  24. }
  25. func TestOAuth2Application_ContainsRedirectURI(t *testing.T) {
  26. app := &auth_model.OAuth2Application{
  27. RedirectURIs: []string{"a", "b", "c"},
  28. }
  29. assert.True(t, app.ContainsRedirectURI("a"))
  30. assert.True(t, app.ContainsRedirectURI("b"))
  31. assert.True(t, app.ContainsRedirectURI("c"))
  32. assert.False(t, app.ContainsRedirectURI("d"))
  33. }
  34. func TestOAuth2Application_ContainsRedirectURI_WithPort(t *testing.T) {
  35. app := &auth_model.OAuth2Application{
  36. RedirectURIs: []string{"http://127.0.0.1/", "http://::1/", "http://192.168.0.1/", "http://intranet/", "https://127.0.0.1/"},
  37. ConfidentialClient: false,
  38. }
  39. // http loopback uris should ignore port
  40. // https://datatracker.ietf.org/doc/html/rfc8252#section-7.3
  41. assert.True(t, app.ContainsRedirectURI("http://127.0.0.1:3456/"))
  42. assert.True(t, app.ContainsRedirectURI("http://127.0.0.1/"))
  43. assert.True(t, app.ContainsRedirectURI("http://[::1]:3456/"))
  44. // not http
  45. assert.False(t, app.ContainsRedirectURI("https://127.0.0.1:3456/"))
  46. // not loopback
  47. assert.False(t, app.ContainsRedirectURI("http://192.168.0.1:9954/"))
  48. assert.False(t, app.ContainsRedirectURI("http://intranet:3456/"))
  49. // unparseable
  50. assert.False(t, app.ContainsRedirectURI(":"))
  51. }
  52. func TestOAuth2Application_ContainsRedirect_Slash(t *testing.T) {
  53. app := &auth_model.OAuth2Application{RedirectURIs: []string{"http://127.0.0.1"}}
  54. assert.True(t, app.ContainsRedirectURI("http://127.0.0.1"))
  55. assert.True(t, app.ContainsRedirectURI("http://127.0.0.1/"))
  56. assert.False(t, app.ContainsRedirectURI("http://127.0.0.1/other"))
  57. app = &auth_model.OAuth2Application{RedirectURIs: []string{"http://127.0.0.1/"}}
  58. assert.True(t, app.ContainsRedirectURI("http://127.0.0.1"))
  59. assert.True(t, app.ContainsRedirectURI("http://127.0.0.1/"))
  60. assert.False(t, app.ContainsRedirectURI("http://127.0.0.1/other"))
  61. }
  62. func TestOAuth2Application_ValidateClientSecret(t *testing.T) {
  63. assert.NoError(t, unittest.PrepareTestDatabase())
  64. app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
  65. secret, err := app.GenerateClientSecret(t.Context())
  66. assert.NoError(t, err)
  67. assert.True(t, app.ValidateClientSecret([]byte(secret)))
  68. assert.False(t, app.ValidateClientSecret([]byte("fewijfowejgfiowjeoifew")))
  69. }
  70. func TestGetOAuth2ApplicationByClientID(t *testing.T) {
  71. assert.NoError(t, unittest.PrepareTestDatabase())
  72. app, err := auth_model.GetOAuth2ApplicationByClientID(t.Context(), "da7da3ba-9a13-4167-856f-3899de0b0138")
  73. assert.NoError(t, err)
  74. assert.Equal(t, "da7da3ba-9a13-4167-856f-3899de0b0138", app.ClientID)
  75. app, err = auth_model.GetOAuth2ApplicationByClientID(t.Context(), "invalid client id")
  76. assert.Error(t, err)
  77. assert.Nil(t, app)
  78. }
  79. func TestCreateOAuth2Application(t *testing.T) {
  80. assert.NoError(t, unittest.PrepareTestDatabase())
  81. app, err := auth_model.CreateOAuth2Application(t.Context(), auth_model.CreateOAuth2ApplicationOptions{Name: "newapp", UserID: 1})
  82. assert.NoError(t, err)
  83. assert.Equal(t, "newapp", app.Name)
  84. assert.Len(t, app.ClientID, 36)
  85. unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{Name: "newapp"})
  86. }
  87. func TestOAuth2Application_TableName(t *testing.T) {
  88. assert.Equal(t, "oauth2_application", new(auth_model.OAuth2Application).TableName())
  89. }
  90. func TestOAuth2Application_GetGrantByUserID(t *testing.T) {
  91. assert.NoError(t, unittest.PrepareTestDatabase())
  92. app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
  93. grant, err := app.GetGrantByUserID(t.Context(), 1)
  94. assert.NoError(t, err)
  95. assert.Equal(t, int64(1), grant.UserID)
  96. grant, err = app.GetGrantByUserID(t.Context(), 34923458)
  97. assert.NoError(t, err)
  98. assert.Nil(t, grant)
  99. }
  100. func TestOAuth2Application_CreateGrant(t *testing.T) {
  101. assert.NoError(t, unittest.PrepareTestDatabase())
  102. app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
  103. grant, err := app.CreateGrant(t.Context(), 2, "")
  104. assert.NoError(t, err)
  105. assert.NotNil(t, grant)
  106. assert.Equal(t, int64(2), grant.UserID)
  107. assert.Equal(t, int64(1), grant.ApplicationID)
  108. assert.Empty(t, grant.Scope)
  109. }
  110. //////////////////// Grant
  111. func TestGetOAuth2GrantByID(t *testing.T) {
  112. assert.NoError(t, unittest.PrepareTestDatabase())
  113. grant, err := auth_model.GetOAuth2GrantByID(t.Context(), 1)
  114. assert.NoError(t, err)
  115. assert.Equal(t, int64(1), grant.ID)
  116. grant, err = auth_model.GetOAuth2GrantByID(t.Context(), 34923458)
  117. assert.NoError(t, err)
  118. assert.Nil(t, grant)
  119. }
  120. func TestOAuth2Grant_IncreaseCounter(t *testing.T) {
  121. assert.NoError(t, unittest.PrepareTestDatabase())
  122. grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 1})
  123. assert.NoError(t, grant.IncreaseCounter(t.Context()))
  124. assert.Equal(t, int64(2), grant.Counter)
  125. unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 2})
  126. }
  127. func TestOAuth2Grant_ScopeContains(t *testing.T) {
  128. assert.NoError(t, unittest.PrepareTestDatabase())
  129. grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Scope: "openid profile"})
  130. assert.True(t, grant.ScopeContains("openid"))
  131. assert.True(t, grant.ScopeContains("profile"))
  132. assert.False(t, grant.ScopeContains("profil"))
  133. assert.False(t, grant.ScopeContains("profile2"))
  134. }
  135. func TestOAuth2Grant_GenerateNewAuthorizationCode(t *testing.T) {
  136. assert.NoError(t, unittest.PrepareTestDatabase())
  137. grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1})
  138. code, err := grant.GenerateNewAuthorizationCode(t.Context(), "https://example2.com/callback", "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg", "S256")
  139. assert.NoError(t, err)
  140. assert.NotNil(t, code)
  141. assert.Greater(t, len(code.Code), 32) // secret length > 32
  142. }
  143. func TestOAuth2Grant_TableName(t *testing.T) {
  144. assert.Equal(t, "oauth2_grant", new(auth_model.OAuth2Grant).TableName())
  145. }
  146. func TestGetOAuth2GrantsByUserID(t *testing.T) {
  147. assert.NoError(t, unittest.PrepareTestDatabase())
  148. result, err := auth_model.GetOAuth2GrantsByUserID(t.Context(), 1)
  149. assert.NoError(t, err)
  150. assert.Len(t, result, 1)
  151. assert.Equal(t, int64(1), result[0].ID)
  152. assert.Equal(t, result[0].ApplicationID, result[0].Application.ID)
  153. result, err = auth_model.GetOAuth2GrantsByUserID(t.Context(), 34134)
  154. assert.NoError(t, err)
  155. assert.Empty(t, result)
  156. }
  157. func TestRevokeOAuth2Grant(t *testing.T) {
  158. assert.NoError(t, unittest.PrepareTestDatabase())
  159. assert.NoError(t, auth_model.RevokeOAuth2Grant(t.Context(), 1, 1))
  160. unittest.AssertNotExistsBean(t, &auth_model.OAuth2Grant{ID: 1, UserID: 1})
  161. }
  162. //////////////////// Authorization Code
  163. func TestGetOAuth2AuthorizationByCode(t *testing.T) {
  164. assert.NoError(t, unittest.PrepareTestDatabase())
  165. code, err := auth_model.GetOAuth2AuthorizationByCode(t.Context(), "authcode")
  166. assert.NoError(t, err)
  167. assert.NotNil(t, code)
  168. assert.Equal(t, "authcode", code.Code)
  169. assert.Equal(t, int64(1), code.ID)
  170. code, err = auth_model.GetOAuth2AuthorizationByCode(t.Context(), "does not exist")
  171. assert.NoError(t, err)
  172. assert.Nil(t, code)
  173. }
  174. func TestOAuth2AuthorizationCode_ValidateCodeChallenge(t *testing.T) {
  175. // test plain
  176. code := &auth_model.OAuth2AuthorizationCode{
  177. CodeChallengeMethod: "plain",
  178. CodeChallenge: "test123",
  179. }
  180. assert.True(t, code.ValidateCodeChallenge("test123"))
  181. assert.False(t, code.ValidateCodeChallenge("ierwgjoergjio"))
  182. // test S256
  183. code = &auth_model.OAuth2AuthorizationCode{
  184. CodeChallengeMethod: "S256",
  185. CodeChallenge: "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg",
  186. }
  187. assert.True(t, code.ValidateCodeChallenge("N1Zo9-8Rfwhkt68r1r29ty8YwIraXR8eh_1Qwxg7yQXsonBt"))
  188. assert.False(t, code.ValidateCodeChallenge("wiogjerogorewngoenrgoiuenorg"))
  189. // test unknown
  190. code = &auth_model.OAuth2AuthorizationCode{
  191. CodeChallengeMethod: "monkey",
  192. CodeChallenge: "foiwgjioriogeiogjerger",
  193. }
  194. assert.False(t, code.ValidateCodeChallenge("foiwgjioriogeiogjerger"))
  195. // test no code challenge
  196. code = &auth_model.OAuth2AuthorizationCode{
  197. CodeChallengeMethod: "",
  198. CodeChallenge: "foierjiogerogerg",
  199. }
  200. assert.True(t, code.ValidateCodeChallenge(""))
  201. }
  202. func TestOAuth2AuthorizationCode_GenerateRedirectURI(t *testing.T) {
  203. code := &auth_model.OAuth2AuthorizationCode{
  204. RedirectURI: "https://example.com/callback",
  205. Code: "thecode",
  206. }
  207. redirect, err := code.GenerateRedirectURI("thestate")
  208. assert.NoError(t, err)
  209. assert.Equal(t, "https://example.com/callback?code=thecode&state=thestate", redirect.String())
  210. redirect, err = code.GenerateRedirectURI("")
  211. assert.NoError(t, err)
  212. assert.Equal(t, "https://example.com/callback?code=thecode", redirect.String())
  213. }
  214. func TestOAuth2AuthorizationCode_Invalidate(t *testing.T) {
  215. assert.NoError(t, unittest.PrepareTestDatabase())
  216. code := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2AuthorizationCode{Code: "authcode"})
  217. assert.NoError(t, code.Invalidate(t.Context()))
  218. unittest.AssertNotExistsBean(t, &auth_model.OAuth2AuthorizationCode{Code: "authcode"})
  219. }
  220. func TestOAuth2AuthorizationCode_TableName(t *testing.T) {
  221. assert.Equal(t, "oauth2_authorization_code", new(auth_model.OAuth2AuthorizationCode).TableName())
  222. }