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