func TestHasRole(t *testing.T) { ctx, done, _ := aetest.NewContext() defer done() ctx = test.WithConfig(ctx, map[string]interface{}{"AuthSecret": "foo"}) w := httptest.NewRecorder() r, _ := http.NewRequest("GET", "/", nil) r.Header.Set("Authorization", "wrong") // Make up a fake user acct, _ := account.New(ctx, "*****@*****.**", "foobar") acct.Roles = append(acct.Roles, "tyrant") account.Save(ctx, acct) // Unretrievable user, because middleware hasn't been run. if err := HasRole("foo")(ctx, w, r); err != ErrCannotGetAccount { t.Errorf("Unexpected error, wanted ErrCannotGetAccount, got %s", err) } // User's set, but claimset isn't for some reason. ctx2 := context.WithValue(ctx, internal.AuthContextKey, &account.Nobody) if err := HasRole("foo")(ctx2, w, r); err != ErrCannotGetClaimSet { t.Errorf("Unexpected error, wanted ErrCannotGetClaimSet, got %s", err) } // Account doesn't have the role. r.Header.Set("Authorization", test.JWT(&jws.ClaimSet{Sub: "*****@*****.**", Scope: AllScope}, "foo")) ctx2 = Middleware(ctx, w, r) if err := HasRole("foo")(ctx2, w, r); err != ErrRoleMissing { t.Errorf("Unexpected error, wanted ErrRoleMissing, got %s", err) } // Token doesn't have the role in scope. r.Header.Set("Authorization", test.JWT(&jws.ClaimSet{Sub: "*****@*****.**", Scope: "somethingelse"}, "foo")) ctx2 = Middleware(ctx, w, r) if err := HasRole("tyrant")(ctx2, w, r); err != ErrRoleNotInScope { t.Errorf("Unexpected error, wanted ErrRoleNotInScope, got %s", err) } // Token is consumable, but hasn't been used yet. consumableToken := test.ConsumableJWT(&jws.ClaimSet{Sub: "*****@*****.**", Scope: "tyrant"}, "foo", 1) r.Header.Set("Authorization", consumableToken) ctx2 = Middleware(ctx, w, r) if err := HasRole("tyrant")(ctx2, w, r); err != nil { t.Errorf("Unexpected error, wanted nil, got %s", err) } // We used this token once already. Should be used up. ctx2 = Middleware(ctx, w, r) if err := HasRole("tyrant")(ctx2, w, r); err != ErrClaimSetUsedUp { t.Errorf("Unexpected error, wanted ErrClaimSetUsedUp, got %s", err) } }
func TestMiddleware(t *testing.T) { var acct account.Account ctx := test.WithConfig(context.Background(), map[string]interface{}{"AuthSecret": "foo"}) // a user is no one (i.e., no Authorization header) w := httptest.NewRecorder() r, _ := http.NewRequest("GET", "/", nil) resultCtx := Middleware(ctx, w, r) err := GetAccount(resultCtx, &acct) if err != nil { t.Errorf("Unexpected error %s", err) } if !acct.Nobody() { t.Errorf("acct should have been the zero value, but got %+v", acct) } // bad jwt w = httptest.NewRecorder() r, _ = http.NewRequest("GET", "/", nil) r.Header.Set("Authorization", "wrong") resultCtx = Middleware(ctx, w, r) err = GetAccount(resultCtx, &acct) if err != InvalidJWTError { t.Errorf("Unexpected error %s", err) } // super (i.e., they passed in the secret itself) w = httptest.NewRecorder() r, _ = http.NewRequest("GET", "/", nil) r.Header.Set("Authorization", "foo") resultCtx = Middleware(ctx, w, r) err = GetAccount(resultCtx, &acct) if err != nil { t.Errorf("Unexpected error %s", err) } if !acct.Super() { t.Errorf("Expected the super account, but got %+v", acct) } // super (i.e., they passed in the secret itself) w = httptest.NewRecorder() r, _ = http.NewRequest("GET", "/", nil) r.Header.Set("Authorization", "foo") resultCtx = Middleware(ctx, w, r) err = GetAccount(resultCtx, &acct) if err != nil { t.Errorf("Unexpected error %s", err) } if !acct.Super() { t.Errorf("Expected the super account, but got %+v", acct) } // test against App Engine dev environment from this point forward realCtx, done, _ := aetest.NewContext() defer done() account.New(realCtx, "*****@*****.**", "foobar") realCtx = test.WithConfig(realCtx, map[string]interface{}{"AuthSecret": "foo"}) // nonexistent account w = httptest.NewRecorder() r, _ = http.NewRequest("GET", "/", nil) r.Header.Set("Authorization", test.JWT(&jws.ClaimSet{Sub: "*****@*****.**"}, "foo")) resultCtx = Middleware(realCtx, w, r) if resultCtx != nil { t.Errorf("Expected Middleware to terminate (i.e. to return nil), but it didn't", err) } // existent account (i.e., the happy path) w = httptest.NewRecorder() r, _ = http.NewRequest("GET", "/", nil) r.Header.Set("Authorization", test.JWT(&jws.ClaimSet{Sub: "*****@*****.**"}, "foo")) resultCtx = Middleware(realCtx, w, r) if resultCtx == nil { t.Errorf("Expected Middleware not to terminate (i.e. to return another context), but it terminated") } else if err = GetAccount(resultCtx, &acct); err != nil { t.Errorf("Expected no error when getting a properly authenticated account, but got %s", err) } else if acct.Email != "*****@*****.**" { t.Errorf("Unexpected account on retrieval: %+v", acct) } }