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