auth_test.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. package gold
  2. import (
  3. "crypto/sha1"
  4. "crypto/x509"
  5. "encoding/base64"
  6. "encoding/pem"
  7. "net/http"
  8. "strings"
  9. "testing"
  10. "time"
  11. "github.com/stretchr/testify/assert"
  12. )
  13. func TestUrlEncodeDecode(t *testing.T) {
  14. str := "test#me="
  15. dec, err := decodeQuery(encodeQuery(str))
  16. assert.NoError(t, err)
  17. assert.Equal(t, str, dec)
  18. }
  19. func TestNewSecureToken(t *testing.T) {
  20. tokenValues := map[string]string{
  21. "secret": string(handler.cookieSalt),
  22. }
  23. validity := 1 * time.Minute
  24. token, err := NewSecureToken("WWW-Authenticate", tokenValues, validity, handler)
  25. assert.NoError(t, err)
  26. assert.Equal(t, 184, len(token))
  27. }
  28. func TestParseBearerAuthorizationHeader(t *testing.T) {
  29. decoded := "MTQ5MzMyMDM2NHx1YVUxT21EYUkxSXZKZ29VdC03NjFibDkzZGx1WEtyUEVpM21XUnVUSGh2LUQtN0ZUTTV0REVPcjNSWEIwUm1Ob2FHMm83LVkxd3d5UGZiYTZUb0pUSmRoZFBwM1BCVWxJN1drbjFMaTZ2bHloc3FtbVJnSkxfN2MzNkQ3eGFpS3FPS2JTOGdCN3NlZnNmb2lncG13ZUdDaUtWLTBmQ3BCMEhDNmVMRUNaWDdzSjlfVXxU5vqaGdhcpGEl9-qrIs-GBl2HJCXwC85bCDr_zrmbjA=="
  30. encoded := "MTQ5MzMyMDM2NHx1YVUxT21EYUkxSXZKZ29VdC03NjFibDkzZGx1WEtyUEVpM21XUnVUSGh2LUQtN0ZUTTV0REVPcjNSWEIwUm1Ob2FHMm83LVkxd3d5UGZiYTZUb0pUSmRoZFBwM1BCVWxJN1drbjFMaTZ2bHloc3FtbVJnSkxfN2MzNkQ3eGFpS3FPS2JTOGdCN3NlZnNmb2lncG13ZUdDaUtWLTBmQ3BCMEhDNmVMRUNaWDdzSjlfVXxU5vqaGdhcpGEl9-qrIs-GBl2HJCXwC85bCDr_zrmbjA%3D%3D"
  31. assert.Equal(t, encoded, encodeQuery(decoded))
  32. dec, err := decodeQuery(encoded)
  33. assert.NoError(t, err)
  34. assert.Equal(t, decoded, dec)
  35. h := "Bearer " + encoded
  36. dec, err = ParseBearerAuthorizationHeader(h)
  37. assert.NoError(t, err)
  38. assert.Equal(t, decoded, dec)
  39. }
  40. func TestParseDigestAuthorizationHeader(t *testing.T) {
  41. h := "WebID-RSA source=\"http://server.org/\", username=\"http://example.org/\", nonce=\"string1\", sig=\"string2\""
  42. p, err := ParseDigestAuthorizationHeader(h)
  43. assert.NoError(t, err)
  44. assert.Equal(t, "WebID-RSA", p.Type)
  45. assert.Equal(t, "http://server.org/", p.Source)
  46. assert.Equal(t, "http://example.org/", p.Username)
  47. assert.Equal(t, "string1", p.Nonce)
  48. assert.Equal(t, "string2", p.Signature)
  49. h = "WebID-RSA source=\"http://server.org/\", \nusername=\"http://example.org/\", \nnonce=\"string1\",\n sig=\"string2\""
  50. p, err = ParseDigestAuthorizationHeader(h)
  51. assert.NoError(t, err)
  52. assert.Equal(t, "WebID-RSA", p.Type)
  53. assert.Equal(t, "http://server.org/", p.Source)
  54. assert.Equal(t, "http://example.org/", p.Username)
  55. assert.Equal(t, "string1", p.Nonce)
  56. assert.Equal(t, "string2", p.Signature)
  57. }
  58. func TestParseDigestAuthenticateHeader(t *testing.T) {
  59. h := `WebID-RSA source="http://server.org/", nonce="string1"`
  60. p, err := ParseDigestAuthenticateHeader(h)
  61. assert.NoError(t, err)
  62. assert.Equal(t, "WebID-RSA", p.Type)
  63. assert.Equal(t, "string1", p.Nonce)
  64. assert.Equal(t, "http://server.org/", p.Source)
  65. }
  66. func TestCookieAuth(t *testing.T) {
  67. request, err := http.NewRequest("MKCOL", testServer.URL+aclDir, nil)
  68. assert.NoError(t, err)
  69. response, err := user1h.Do(request)
  70. assert.NoError(t, err)
  71. response.Body.Close()
  72. assert.Equal(t, 201, response.StatusCode)
  73. request, err = http.NewRequest("PUT", testServer.URL+aclDir+"abc", strings.NewReader("<a> <b> <c> ."))
  74. assert.NoError(t, err)
  75. request.Header.Add("Content-Type", "text/turtle")
  76. response, err = user1h.Do(request)
  77. assert.NoError(t, err)
  78. response.Body.Close()
  79. assert.Equal(t, 201, response.StatusCode)
  80. request, err = http.NewRequest("HEAD", testServer.URL+aclDir+"abc", nil)
  81. assert.NoError(t, err)
  82. response, err = user1h.Do(request)
  83. assert.NoError(t, err)
  84. assert.Equal(t, 200, response.StatusCode)
  85. cookie1 := response.Header.Get("Set-Cookie")
  86. assert.NotNil(t, cookie1)
  87. acl := ParseLinkHeader(response.Header.Get("Link")).MatchRel("acl")
  88. assert.NotNil(t, acl)
  89. body := "<#Owner>" +
  90. " <http://www.w3.org/ns/auth/acl#accessTo> <" + aclDir + "abc>, <" + acl + ">;" +
  91. " <http://www.w3.org/ns/auth/acl#agent> <" + user1 + ">;" +
  92. " <http://www.w3.org/ns/auth/acl#mode> <http://www.w3.org/ns/auth/acl#Read>, <http://www.w3.org/ns/auth/acl#Write> ." +
  93. "<#Restricted>" +
  94. " <http://www.w3.org/ns/auth/acl#accessTo> <" + aclDir + "abc>;" +
  95. " <http://www.w3.org/ns/auth/acl#agent> <" + user2 + ">;" +
  96. " <http://www.w3.org/ns/auth/acl#mode> <http://www.w3.org/ns/auth/acl#Read>, <http://www.w3.org/ns/auth/acl#Write>."
  97. request, err = http.NewRequest("PUT", acl, strings.NewReader(body))
  98. assert.NoError(t, err)
  99. request.Header.Add("Content-Type", "text/turtle")
  100. response, err = user1h.Do(request)
  101. assert.NoError(t, err)
  102. response.Body.Close()
  103. assert.Equal(t, 201, response.StatusCode)
  104. request, err = http.NewRequest("HEAD", testServer.URL+aclDir+"abc", nil)
  105. assert.NoError(t, err)
  106. request.Header.Add("Cookie", cookie1)
  107. response, err = httpClient.Do(request)
  108. assert.NoError(t, err)
  109. assert.Equal(t, 200, response.StatusCode)
  110. request, err = http.NewRequest("HEAD", testServer.URL+aclDir+"abc", nil)
  111. assert.NoError(t, err)
  112. response, err = user1h.Do(request)
  113. assert.NoError(t, err)
  114. assert.Equal(t, 200, response.StatusCode)
  115. cookie2 := response.Header.Get("Set-Cookie")
  116. assert.NotNil(t, cookie2)
  117. request, err = http.NewRequest("HEAD", testServer.URL+aclDir+"abc", nil)
  118. assert.NoError(t, err)
  119. request.Header.Add("Cookie", cookie2)
  120. response, err = user2h.Do(request)
  121. assert.NoError(t, err)
  122. assert.Equal(t, 200, response.StatusCode)
  123. request, err = http.NewRequest("HEAD", testServer.URL+aclDir+"abc", nil)
  124. assert.NoError(t, err)
  125. response, err = httpClient.Do(request)
  126. assert.NoError(t, err)
  127. assert.Equal(t, 401, response.StatusCode)
  128. }
  129. func TestWebIDRSAAuth(t *testing.T) {
  130. request, err := http.NewRequest("GET", testServer.URL+aclDir+"abc", nil)
  131. assert.NoError(t, err)
  132. response, err := httpClient.Do(request)
  133. assert.NoError(t, err)
  134. assert.Equal(t, 401, response.StatusCode)
  135. wwwAuth := response.Header.Get("WWW-Authenticate")
  136. assert.NotEmpty(t, wwwAuth)
  137. p, _ := ParseDigestAuthenticateHeader(wwwAuth)
  138. // Load private key
  139. pKey := x509.MarshalPKCS1PrivateKey(user1k)
  140. keyBytes := pem.EncodeToMemory(&pem.Block{
  141. Type: "RSA PRIVATE KEY",
  142. Bytes: pKey,
  143. })
  144. signer, err := ParseRSAPrivatePEMKey(keyBytes)
  145. assert.NoError(t, err)
  146. claim := sha1.Sum([]byte(p.Source + user1 + p.Nonce))
  147. signed, err := signer.Sign(claim[:])
  148. assert.NoError(t, err)
  149. b64Sig := base64.StdEncoding.EncodeToString(signed)
  150. assert.NotEmpty(t, b64Sig)
  151. authHeader := `WebID-RSA source="` + p.Source + `", username="` + user1 + `", nonce="` + p.Nonce + `", sig="` + b64Sig + `"`
  152. request, err = http.NewRequest("GET", testServer.URL+aclDir+"abc", nil)
  153. request.Header.Add("Authorization", authHeader)
  154. assert.NoError(t, err)
  155. response, err = httpClient.Do(request)
  156. assert.NoError(t, err)
  157. assert.Equal(t, 200, response.StatusCode)
  158. }
  159. func TestWebIDRSAAuthBadSource(t *testing.T) {
  160. request, err := http.NewRequest("GET", testServer.URL+aclDir+"abc", nil)
  161. assert.NoError(t, err)
  162. response, err := httpClient.Do(request)
  163. assert.NoError(t, err)
  164. assert.Equal(t, 401, response.StatusCode)
  165. wwwAuth := response.Header.Get("WWW-Authenticate")
  166. assert.NotEmpty(t, wwwAuth)
  167. p, _ := ParseDigestAuthenticateHeader(wwwAuth)
  168. // Load private key
  169. pKey := x509.MarshalPKCS1PrivateKey(user1k)
  170. keyBytes := pem.EncodeToMemory(&pem.Block{
  171. Type: "RSA PRIVATE KEY",
  172. Bytes: pKey,
  173. })
  174. signer, err := ParseRSAPrivatePEMKey(keyBytes)
  175. assert.NoError(t, err)
  176. // Bad source
  177. claim := sha1.Sum([]byte("http://baddude.org/" + user1 + p.Nonce))
  178. signed, err := signer.Sign(claim[:])
  179. assert.NoError(t, err)
  180. b64Sig := base64.StdEncoding.EncodeToString(signed)
  181. assert.NotEmpty(t, b64Sig)
  182. authHeader := `WebID-RSA source="http://baddude.org/", username="` + user1 + `", nonce="` + p.Nonce + `", sig="` + b64Sig + `"`
  183. request, err = http.NewRequest("GET", testServer.URL+aclDir+"abc", nil)
  184. request.Header.Add("Authorization", authHeader)
  185. assert.NoError(t, err)
  186. response, err = httpClient.Do(request)
  187. assert.NoError(t, err)
  188. assert.Equal(t, 401, response.StatusCode)
  189. }
  190. func TestCleanupAuth(t *testing.T) {
  191. request, err := http.NewRequest("HEAD", testServer.URL+aclDir+"abc", nil)
  192. assert.NoError(t, err)
  193. response, err := user1h.Do(request)
  194. assert.NoError(t, err)
  195. assert.Equal(t, 200, response.StatusCode)
  196. acl := ParseLinkHeader(response.Header.Get("Link")).MatchRel("acl")
  197. request, err = http.NewRequest("DELETE", acl, nil)
  198. assert.NoError(t, err)
  199. response, err = user1h.Do(request)
  200. assert.NoError(t, err)
  201. response.Body.Close()
  202. assert.Equal(t, 200, response.StatusCode)
  203. request, err = http.NewRequest("DELETE", testServer.URL+aclDir+"abc", nil)
  204. assert.NoError(t, err)
  205. response, err = user1h.Do(request)
  206. assert.NoError(t, err)
  207. response.Body.Close()
  208. assert.Equal(t, 200, response.StatusCode)
  209. request, err = http.NewRequest("DELETE", testServer.URL+aclDir, nil)
  210. assert.NoError(t, err)
  211. response, err = user1h.Do(request)
  212. assert.NoError(t, err)
  213. response.Body.Close()
  214. assert.Equal(t, 200, response.StatusCode)
  215. }
  216. func TestACLCleanUsers(t *testing.T) {
  217. request, err := http.NewRequest("DELETE", testServer.URL+"/_test/user1", nil)
  218. assert.NoError(t, err)
  219. response, err := user1h.Do(request)
  220. assert.NoError(t, err)
  221. assert.Equal(t, 200, response.StatusCode)
  222. request, err = http.NewRequest("DELETE", testServer.URL+"/_test/user2", nil)
  223. assert.NoError(t, err)
  224. response, err = user1h.Do(request)
  225. assert.NoError(t, err)
  226. assert.Equal(t, 200, response.StatusCode)
  227. }