auth

Paddy 2015-03-05 Parent:d30a3a12d387 Child:8267e1c8bcd1

136:e090a69e711f Go to Latest

auth/authcode_test.go

Fix go vet error. We accidentally had a $ instead of a % in our test output, which would have caused an error in printing that output. This fixed it.

History
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 }