auth
auth/authcode_test.go
Implement postgres version of scopeStore. Update the authd server to use postgres as its scopeStore, instead of memstore. panic when starting the authd server if the CreateScopes call fails. This should, ideally, ignore ErrScopeAlreadyExists errors, but does not as of this commit. Update the simple.gotmpl template to properly display scopes, after switching to the Scope type instead of simply passing around the string the client supplied broke the template and I never bothered fixing it. Update the updateScopes method on the scopeStore (and the corresponding UpdateScopes method on the Context type) to be updateScope/UpdateScope. Operating on several scopes at a time like that is simply too challenging in SQL and I can't justify the complexity with a use case. Add a helper method to ScopeChange called Empty(), which returns true if the ScopeChange is full of nil values. Remove the ID from the ScopeChange type, because we're no longer accepting multiple ScopeChange types in UpdateScope, so we can supply that information outside the ScopeChange, which matches the rest of our update* methods. Correct our tests in scope_test.go to correctly use the updateScope method instead of the old updateScopes method. This generally just resulted in calling updateScope multiple times, as opposed to just once. Add a scope table initialization to the sql/postgres_init.sql script.
| 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@149 | 58 Created: time.Now().Round(time.Millisecond), |
| 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@149 | 138 Added: time.Now().Round(time.Millisecond), |
| 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@151 | 144 err = testContext.AddEndpoints([]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@149 | 150 Created: time.Now().Round(time.Millisecond), |
| 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@149 | 332 Created: time.Now().Round(time.Millisecond), |
| 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 } |