auth
auth/authcode_test.go
Implement an endpoint for token information. Implement an endpoint that allows us to look up information on a token. We strip the refresh token before the response is sent to avoid leaking the response token.
| paddy@29 | 1 package auth |
| paddy@29 | 2 |
| paddy@29 | 3 import ( |
| paddy@111 | 4 "bytes" |
| paddy@111 | 5 "io/ioutil" |
| paddy@111 | 6 "net/http" |
| paddy@111 | 7 "net/http/httptest" |
| paddy@111 | 8 "net/url" |
| paddy@156 | 9 "os" |
| paddy@111 | 10 "strings" |
| paddy@29 | 11 "testing" |
| paddy@29 | 12 "time" |
| paddy@29 | 13 |
| paddy@107 | 14 "code.secondbit.org/uuid.hg" |
| paddy@29 | 15 ) |
| paddy@29 | 16 |
| paddy@156 | 17 func init() { |
| paddy@156 | 18 if os.Getenv("PG_TEST_DB") != "" { |
| paddy@156 | 19 p, err := NewPostgres(os.Getenv("PG_TEST_DB")) |
| paddy@156 | 20 if err != nil { |
| paddy@156 | 21 panic(err) |
| paddy@156 | 22 } |
| paddy@156 | 23 authCodeStores = append(authCodeStores, &p) |
| paddy@156 | 24 } |
| paddy@156 | 25 } |
| paddy@156 | 26 |
| paddy@87 | 27 var authCodeStores = []authorizationCodeStore{NewMemstore()} |
| paddy@29 | 28 |
| paddy@87 | 29 func compareAuthorizationCodes(authCode1, authCode2 AuthorizationCode) (success bool, field string, authCode1val, authCode2val interface{}) { |
| paddy@87 | 30 if authCode1.Code != authCode2.Code { |
| paddy@87 | 31 return false, "code", authCode1.Code, authCode2.Code |
| paddy@34 | 32 } |
| paddy@87 | 33 if !authCode1.Created.Equal(authCode2.Created) { |
| paddy@87 | 34 return false, "created", authCode1.Created, authCode2.Created |
| paddy@34 | 35 } |
| paddy@87 | 36 if authCode1.ExpiresIn != authCode2.ExpiresIn { |
| paddy@87 | 37 return false, "expires in", authCode1.ExpiresIn, authCode2.ExpiresIn |
| paddy@34 | 38 } |
| paddy@87 | 39 if !authCode1.ClientID.Equal(authCode2.ClientID) { |
| paddy@87 | 40 return false, "client ID", authCode1.ClientID, authCode2.ClientID |
| paddy@34 | 41 } |
| paddy@135 | 42 if len(authCode1.Scopes) != len(authCode2.Scopes) { |
| paddy@135 | 43 return false, "scopes", authCode1.Scopes, authCode2.Scopes |
| paddy@135 | 44 } |
| paddy@135 | 45 for pos, scope := range authCode1.Scopes { |
| paddy@135 | 46 if scope != authCode2.Scopes[pos] { |
| paddy@135 | 47 return false, "scopes", authCode1.Scopes, authCode2.Scopes |
| paddy@135 | 48 } |
| paddy@34 | 49 } |
| paddy@87 | 50 if authCode1.RedirectURI != authCode2.RedirectURI { |
| paddy@87 | 51 return false, "redirect URI", authCode1.RedirectURI, authCode2.RedirectURI |
| paddy@34 | 52 } |
| paddy@87 | 53 if authCode1.State != authCode2.State { |
| paddy@87 | 54 return false, "state", authCode1.State, authCode2.State |
| paddy@34 | 55 } |
| paddy@111 | 56 if !authCode1.ProfileID.Equal(authCode2.ProfileID) { |
| paddy@111 | 57 return false, "profile ID", authCode1.ProfileID, authCode2.ProfileID |
| paddy@111 | 58 } |
| paddy@111 | 59 if authCode1.Used != authCode2.Used { |
| paddy@111 | 60 return false, "used", authCode1.Used, authCode2.Used |
| paddy@111 | 61 } |
| paddy@34 | 62 return true, "", nil, nil |
| paddy@34 | 63 } |
| paddy@34 | 64 |
| paddy@111 | 65 func TestAuthorizationCodeStore(t *testing.T) { |
| paddy@36 | 66 t.Parallel() |
| paddy@87 | 67 authCode := AuthorizationCode{ |
| paddy@29 | 68 Code: "code", |
| paddy@149 | 69 Created: time.Now().Round(time.Millisecond), |
| paddy@29 | 70 ExpiresIn: 180, |
| paddy@29 | 71 ClientID: uuid.NewID(), |
| paddy@163 | 72 Scopes: stringsToScopes([]string{"scope"}), |
| paddy@29 | 73 RedirectURI: "redirectURI", |
| paddy@29 | 74 State: "state", |
| paddy@29 | 75 } |
| paddy@87 | 76 for _, store := range authCodeStores { |
| paddy@116 | 77 context := Context{authCodes: store} |
| paddy@116 | 78 err := context.SaveAuthorizationCode(authCode) |
| paddy@29 | 79 if err != nil { |
| paddy@87 | 80 t.Errorf("Error saving auth code to %T: %s", store, err) |
| paddy@34 | 81 } |
| paddy@116 | 82 err = context.SaveAuthorizationCode(authCode) |
| paddy@87 | 83 if err != ErrAuthorizationCodeAlreadyExists { |
| paddy@87 | 84 t.Errorf("Expected ErrAuthorizationCodeAlreadyExists from %T, got %+v", store, err) |
| paddy@29 | 85 } |
| paddy@116 | 86 retrieved, err := context.GetAuthorizationCode(authCode.Code) |
| paddy@29 | 87 if err != nil { |
| paddy@87 | 88 t.Errorf("Error retrieving auth code from %T: %s", store, err) |
| paddy@29 | 89 } |
| paddy@87 | 90 match, field, expectation, result := compareAuthorizationCodes(authCode, retrieved) |
| paddy@34 | 91 if !match { |
| paddy@87 | 92 t.Errorf("Expected `%v` in the `%s` field of auth code retrieved from %T, got `%v`", expectation, field, store, result) |
| paddy@34 | 93 } |
| paddy@116 | 94 err = context.UseAuthorizationCode(authCode.Code) |
| paddy@111 | 95 if err != nil { |
| paddy@111 | 96 t.Errorf("Error retrieving auth code from %T: %s", store, err) |
| paddy@111 | 97 } |
| paddy@116 | 98 retrieved, err = context.GetAuthorizationCode(authCode.Code) |
| paddy@111 | 99 if err != nil { |
| paddy@111 | 100 t.Errorf("Error retrieving auth code from %T: %s", store, err) |
| paddy@111 | 101 } |
| paddy@111 | 102 authCode.Used = true |
| paddy@111 | 103 match, field, expectation, result = compareAuthorizationCodes(authCode, retrieved) |
| paddy@111 | 104 if !match { |
| paddy@111 | 105 t.Errorf("Expected `%v` in the `%s` field of auth code retrieved from %T, got `%v`", expectation, field, store, result) |
| paddy@111 | 106 } |
| paddy@116 | 107 err = context.DeleteAuthorizationCode(authCode.Code) |
| paddy@29 | 108 if err != nil { |
| paddy@87 | 109 t.Errorf("Error removing auth code from %T: %s", store, err) |
| paddy@29 | 110 } |
| paddy@116 | 111 retrieved, err = context.GetAuthorizationCode(authCode.Code) |
| paddy@87 | 112 if err != ErrAuthorizationCodeNotFound { |
| paddy@87 | 113 t.Errorf("Expected ErrAuthorizationCodeNotFound from %T, got %+v and %+v", store, retrieved, err) |
| paddy@34 | 114 } |
| paddy@116 | 115 err = context.DeleteAuthorizationCode(authCode.Code) |
| paddy@87 | 116 if err != ErrAuthorizationCodeNotFound { |
| paddy@87 | 117 t.Errorf("Expected ErrAuthorizationCodeNotFound from %T, got %+v", store, err) |
| paddy@29 | 118 } |
| paddy@116 | 119 err = context.UseAuthorizationCode(authCode.Code) |
| paddy@111 | 120 if err != ErrAuthorizationCodeNotFound { |
| paddy@111 | 121 t.Errorf("Expected ErrAuthorizationCodeNotFound from %T, got %+v", store, err) |
| paddy@111 | 122 } |
| paddy@29 | 123 } |
| paddy@29 | 124 } |
| paddy@111 | 125 |
| paddy@111 | 126 func TestAuthCodeGrantValidate(t *testing.T) { |
| paddy@111 | 127 t.Parallel() |
| paddy@111 | 128 store := NewMemstore() |
| paddy@111 | 129 testContext := Context{ |
| paddy@111 | 130 clients: store, |
| paddy@111 | 131 authCodes: store, |
| paddy@111 | 132 profiles: store, |
| paddy@111 | 133 tokens: store, |
| paddy@111 | 134 sessions: store, |
| paddy@111 | 135 } |
| paddy@111 | 136 client := Client{ |
| paddy@111 | 137 ID: uuid.NewID(), |
| paddy@111 | 138 Secret: "super secret!", |
| paddy@111 | 139 OwnerID: uuid.NewID(), |
| paddy@111 | 140 Name: "My test client", |
| paddy@111 | 141 Logo: "https://secondbit.org/logo.png", |
| paddy@111 | 142 Website: "https://secondbit.org/", |
| paddy@111 | 143 Type: "public", |
| paddy@111 | 144 } |
| paddy@111 | 145 endpoint := Endpoint{ |
| paddy@111 | 146 ID: uuid.NewID(), |
| paddy@111 | 147 ClientID: client.ID, |
| paddy@116 | 148 URI: "https://test.secondbit.org/redirect", |
| paddy@149 | 149 Added: time.Now().Round(time.Millisecond), |
| paddy@111 | 150 } |
| paddy@116 | 151 err := testContext.SaveClient(client) |
| paddy@111 | 152 if err != nil { |
| paddy@111 | 153 t.Fatal("Can't store client:", err) |
| paddy@111 | 154 } |
| paddy@151 | 155 err = testContext.AddEndpoints([]Endpoint{endpoint}) |
| paddy@111 | 156 if err != nil { |
| paddy@111 | 157 t.Fatal("Can't store endpoint:", err) |
| paddy@111 | 158 } |
| paddy@111 | 159 code := AuthorizationCode{ |
| paddy@111 | 160 Code: "myauthcode", |
| paddy@149 | 161 Created: time.Now().Round(time.Millisecond), |
| paddy@111 | 162 ExpiresIn: 180, |
| paddy@111 | 163 ClientID: uuid.NewID(), |
| paddy@163 | 164 Scopes: stringsToScopes([]string{"scope"}), |
| paddy@111 | 165 RedirectURI: "redirectURI", |
| paddy@111 | 166 State: "state", |
| paddy@111 | 167 } |
| paddy@111 | 168 err = testContext.SaveAuthorizationCode(code) |
| paddy@111 | 169 if err != nil { |
| paddy@111 | 170 t.Fatal("Can't add auth code:", err) |
| paddy@111 | 171 } |
| paddy@112 | 172 code2 := code |
| paddy@112 | 173 code2.Code = "otherauthcode" |
| paddy@112 | 174 code2.ClientID = client.ID |
| paddy@112 | 175 err = testContext.SaveAuthorizationCode(code2) |
| paddy@112 | 176 if err != nil { |
| paddy@112 | 177 t.Fatal("Can't add second auth code:", err) |
| paddy@112 | 178 } |
| paddy@111 | 179 req, err := http.NewRequest("POST", "https://test.auth.secondbit.org/oauth2/grant", nil) |
| paddy@111 | 180 if err != nil { |
| paddy@111 | 181 t.Fatal("Can't build request:", err) |
| paddy@111 | 182 } |
| paddy@112 | 183 req.Header.Set("Content-Type", "application/x-www-form-urlencoded") |
| paddy@111 | 184 w := httptest.NewRecorder() |
| paddy@111 | 185 params := url.Values{} |
| paddy@111 | 186 body := bytes.NewBufferString(params.Encode()) |
| paddy@111 | 187 req.Body = ioutil.NopCloser(body) |
| paddy@111 | 188 scope, profileID, valid := authCodeGrantValidate(w, req, testContext) |
| paddy@111 | 189 if valid { |
| paddy@112 | 190 t.Fatalf("Expected invalid auth code, got scope `%s` and profileID `%s`.", scope, profileID) |
| paddy@111 | 191 } |
| paddy@111 | 192 if w.Code != http.StatusBadRequest { |
| paddy@111 | 193 t.Errorf("Expected status %d, got %d", http.StatusBadRequest, w.Code) |
| paddy@111 | 194 } |
| paddy@112 | 195 expectedBody := `{"error":"invalid_request"}` |
| paddy@112 | 196 if strings.TrimSpace(w.Body.String()) != expectedBody { |
| paddy@112 | 197 t.Errorf("Expected body of `%s`, got `%s`", expectedBody, strings.TrimSpace(w.Body.String())) |
| paddy@112 | 198 } |
| paddy@112 | 199 |
| paddy@112 | 200 req, err = http.NewRequest("POST", "https://test.auth.secondbit.org/oauth2/grant", nil) |
| paddy@112 | 201 if err != nil { |
| paddy@112 | 202 t.Fatal("Can't build request:", err) |
| paddy@112 | 203 } |
| paddy@112 | 204 req.Header.Set("Content-Type", "application/x-www-form-urlencoded") |
| paddy@112 | 205 w = httptest.NewRecorder() |
| paddy@112 | 206 params = url.Values{} |
| paddy@112 | 207 params.Set("code", "notmycode") |
| paddy@112 | 208 body = bytes.NewBufferString(params.Encode()) |
| paddy@112 | 209 req.Body = ioutil.NopCloser(body) |
| paddy@112 | 210 err = req.ParseForm() |
| paddy@112 | 211 if err != nil { |
| paddy@112 | 212 t.Log(err) |
| paddy@112 | 213 } |
| paddy@112 | 214 scope, profileID, valid = authCodeGrantValidate(w, req, testContext) |
| paddy@112 | 215 if valid { |
| paddy@112 | 216 t.Fatalf("Expected invalid auth code, got scope `%s` and profileID `%s`.", scope, profileID) |
| paddy@112 | 217 } |
| paddy@112 | 218 if w.Code != http.StatusUnauthorized { |
| paddy@112 | 219 t.Errorf("Expected status %d, got %d", http.StatusUnauthorized, w.Code) |
| paddy@112 | 220 } |
| paddy@112 | 221 expectedBody = `{"error":"invalid_client"}` |
| paddy@112 | 222 if expectedBody != strings.TrimSpace(w.Body.String()) { |
| paddy@112 | 223 t.Errorf("Expected body of `%s`, got `%s`", expectedBody, strings.TrimSpace(w.Body.String())) |
| paddy@112 | 224 } |
| paddy@112 | 225 |
| paddy@112 | 226 req, err = http.NewRequest("POST", "https://test.auth.secondbit.org/oauth2/grant", nil) |
| paddy@112 | 227 if err != nil { |
| paddy@112 | 228 t.Fatal("Can't build request:", err) |
| paddy@112 | 229 } |
| paddy@112 | 230 req.Header.Set("Content-Type", "application/x-www-form-urlencoded") |
| paddy@112 | 231 req.SetBasicAuth(client.ID.String(), client.Secret) |
| paddy@112 | 232 w = httptest.NewRecorder() |
| paddy@112 | 233 params = url.Values{} |
| paddy@112 | 234 params.Set("code", "notmycode") |
| paddy@112 | 235 body = bytes.NewBufferString(params.Encode()) |
| paddy@112 | 236 req.Body = ioutil.NopCloser(body) |
| paddy@112 | 237 err = req.ParseForm() |
| paddy@112 | 238 if err != nil { |
| paddy@112 | 239 t.Log(err) |
| paddy@112 | 240 } |
| paddy@112 | 241 scope, profileID, valid = authCodeGrantValidate(w, req, testContext) |
| paddy@112 | 242 if valid { |
| paddy@112 | 243 t.Fatalf("Expected invalid auth code, got scope `%s` and profileID `%s`.", scope, profileID) |
| paddy@112 | 244 } |
| paddy@112 | 245 if w.Code != http.StatusBadRequest { |
| paddy@112 | 246 t.Errorf("Expected status %d, got %d", http.StatusUnauthorized, w.Code) |
| paddy@112 | 247 } |
| paddy@112 | 248 expectedBody = `{"error":"invalid_grant"}` |
| paddy@112 | 249 if expectedBody != strings.TrimSpace(w.Body.String()) { |
| paddy@112 | 250 t.Errorf("Expected body of `%s`, got `%s`", expectedBody, strings.TrimSpace(w.Body.String())) |
| paddy@112 | 251 } |
| paddy@112 | 252 |
| paddy@112 | 253 req, err = http.NewRequest("POST", "https://test.auth.secondbit.org/oauth2/grant", nil) |
| paddy@112 | 254 if err != nil { |
| paddy@112 | 255 t.Fatal("Can't build request:", err) |
| paddy@112 | 256 } |
| paddy@112 | 257 req.Header.Set("Content-Type", "application/x-www-form-urlencoded") |
| paddy@112 | 258 req.SetBasicAuth(client.ID.String(), client.Secret) |
| paddy@112 | 259 w = httptest.NewRecorder() |
| paddy@112 | 260 params = url.Values{} |
| paddy@112 | 261 params.Set("code", code.Code) |
| paddy@112 | 262 params.Set("redirect_uri", "not my redirectURI") |
| paddy@112 | 263 body = bytes.NewBufferString(params.Encode()) |
| paddy@112 | 264 req.Body = ioutil.NopCloser(body) |
| paddy@112 | 265 err = req.ParseForm() |
| paddy@112 | 266 if err != nil { |
| paddy@112 | 267 t.Log(err) |
| paddy@112 | 268 } |
| paddy@112 | 269 scope, profileID, valid = authCodeGrantValidate(w, req, testContext) |
| paddy@112 | 270 if valid { |
| paddy@112 | 271 t.Fatalf("Expected invalid auth code, got scope `%s` and profileID `%s`.", scope, profileID) |
| paddy@112 | 272 } |
| paddy@112 | 273 if w.Code != http.StatusBadRequest { |
| paddy@112 | 274 t.Errorf("Expected status %d, got %d", http.StatusUnauthorized, w.Code) |
| paddy@112 | 275 } |
| paddy@112 | 276 expectedBody = `{"error":"invalid_grant"}` |
| paddy@112 | 277 if expectedBody != strings.TrimSpace(w.Body.String()) { |
| paddy@112 | 278 t.Errorf("Expected body of `%s`, got `%s`", expectedBody, strings.TrimSpace(w.Body.String())) |
| paddy@112 | 279 } |
| paddy@112 | 280 |
| paddy@112 | 281 req, err = http.NewRequest("POST", "https://test.auth.secondbit.org/oauth2/grant", nil) |
| paddy@112 | 282 if err != nil { |
| paddy@112 | 283 t.Fatal("Can't build request:", err) |
| paddy@112 | 284 } |
| paddy@112 | 285 req.Header.Set("Content-Type", "application/x-www-form-urlencoded") |
| paddy@112 | 286 req.SetBasicAuth(client.ID.String(), client.Secret) |
| paddy@112 | 287 w = httptest.NewRecorder() |
| paddy@112 | 288 params = url.Values{} |
| paddy@112 | 289 params.Set("code", code.Code) |
| paddy@112 | 290 params.Set("redirect_uri", code.RedirectURI) |
| paddy@112 | 291 body = bytes.NewBufferString(params.Encode()) |
| paddy@112 | 292 req.Body = ioutil.NopCloser(body) |
| paddy@112 | 293 err = req.ParseForm() |
| paddy@112 | 294 if err != nil { |
| paddy@112 | 295 t.Log(err) |
| paddy@112 | 296 } |
| paddy@112 | 297 scope, profileID, valid = authCodeGrantValidate(w, req, testContext) |
| paddy@112 | 298 if valid { |
| paddy@112 | 299 t.Fatalf("Expected invalid auth code, got scope `%s` and profileID `%s`.", scope, profileID) |
| paddy@112 | 300 } |
| paddy@112 | 301 if w.Code != http.StatusBadRequest { |
| paddy@112 | 302 t.Errorf("Expected status %d, got %d", http.StatusUnauthorized, w.Code) |
| paddy@112 | 303 } |
| paddy@112 | 304 expectedBody = `{"error":"invalid_grant"}` |
| paddy@112 | 305 if expectedBody != strings.TrimSpace(w.Body.String()) { |
| paddy@112 | 306 t.Errorf("Expected body of `%s`, got `%s`", expectedBody, strings.TrimSpace(w.Body.String())) |
| paddy@112 | 307 } |
| paddy@112 | 308 |
| paddy@112 | 309 req, err = http.NewRequest("POST", "https://test.auth.secondbit.org/oauth2/grant", nil) |
| paddy@112 | 310 if err != nil { |
| paddy@112 | 311 t.Fatal("Can't build request:", err) |
| paddy@112 | 312 } |
| paddy@112 | 313 req.Header.Set("Content-Type", "application/x-www-form-urlencoded") |
| paddy@112 | 314 req.SetBasicAuth(client.ID.String(), client.Secret) |
| paddy@112 | 315 w = httptest.NewRecorder() |
| paddy@112 | 316 params = url.Values{} |
| paddy@112 | 317 params.Set("code", code2.Code) |
| paddy@112 | 318 params.Set("redirect_uri", code2.RedirectURI) |
| paddy@112 | 319 body = bytes.NewBufferString(params.Encode()) |
| paddy@112 | 320 req.Body = ioutil.NopCloser(body) |
| paddy@112 | 321 err = req.ParseForm() |
| paddy@112 | 322 if err != nil { |
| paddy@112 | 323 t.Log(err) |
| paddy@112 | 324 } |
| paddy@112 | 325 scope, profileID, valid = authCodeGrantValidate(w, req, testContext) |
| paddy@112 | 326 if !valid { |
| paddy@112 | 327 t.Fatalf("Expected valid auth code, was not valid.") |
| paddy@111 | 328 } |
| paddy@111 | 329 } |
| paddy@112 | 330 |
| paddy@112 | 331 func TestAuthCodeGrantInvalidate(t *testing.T) { |
| paddy@112 | 332 t.Parallel() |
| paddy@112 | 333 store := NewMemstore() |
| paddy@112 | 334 testContext := Context{ |
| paddy@112 | 335 clients: store, |
| paddy@112 | 336 authCodes: store, |
| paddy@112 | 337 profiles: store, |
| paddy@112 | 338 tokens: store, |
| paddy@112 | 339 sessions: store, |
| paddy@112 | 340 } |
| paddy@112 | 341 code := AuthorizationCode{ |
| paddy@112 | 342 Code: "myauthcode", |
| paddy@149 | 343 Created: time.Now().Round(time.Millisecond), |
| paddy@112 | 344 ExpiresIn: 180, |
| paddy@112 | 345 ClientID: uuid.NewID(), |
| paddy@163 | 346 Scopes: stringsToScopes([]string{"scope"}), |
| paddy@112 | 347 RedirectURI: "redirectURI", |
| paddy@112 | 348 State: "state", |
| paddy@112 | 349 } |
| paddy@112 | 350 err := testContext.SaveAuthorizationCode(code) |
| paddy@112 | 351 if err != nil { |
| paddy@112 | 352 t.Fatal("Can't add auth code:", err) |
| paddy@112 | 353 } |
| paddy@112 | 354 req, err := http.NewRequest("POST", "https://test.auth.secondbit.org/oauth2/grant", nil) |
| paddy@112 | 355 if err != nil { |
| paddy@112 | 356 t.Fatal("Can't build request:", err) |
| paddy@112 | 357 } |
| paddy@112 | 358 err = authCodeGrantInvalidate(req, testContext) |
| paddy@112 | 359 if err != ErrAuthorizationCodeNotFound { |
| paddy@112 | 360 t.Errorf("Expected `%s`, got `%+v`", ErrAuthorizationCodeNotFound, err) |
| paddy@112 | 361 } |
| paddy@112 | 362 req, err = http.NewRequest("POST", "https://test.auth.secondbit.org/oauth2/grant", nil) |
| paddy@112 | 363 if err != nil { |
| paddy@112 | 364 t.Fatal("Can't build request:", err) |
| paddy@112 | 365 } |
| paddy@112 | 366 req.Header.Set("Content-Type", "application/x-www-form-urlencoded") |
| paddy@112 | 367 params := url.Values{} |
| paddy@112 | 368 params.Set("code", "notmycode") |
| paddy@112 | 369 body := bytes.NewBufferString(params.Encode()) |
| paddy@112 | 370 req.Body = ioutil.NopCloser(body) |
| paddy@112 | 371 err = authCodeGrantInvalidate(req, testContext) |
| paddy@112 | 372 if err != ErrAuthorizationCodeNotFound { |
| paddy@112 | 373 t.Errorf("Expected `%s`, got `%+v`", ErrAuthorizationCodeNotFound, err) |
| paddy@112 | 374 } |
| paddy@112 | 375 req, err = http.NewRequest("POST", "https://test.auth.secondbit.org/oauth2/grant", nil) |
| paddy@112 | 376 if err != nil { |
| paddy@112 | 377 t.Fatal("Can't build request:", err) |
| paddy@112 | 378 } |
| paddy@112 | 379 req.Header.Set("Content-Type", "application/x-www-form-urlencoded") |
| paddy@112 | 380 params.Set("code", code.Code) |
| paddy@112 | 381 body = bytes.NewBufferString(params.Encode()) |
| paddy@112 | 382 req.Body = ioutil.NopCloser(body) |
| paddy@112 | 383 err = authCodeGrantInvalidate(req, testContext) |
| paddy@112 | 384 if err != nil { |
| paddy@112 | 385 t.Error("Error invalidating auth code:", err) |
| paddy@112 | 386 } |
| paddy@112 | 387 authCode, err := testContext.GetAuthorizationCode(code.Code) |
| paddy@112 | 388 if err != nil { |
| paddy@112 | 389 t.Error("Error retrieving auth code:", err) |
| paddy@112 | 390 } |
| paddy@112 | 391 if !authCode.Used { |
| paddy@112 | 392 t.Error("Expected auth code to be used, was not.") |
| paddy@112 | 393 } |
| paddy@112 | 394 } |