auth

Paddy 2014-11-02 Parent:dd5d23d490ee Child:f97ca45d5657

64:c29c7df35905 Go to Latest

auth/http_test.go

Parse the redirect URI early, add new failure modes to tests. When obtaining a grant code, parse the redirect_uri early as a URL, so we can fail without even hitting the database, if possible. Add a test to cover the scenario where the client doesn't specify an endpoint, and the client has no endpoints registered. Add a test to cover the scenario where the client has two endpoints registered, but doesn't specify an endpoint. Fix the test that tested for invalid URLs by actually using an invalid URL. Apparently, "not a URL" is a valid URL. Go figure.

History
1 package auth
3 import (
4 "html/template"
5 "net/http"
6 "net/http/httptest"
7 "net/url"
8 "testing"
9 "time"
11 "code.secondbit.org/uuid"
12 )
14 const (
15 scopeSet = 1 << iota
16 stateSet
17 uriSet
18 )
20 func TestGetGrantCodeSuccess(t *testing.T) {
21 t.Parallel()
22 store := NewMemstore()
23 testContext := Context{
24 template: template.Must(template.New(getGrantTemplateName).Parse("Get auth grant")),
25 clients: store,
26 grants: store,
27 profiles: store,
28 tokens: store,
29 }
30 client := Client{
31 ID: uuid.NewID(),
32 Secret: "super secret!",
33 OwnerID: uuid.NewID(),
34 Name: "My test client",
35 Logo: "https://secondbit.org/logo.png",
36 Website: "https://secondbit.org",
37 Type: "public",
38 }
39 uri, err := url.Parse("https://test.secondbit.org/redirect")
40 if err != nil {
41 t.Fatal("Can't parse URL:", err)
42 }
43 endpoint := Endpoint{
44 ID: uuid.NewID(),
45 ClientID: client.ID,
46 URI: *uri,
47 Added: time.Now(),
48 }
49 err = testContext.SaveClient(client)
50 if err != nil {
51 t.Fatal("Can't store client:", err)
52 }
53 err = testContext.AddEndpoint(client.ID, endpoint)
54 if err != nil {
55 t.Fatal("Can't store endpoint:", err)
56 }
57 req, err := http.NewRequest("GET", "https://test.auth.secondbit.org/oauth2/grant", nil)
58 if err != nil {
59 t.Fatal("Can't build request:", err)
60 }
61 for i := 0; i < 1<<3; i++ {
62 w := httptest.NewRecorder()
63 params := url.Values{}
64 // see OAuth 2.0 spec, section 4.1.1
65 params.Set("response_type", "code")
66 params.Set("client_id", client.ID.String())
67 if i&uriSet != 0 {
68 params.Set("redirect_uri", endpoint.URI.String())
69 }
70 if i&scopeSet != 0 {
71 params.Set("scope", "testscope")
72 }
73 if i&stateSet != 0 {
74 params.Set("state", "my super secure state string")
75 }
76 req.URL.RawQuery = params.Encode()
77 GetGrantHandler(w, req, testContext)
78 if w.Code != http.StatusOK {
79 t.Errorf("Expected status code to be %d, got %d for %s", http.StatusOK, w.Code, req.URL.String())
80 }
81 if w.Body.String() != "Get auth grant" {
82 t.Errorf("Expected body to be `%s`, got `%s` for %s", "Get auth grant", w.Body.String(), req.URL.String())
83 }
84 }
85 }
87 func TestGetGrantCodeInvalidClient(t *testing.T) {
88 t.Parallel()
89 store := NewMemstore()
90 testContext := Context{
91 template: template.Must(template.New(getGrantTemplateName).Parse("{{ .error }}")),
92 clients: store,
93 grants: store,
94 profiles: store,
95 tokens: store,
96 }
97 client := Client{
98 ID: uuid.NewID(),
99 Secret: "super secret!",
100 OwnerID: uuid.NewID(),
101 Name: "My test client",
102 Type: "public",
103 }
104 err := testContext.SaveClient(client)
105 if err != nil {
106 t.Fatal("Can't store client:", err)
107 }
108 req, err := http.NewRequest("GET", "https://test.auth.secondbit.org/oauth2/grant", nil)
109 if err != nil {
110 t.Fatal("Can't build request:", err)
111 }
112 w := httptest.NewRecorder()
113 params := url.Values{}
114 params.Set("response_type", "code")
115 params.Set("redirect_uri", "https://test.secondbit.org/")
116 req.URL.RawQuery = params.Encode()
117 GetGrantHandler(w, req, testContext)
118 if w.Code != http.StatusBadRequest {
119 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code)
120 }
121 if w.Body.String() != "Client ID must be specified in the request." {
122 t.Errorf(`Expected output to be "%s", got "%s" instead.`, "Client ID must be specified in the request.", w.Body.String())
123 }
124 w = httptest.NewRecorder()
125 params.Set("client_id", "Not an ID")
126 req.URL.RawQuery = params.Encode()
127 GetGrantHandler(w, req, testContext)
128 if w.Code != http.StatusBadRequest {
129 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code)
130 }
131 if w.Body.String() != "client_id is not a valid Client ID." {
132 t.Errorf(`Expected output to be "%s", got "%s" instead.`, "client_id is not a valid Client ID.", w.Body.String())
133 }
134 w = httptest.NewRecorder()
135 params.Set("client_id", uuid.NewID().String())
136 req.URL.RawQuery = params.Encode()
137 GetGrantHandler(w, req, testContext)
138 if w.Code != http.StatusBadRequest {
139 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code)
140 }
141 if w.Body.String() != "The specified Client couldn&rsquo;t be found." {
142 t.Errorf(`Expected output to be "%s", got "%s" instead.`, "The specified Client couldn&rsquo;t be found.", w.Body.String())
143 }
144 }
146 func TestGetGrantCodeInvalidURI(t *testing.T) {
147 t.Parallel()
148 store := NewMemstore()
149 testContext := Context{
150 template: template.Must(template.New(getGrantTemplateName).Parse("{{ .error }}")),
151 clients: store,
152 grants: store,
153 profiles: store,
154 tokens: store,
155 }
156 client := Client{
157 ID: uuid.NewID(),
158 Secret: "super secret!",
159 OwnerID: uuid.NewID(),
160 Name: "My test client",
161 Type: "public",
162 }
163 uri, err := url.Parse("https://test.secondbit.org/redirect")
164 if err != nil {
165 t.Fatal("Can't parse URL:", err)
166 }
167 err = testContext.SaveClient(client)
168 if err != nil {
169 t.Fatal("Can't store client:", err)
170 }
171 req, err := http.NewRequest("GET", "https://test.auth.secondbit.org/oauth2/grant", nil)
172 if err != nil {
173 t.Fatal("Can't build request:", err)
174 }
175 w := httptest.NewRecorder()
176 params := url.Values{}
177 params.Set("response_type", "code")
178 params.Set("client_id", client.ID.String())
179 req.URL.RawQuery = params.Encode()
180 GetGrantHandler(w, req, testContext)
181 if w.Code != http.StatusBadRequest {
182 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code)
183 }
184 if w.Body.String() != "The redirect_uri specified is not valid." {
185 t.Errorf(`Expected output to be "%s", got "%s" instead.`, "The redirect_uri specified is not valid.", w.Body.String())
186 }
187 endpoint := Endpoint{
188 ID: uuid.NewID(),
189 ClientID: client.ID,
190 URI: *uri,
191 Added: time.Now(),
192 }
193 err = testContext.AddEndpoint(client.ID, endpoint)
194 if err != nil {
195 t.Fatal("Can't store endpoint:", err)
196 }
197 w = httptest.NewRecorder()
198 params.Set("redirect_uri", "https://test.secondbit.org/wrong")
199 req.URL.RawQuery = params.Encode()
200 GetGrantHandler(w, req, testContext)
201 if w.Code != http.StatusBadRequest {
202 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code)
203 }
204 if w.Body.String() != "The redirect_uri specified is not valid." {
205 t.Errorf(`Expected output to be "%s", got "%s" instead.`, "The redirect_uri specified is not valid.", w.Body.String())
206 }
207 endpoint2 := Endpoint{
208 ID: uuid.NewID(),
209 ClientID: client.ID,
210 URI: *uri,
211 Added: time.Now(),
212 }
213 err = testContext.AddEndpoint(client.ID, endpoint2)
214 if err != nil {
215 t.Fatal("Can't store endpoint:", err)
216 }
217 w = httptest.NewRecorder()
218 params.Set("redirect_uri", "")
219 req.URL.RawQuery = params.Encode()
220 GetGrantHandler(w, req, testContext)
221 if w.Code != http.StatusBadRequest {
222 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code)
223 }
224 if w.Body.String() != "The redirect_uri specified is not valid." {
225 t.Errorf(`Expected output to be "%s", got "%s" instead.`, "The redirect_uri specified is not valid.", w.Body.String())
226 }
227 w = httptest.NewRecorder()
228 params.Set("redirect_uri", "://not a URL")
229 req.URL.RawQuery = params.Encode()
230 GetGrantHandler(w, req, testContext)
231 if w.Code != http.StatusBadRequest {
232 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code)
233 }
234 if w.Body.String() != "The redirect_uri specified is not valid." {
235 t.Errorf(`Expected output to be "%s", got "%s" instead.`, "The redirect_uri specified is not valid.", w.Body.String())
236 }
237 }