func (suite *OauthTestSuite) TestClientCredentialsGrant() { // Prepare a request r, err := http.NewRequest("POST", "http://1.2.3.4/v1/oauth/tokens", nil) assert.NoError(suite.T(), err, "Request setup should not get an error") r.SetBasicAuth("test_client_1", "test_secret") r.PostForm = url.Values{ "grant_type": {"client_credentials"}, "scope": {"read_write"}, } // Serve the request w := httptest.NewRecorder() suite.router.ServeHTTP(w, r) // Fetch data accessToken := new(oauth.AccessToken) assert.False(suite.T(), oauth.AccessTokenPreload(suite.db). Last(accessToken).RecordNotFound()) // Check the response expected := &oauth.AccessTokenResponse{ AccessToken: accessToken.Token, ExpiresIn: 3600, TokenType: tokentypes.Bearer, Scope: "read_write", } testutil.TestResponseObject(suite.T(), w, expected, 200) // Client credentials grant does not produce refresh token assert.True(suite.T(), oauth.RefreshTokenPreload(suite.db). First(new(oauth.RefreshToken)).RecordNotFound()) }
func (suite *OauthTestSuite) TestPasswordGrant() { // Prepare a request r, err := http.NewRequest("POST", "http://1.2.3.4/v1/oauth/tokens", nil) assert.NoError(suite.T(), err, "Request setup should not get an error") r.SetBasicAuth("test_client_1", "test_secret") r.PostForm = url.Values{ "grant_type": {"password"}, "username": {"test@user"}, "password": {"test_password"}, "scope": {"read_write"}, } // Serve the request w := httptest.NewRecorder() suite.router.ServeHTTP(w, r) // Fetch data accessToken, refreshToken := new(oauth.AccessToken), new(oauth.RefreshToken) assert.False(suite.T(), oauth.AccessTokenPreload(suite.db). Last(accessToken).RecordNotFound()) assert.False(suite.T(), oauth.RefreshTokenPreload(suite.db). Last(refreshToken).RecordNotFound()) // Check the response expected := &oauth.AccessTokenResponse{ UserID: accessToken.User.MetaUserID, AccessToken: accessToken.Token, ExpiresIn: 3600, TokenType: tokentypes.Bearer, Scope: "read_write", RefreshToken: refreshToken.Token, } testutil.TestResponseObject(suite.T(), w, expected, 200) }
func (suite *OauthTestSuite) TestAuthorizationCodeGrant() { // Insert a test authorization code err := suite.db.Create(&oauth.AuthorizationCode{ Code: "test_code", ExpiresAt: time.Now().UTC().Add(+10 * time.Second), Client: suite.clients[0], User: suite.users[0], RedirectURI: util.StringOrNull("https://www.example.com"), Scope: "read_write", }).Error assert.NoError(suite.T(), err, "Inserting test data failed") // Prepare a request r, err := http.NewRequest("POST", "http://1.2.3.4/v1/oauth/tokens", nil) assert.NoError(suite.T(), err, "Request setup should not get an error") r.SetBasicAuth("test_client_1", "test_secret") r.PostForm = url.Values{ "grant_type": {"authorization_code"}, "code": {"test_code"}, "redirect_uri": {"https://www.example.com"}, } // Serve the request w := httptest.NewRecorder() suite.router.ServeHTTP(w, r) // Fetch data accessToken, refreshToken := new(oauth.AccessToken), new(oauth.RefreshToken) assert.False(suite.T(), oauth.AccessTokenPreload(suite.db). Last(accessToken).RecordNotFound()) assert.False(suite.T(), oauth.RefreshTokenPreload(suite.db). Last(refreshToken).RecordNotFound()) // Check the response expected := &oauth.AccessTokenResponse{ UserID: accessToken.User.MetaUserID, AccessToken: accessToken.Token, ExpiresIn: 3600, TokenType: tokentypes.Bearer, Scope: "read_write", RefreshToken: refreshToken.Token, } testutil.TestResponseObject(suite.T(), w, expected, 200) // The authorization code should get deleted after use assert.True(suite.T(), suite.db.Unscoped(). First(new(oauth.AuthorizationCode)).RecordNotFound()) }
func (suite *OauthTestSuite) TestRefreshTokenGrant() { // Insert a test refresh token err := suite.db.Create(&oauth.RefreshToken{ Token: "test_token", ExpiresAt: time.Now().UTC().Add(+10 * time.Second), Client: suite.clients[0], User: suite.users[0], Scope: "read_write", }).Error assert.NoError(suite.T(), err, "Inserting test data failed") // Make a request r, err := http.NewRequest("POST", "http://1.2.3.4/v1/oauth/tokens", nil) assert.NoError(suite.T(), err, "Request setup should not get an error") r.SetBasicAuth("test_client_1", "test_secret") r.PostForm = url.Values{ "grant_type": {"refresh_token"}, "refresh_token": {"test_token"}, "scope": {"read_write"}, } // Serve the request w := httptest.NewRecorder() suite.router.ServeHTTP(w, r) // Fetch data accessToken := new(oauth.AccessToken) assert.False(suite.T(), oauth.AccessTokenPreload(suite.db). Last(accessToken).RecordNotFound()) // Check the response expected := &oauth.AccessTokenResponse{ UserID: accessToken.User.MetaUserID, AccessToken: accessToken.Token, ExpiresIn: 3600, TokenType: tokentypes.Bearer, Scope: "read_write", RefreshToken: "test_token", } testutil.TestResponseObject(suite.T(), w, expected, 200) }
func (suite *OauthTestSuite) TestGrantAccessToken() { var ( accessToken *oauth.AccessToken err error tokens []*oauth.AccessToken ) // Grant a client only access token accessToken, err = suite.service.GrantAccessToken( suite.clients[0], // client nil, // user 3600, // expires in "scope doesn't matter", // scope ) // Error should be Nil assert.Nil(suite.T(), err) // Correct access token object should be returned if assert.NotNil(suite.T(), accessToken) { // Fetch all access tokens oauth.AccessTokenPreload(suite.db).Order("id").Find(&tokens) // There should be just one right now assert.Equal(suite.T(), 1, len(tokens)) // And the token should match the one returned by the grant method assert.Equal(suite.T(), tokens[0].Token, accessToken.Token) // Client id should be set assert.True(suite.T(), tokens[0].ClientID.Valid) assert.Equal(suite.T(), int64(suite.clients[0].ID), tokens[0].ClientID.Int64) // User id should be nil assert.False(suite.T(), tokens[0].UserID.Valid) } // Grant a user specific access token accessToken, err = suite.service.GrantAccessToken( suite.clients[0], // client suite.users[0], // user 3600, // expires in "scope doesn't matter", // scope ) // Error should be Nil assert.Nil(suite.T(), err) // Correct access token object should be returned if assert.NotNil(suite.T(), accessToken) { // Fetch all access tokens oauth.AccessTokenPreload(suite.db).Order("id").Find(&tokens) // There should be 2 tokens now assert.Equal(suite.T(), 2, len(tokens)) // And the second token should match the one returned by the grant method assert.Equal(suite.T(), tokens[1].Token, accessToken.Token) // Client id should be set assert.True(suite.T(), tokens[1].ClientID.Valid) assert.Equal(suite.T(), int64(suite.clients[0].ID), tokens[1].ClientID.Int64) // User id should be set assert.True(suite.T(), tokens[1].UserID.Valid) assert.Equal(suite.T(), int64(suite.users[0].ID), tokens[1].UserID.Int64) } }
func (suite *AccountsTestSuite) TestConfirmEmailWithAutologinFlag() { var ( testOauthUser *oauth.User testUser *accounts.User testConfirmation *accounts.Confirmation err error ) // Insert a test user testOauthUser, err = suite.service.GetOauthService().CreateUser( roles.User, "harold@finch", "test_password", ) assert.NoError(suite.T(), err, "Failed to insert a test oauth user") testUser, err = accounts.NewUser( suite.accounts[0], testOauthUser, "", //facebook ID false, // confirmed &accounts.UserRequest{ FirstName: "Harold", LastName: "Finch", }, ) assert.NoError(suite.T(), err, "Failed to create a new user object") err = suite.db.Create(testUser).Error assert.NoError(suite.T(), err, "Failed to insert a test user") testUser.Account = suite.accounts[0] // Insert a test confirmation testConfirmation, err = accounts.NewConfirmation( testUser, suite.cnf.AppSpecific.ConfirmationLifetime, ) assert.NoError(suite.T(), err, "Failed to create a new confirmation object") err = suite.db.Create(testConfirmation).Error assert.NoError(suite.T(), err, "Failed to insert a test confirmation") testConfirmation.User = testUser // Prepare a request r, err := http.NewRequest( "GET", fmt.Sprintf( "http://1.2.3.4/v1/confirmations/%s?autologin=true", testConfirmation.Reference, ), nil, ) assert.NoError(suite.T(), err, "Request setup should not get an error") r.Header.Set( "Authorization", fmt.Sprintf( "Basic %s", b64.StdEncoding.EncodeToString([]byte("test_client_1:test_secret")), ), ) // Check the routing match := new(mux.RouteMatch) suite.router.Match(r, match) if assert.NotNil(suite.T(), match.Route) { assert.Equal(suite.T(), "confirm_email", match.Route.GetName()) } // Count before var ( countBefore int accessTokensCountBefore int refreshTokensCountBefore int ) suite.db.Model(new(accounts.Confirmation)).Count(&countBefore) suite.db.Model(new(oauth.AccessToken)).Count(&accessTokensCountBefore) suite.db.Model(new(oauth.RefreshToken)).Count(&refreshTokensCountBefore) // And serve the request w := httptest.NewRecorder() suite.router.ServeHTTP(w, r) // Count after var ( countAfter int accessTokensCountAfter int refreshTokensCountAfter int ) suite.db.Model(new(accounts.Confirmation)).Count(&countAfter) suite.db.Model(new(oauth.AccessToken)).Count(&accessTokensCountAfter) suite.db.Model(new(oauth.RefreshToken)).Count(&refreshTokensCountAfter) assert.Equal(suite.T(), countBefore-1, countAfter) assert.Equal(suite.T(), accessTokensCountBefore+1, accessTokensCountAfter) assert.Equal(suite.T(), refreshTokensCountBefore+1, refreshTokensCountAfter) // Fetch the updated user user := new(accounts.User) notFound := accounts.UserPreload(suite.db).First(user, testUser.ID).RecordNotFound() assert.False(suite.T(), notFound) // Confirmation should have been soft deleteted assert.True(suite.T(), suite.db.Last(new(accounts.Confirmation)).RecordNotFound()) // And correct data was saved assert.True(suite.T(), user.Confirmed) // Fetch login data accessToken, refreshToken := new(oauth.AccessToken), new(oauth.RefreshToken) assert.False(suite.T(), oauth.AccessTokenPreload(suite.db). Last(accessToken).RecordNotFound()) assert.False(suite.T(), oauth.RefreshTokenPreload(suite.db). Last(refreshToken).RecordNotFound()) // Check the response expectedEmbeddedTokenResponse, err := oauth.NewAccessTokenResponse( accessToken, refreshToken, suite.cnf.Oauth.AccessTokenLifetime, tokentypes.Bearer, ) assert.NoError(suite.T(), err, "Failed to create expected response object") expected, err := accounts.NewConfirmationResponse(testConfirmation) expected.SetEmbedded( "access-token", jsonhal.Embedded(expectedEmbeddedTokenResponse), ) assert.NoError(suite.T(), err, "Failed to create expected response object") testutil.TestResponseObject(suite.T(), w, expected, 200) }
func (suite *FacebookTestSuite) TestLoginCreatesNewUserNoPicture() { // Prepare a request r, err := http.NewRequest("POST", "http://1.2.3.4/v1/facebook/login", nil) assert.NoError(suite.T(), err, "Request setup should not get an error") r.PostForm = url.Values{ "access_token": {"facebook_token"}, "scope": {"read_write"}, } r.SetBasicAuth("test_client_1", "test_secret") // Check the routing match := new(mux.RouteMatch) suite.router.Match(r, match) if assert.NotNil(suite.T(), match.Route) { assert.Equal(suite.T(), "facebook_login", match.Route.GetName()) } // Mock fetching profile data from facebook suite.mockFacebookGetMe(fb.Result{ "id": "new_facebook_id", "email": "new@user", "name": "John Reese", "first_name": "John", "last_name": "Reese", "picture": nil, }, nil) // Count before var countBefore int suite.db.Model(new(accounts.User)).Count(&countBefore) // And serve the request w := httptest.NewRecorder() suite.router.ServeHTTP(w, r) // Check mock expectations were met suite.adapterMock.AssertExpectations(suite.T()) // Check the status code if !assert.Equal(suite.T(), 200, w.Code) { log.Print(w.Body.String()) } // Count after var countAfter int suite.db.Model(new(accounts.User)).Count(&countAfter) assert.Equal(suite.T(), countBefore+1, countAfter) // Fetch the created user user := new(accounts.User) notFound := accounts.UserPreload(suite.db). Last(user).RecordNotFound() assert.False(suite.T(), notFound) // And correct data was saved assert.Equal(suite.T(), user.ID, user.OauthUser.MetaUserID) assert.Equal(suite.T(), "new@user", user.OauthUser.Username) assert.Equal(suite.T(), "John", user.FirstName.String) assert.Equal(suite.T(), "Reese", user.LastName.String) assert.Equal(suite.T(), "new_facebook_id", user.FacebookID.String) assert.False(suite.T(), user.Picture.Valid) assert.Equal(suite.T(), roles.User, user.OauthUser.RoleID.String) // Fetch oauth tokens accessToken := new(oauth.AccessToken) assert.False(suite.T(), oauth.AccessTokenPreload(suite.db). First(accessToken).RecordNotFound()) refreshToken := new(oauth.RefreshToken) assert.False(suite.T(), oauth.RefreshTokenPreload(suite.db). First(refreshToken).RecordNotFound()) // Check the response body expected, err := json.Marshal(&oauth.AccessTokenResponse{ UserID: user.ID, AccessToken: accessToken.Token, ExpiresIn: 3600, TokenType: tokentypes.Bearer, Scope: "read_write", RefreshToken: refreshToken.Token, }) if assert.NoError(suite.T(), err, "JSON marshalling failed") { assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String())) } }
func (suite *FacebookTestSuite) TestLoginUpdatesExistingUser() { var ( testOauthUser *oauth.User testUser *accounts.User err error ) // Insert a test user testOauthUser, err = suite.service.GetAccountsService().GetOauthService().CreateUser( roles.User, "harold@finch", "", // empty password ) assert.NoError(suite.T(), err, "Failed to insert a test oauth user") testUser, err = accounts.NewUser( suite.accounts[0], testOauthUser, "some_facebook_id", // facebook ID true, // confirmed &accounts.UserRequest{ FirstName: "Harold", LastName: "Finch", Picture: "some_picture", }, ) assert.NoError(suite.T(), err, "Failed to create a new test account user object") err = suite.db.Create(testUser).Error assert.NoError(suite.T(), err, "Failed to insert a test user") testUser.OauthUser = testOauthUser // Prepare a request r, err := http.NewRequest("POST", "http://1.2.3.4/v1/facebook/login", nil) assert.NoError(suite.T(), err, "Request setup should not get an error") r.PostForm = url.Values{ "access_token": {"facebook_token"}, "scope": {"read_write"}, } r.SetBasicAuth("test_client_1", "test_secret") // Check the routing match := new(mux.RouteMatch) suite.router.Match(r, match) if assert.NotNil(suite.T(), match.Route) { assert.Equal(suite.T(), "facebook_login", match.Route.GetName()) } // Mock fetching profile data from facebook suite.mockFacebookGetMe(fb.Result{ "id": "new_facebook_id", "email": testUser.OauthUser.Username, "name": "New Name", "first_name": "New First Name", "last_name": "New Last Name", "picture": map[string]interface{}{ "data": map[string]interface{}{ "url": "new_picture", }, }, }, nil) // Count before var countBefore int suite.db.Model(new(accounts.User)).Count(&countBefore) // And serve the request w := httptest.NewRecorder() suite.router.ServeHTTP(w, r) // Check mock expectations were met suite.adapterMock.AssertExpectations(suite.T()) // Check the status code if !assert.Equal(suite.T(), 200, w.Code) { log.Print(w.Body.String()) } // Count after var countAfter int suite.db.Model(new(accounts.User)).Count(&countAfter) assert.Equal(suite.T(), countBefore, countAfter) // Fetch the updated user user := new(accounts.User) notFound := accounts.UserPreload(suite.db). First(user, testUser.ID).RecordNotFound() assert.False(suite.T(), notFound) // And correct data was saved assert.Equal(suite.T(), testUser.OauthUser.Username, user.OauthUser.Username) assert.Equal(suite.T(), "New First Name", user.FirstName.String) assert.Equal(suite.T(), "New Last Name", user.LastName.String) assert.Equal(suite.T(), "new_facebook_id", user.FacebookID.String) assert.Equal(suite.T(), "new_picture", user.Picture.String) assert.Equal(suite.T(), roles.User, user.OauthUser.RoleID.String) // Fetch oauth tokens accessToken := new(oauth.AccessToken) assert.False(suite.T(), oauth.AccessTokenPreload(suite.db). First(accessToken).RecordNotFound()) refreshToken := new(oauth.RefreshToken) assert.False(suite.T(), oauth.RefreshTokenPreload(suite.db). First(refreshToken).RecordNotFound()) // Check the response body expected, err := json.Marshal(&oauth.AccessTokenResponse{ UserID: user.ID, AccessToken: accessToken.Token, ExpiresIn: 3600, TokenType: tokentypes.Bearer, Scope: "read_write", RefreshToken: refreshToken.Token, }) if assert.NoError(suite.T(), err, "JSON marshalling failed") { assert.Equal(suite.T(), string(expected), strings.TrimSpace(w.Body.String())) } }