You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

oauth_test.go 6.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package integrations
  5. import (
  6. "encoding/json"
  7. "testing"
  8. "github.com/stretchr/testify/assert"
  9. )
  10. const defaultAuthorize = "/login/oauth/authorize?client_id=da7da3ba-9a13-4167-856f-3899de0b0138&redirect_uri=a&response_type=code&state=thestate"
  11. func TestNoClientID(t *testing.T) {
  12. prepareTestEnv(t)
  13. req := NewRequest(t, "GET", "/login/oauth/authorize")
  14. ctx := loginUser(t, "user2")
  15. ctx.MakeRequest(t, req, 400)
  16. }
  17. func TestLoginRedirect(t *testing.T) {
  18. prepareTestEnv(t)
  19. req := NewRequest(t, "GET", "/login/oauth/authorize")
  20. assert.Contains(t, MakeRequest(t, req, 302).Body.String(), "/user/login")
  21. }
  22. func TestShowAuthorize(t *testing.T) {
  23. prepareTestEnv(t)
  24. req := NewRequest(t, "GET", defaultAuthorize)
  25. ctx := loginUser(t, "user4")
  26. resp := ctx.MakeRequest(t, req, 200)
  27. htmlDoc := NewHTMLParser(t, resp.Body)
  28. htmlDoc.AssertElement(t, "#authorize-app", true)
  29. htmlDoc.GetCSRF()
  30. }
  31. func TestRedirectWithExistingGrant(t *testing.T) {
  32. prepareTestEnv(t)
  33. req := NewRequest(t, "GET", defaultAuthorize)
  34. ctx := loginUser(t, "user1")
  35. resp := ctx.MakeRequest(t, req, 302)
  36. u, err := resp.Result().Location()
  37. assert.NoError(t, err)
  38. assert.Equal(t, "thestate", u.Query().Get("state"))
  39. assert.Truef(t, len(u.Query().Get("code")) > 30, "authorization code '%s' should be longer then 30", u.Query().Get("code"))
  40. }
  41. func TestAccessTokenExchange(t *testing.T) {
  42. prepareTestEnv(t)
  43. req := NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
  44. "grant_type": "authorization_code",
  45. "client_id": "da7da3ba-9a13-4167-856f-3899de0b0138",
  46. "client_secret": "4MK8Na6R55smdCY0WuCCumZ6hjRPnGY5saWVRHHjJiA=",
  47. "redirect_uri": "a",
  48. "code": "authcode",
  49. "code_verifier": "N1Zo9-8Rfwhkt68r1r29ty8YwIraXR8eh_1Qwxg7yQXsonBt", // test PKCE additionally
  50. })
  51. resp := MakeRequest(t, req, 200)
  52. type response struct {
  53. AccessToken string `json:"access_token"`
  54. TokenType string `json:"token_type"`
  55. ExpiresIn int64 `json:"expires_in"`
  56. RefreshToken string `json:"refresh_token"`
  57. }
  58. parsed := new(response)
  59. assert.NoError(t, json.Unmarshal(resp.Body.Bytes(), parsed))
  60. assert.True(t, len(parsed.AccessToken) > 10)
  61. assert.True(t, len(parsed.RefreshToken) > 10)
  62. }
  63. func TestAccessTokenExchangeWithoutPKCE(t *testing.T) {
  64. prepareTestEnv(t)
  65. req := NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
  66. "grant_type": "authorization_code",
  67. "client_id": "da7da3ba-9a13-4167-856f-3899de0b0138",
  68. "client_secret": "4MK8Na6R55smdCY0WuCCumZ6hjRPnGY5saWVRHHjJiA=",
  69. "redirect_uri": "a",
  70. "code": "authcode",
  71. })
  72. MakeRequest(t, req, 400)
  73. }
  74. func TestAccessTokenExchangeWithInvalidCredentials(t *testing.T) {
  75. prepareTestEnv(t)
  76. // invalid client id
  77. req := NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
  78. "grant_type": "authorization_code",
  79. "client_id": "???",
  80. "client_secret": "4MK8Na6R55smdCY0WuCCumZ6hjRPnGY5saWVRHHjJiA=",
  81. "redirect_uri": "a",
  82. "code": "authcode",
  83. "code_verifier": "N1Zo9-8Rfwhkt68r1r29ty8YwIraXR8eh_1Qwxg7yQXsonBt", // test PKCE additionally
  84. })
  85. MakeRequest(t, req, 400)
  86. // invalid client secret
  87. req = NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
  88. "grant_type": "authorization_code",
  89. "client_id": "da7da3ba-9a13-4167-856f-3899de0b0138",
  90. "client_secret": "???",
  91. "redirect_uri": "a",
  92. "code": "authcode",
  93. "code_verifier": "N1Zo9-8Rfwhkt68r1r29ty8YwIraXR8eh_1Qwxg7yQXsonBt", // test PKCE additionally
  94. })
  95. MakeRequest(t, req, 400)
  96. // invalid redirect uri
  97. req = NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
  98. "grant_type": "authorization_code",
  99. "client_id": "da7da3ba-9a13-4167-856f-3899de0b0138",
  100. "client_secret": "4MK8Na6R55smdCY0WuCCumZ6hjRPnGY5saWVRHHjJiA=",
  101. "redirect_uri": "???",
  102. "code": "authcode",
  103. "code_verifier": "N1Zo9-8Rfwhkt68r1r29ty8YwIraXR8eh_1Qwxg7yQXsonBt", // test PKCE additionally
  104. })
  105. MakeRequest(t, req, 400)
  106. // invalid authorization code
  107. req = NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
  108. "grant_type": "authorization_code",
  109. "client_id": "da7da3ba-9a13-4167-856f-3899de0b0138",
  110. "client_secret": "4MK8Na6R55smdCY0WuCCumZ6hjRPnGY5saWVRHHjJiA=",
  111. "redirect_uri": "a",
  112. "code": "???",
  113. "code_verifier": "N1Zo9-8Rfwhkt68r1r29ty8YwIraXR8eh_1Qwxg7yQXsonBt", // test PKCE additionally
  114. })
  115. MakeRequest(t, req, 400)
  116. // invalid grant_type
  117. req = NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
  118. "grant_type": "???",
  119. "client_id": "da7da3ba-9a13-4167-856f-3899de0b0138",
  120. "client_secret": "4MK8Na6R55smdCY0WuCCumZ6hjRPnGY5saWVRHHjJiA=",
  121. "redirect_uri": "a",
  122. "code": "authcode",
  123. "code_verifier": "N1Zo9-8Rfwhkt68r1r29ty8YwIraXR8eh_1Qwxg7yQXsonBt", // test PKCE additionally
  124. })
  125. MakeRequest(t, req, 400)
  126. }
  127. func TestAccessTokenExchangeWithBasicAuth(t *testing.T) {
  128. prepareTestEnv(t)
  129. req := NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
  130. "grant_type": "authorization_code",
  131. "redirect_uri": "a",
  132. "code": "authcode",
  133. "code_verifier": "N1Zo9-8Rfwhkt68r1r29ty8YwIraXR8eh_1Qwxg7yQXsonBt", // test PKCE additionally
  134. })
  135. req.Header.Add("Authorization", "Basic ZGE3ZGEzYmEtOWExMy00MTY3LTg1NmYtMzg5OWRlMGIwMTM4OjRNSzhOYTZSNTVzbWRDWTBXdUNDdW1aNmhqUlBuR1k1c2FXVlJISGpKaUE9")
  136. resp := MakeRequest(t, req, 200)
  137. type response struct {
  138. AccessToken string `json:"access_token"`
  139. TokenType string `json:"token_type"`
  140. ExpiresIn int64 `json:"expires_in"`
  141. RefreshToken string `json:"refresh_token"`
  142. }
  143. parsed := new(response)
  144. assert.NoError(t, json.Unmarshal(resp.Body.Bytes(), parsed))
  145. assert.True(t, len(parsed.AccessToken) > 10)
  146. assert.True(t, len(parsed.RefreshToken) > 10)
  147. // use wrong client_secret
  148. req = NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
  149. "grant_type": "authorization_code",
  150. "redirect_uri": "a",
  151. "code": "authcode",
  152. "code_verifier": "N1Zo9-8Rfwhkt68r1r29ty8YwIraXR8eh_1Qwxg7yQXsonBt", // test PKCE additionally
  153. })
  154. req.Header.Add("Authorization", "Basic ZGE3ZGEzYmEtOWExMy00MTY3LTg1NmYtMzg5OWRlMGIwMTM4OmJsYWJsYQ==")
  155. resp = MakeRequest(t, req, 400)
  156. // missing header
  157. req = NewRequestWithValues(t, "POST", "/login/oauth/access_token", map[string]string{
  158. "grant_type": "authorization_code",
  159. "redirect_uri": "a",
  160. "code": "authcode",
  161. "code_verifier": "N1Zo9-8Rfwhkt68r1r29ty8YwIraXR8eh_1Qwxg7yQXsonBt", // test PKCE additionally
  162. })
  163. resp = MakeRequest(t, req, 400)
  164. }