func TestGetAuthenticatedAccount(t *testing.T) { var ( account *accounts.Account err error ) // A test request r, err := http.NewRequest("GET", "http://1.2.3.4/something", nil) assert.NoError(t, err, "Request setup should not get an error") account, err = accounts.GetAuthenticatedAccount(r) // Account object should be nil assert.Nil(t, account) // Correct error should be returned if assert.NotNil(t, err) { assert.Equal(t, accounts.ErrAccountAuthenticationRequired, err) } // Set a context value of an invalid type context.Set(r, accounts.AuthenticatedAccountKey, "bogus") account, err = accounts.GetAuthenticatedAccount(r) // Account object should be nil assert.Nil(t, account) // Correct error should be returned if assert.NotNil(t, err) { assert.Equal(t, accounts.ErrAccountAuthenticationRequired, err) } // Set a valid context value context.Set(r, accounts.AuthenticatedAccountKey, &accounts.Account{Name: "Test Account"}) account, err = accounts.GetAuthenticatedAccount(r) // Error should be nil assert.Nil(t, err) // Correct account object should be returned if assert.NotNil(t, account) { assert.Equal(t, "Test Account", account.Name) } }
func (suite *AccountsTestSuite) TestAccountAuthMiddleware() { var ( r *http.Request w *httptest.ResponseRecorder next http.HandlerFunc authenticatedAccount *accounts.Account err error ) middleware := accounts.NewAccountAuthMiddleware(suite.service) // Send a request without basic auth through the middleware r, err = http.NewRequest("POST", "http://1.2.3.4/something", nil) assert.NoError(suite.T(), err, "Request setup should not get an error") w = httptest.NewRecorder() next = func(w http.ResponseWriter, r *http.Request) {} middleware.ServeHTTP(w, r, next) // Check the response testutil.TestResponseForError( suite.T(), w, accounts.ErrAccountAuthenticationRequired.Error(), 401, ) // Check the context variable has not been set authenticatedAccount, err = accounts.GetAuthenticatedAccount(r) assert.Nil(suite.T(), authenticatedAccount) assert.Error(suite.T(), err) assert.Equal(suite.T(), accounts.ErrAccountAuthenticationRequired, err) // Send a request with incorrect basic auth through the middleware r, err = http.NewRequest("POST", "http://1.2.3.4/something", nil) assert.NoError(suite.T(), err, "Request setup should not get an error") r.SetBasicAuth("bogus", "bogus") w = httptest.NewRecorder() next = func(w http.ResponseWriter, r *http.Request) {} middleware.ServeHTTP(w, r, next) // Check the response testutil.TestResponseForError( suite.T(), w, accounts.ErrAccountAuthenticationRequired.Error(), 401, ) // Check the context variable has not been set authenticatedAccount, err = accounts.GetAuthenticatedAccount(r) assert.Nil(suite.T(), authenticatedAccount) assert.Error(suite.T(), err) assert.Equal(suite.T(), accounts.ErrAccountAuthenticationRequired, err) // Send a request with correct basic auth through the middleware r, err = http.NewRequest("POST", "http://1.2.3.4/something", nil) assert.NoError(suite.T(), err, "Request setup should not get an error") r.SetBasicAuth("test_client_1", "test_secret") w = httptest.NewRecorder() next = func(w http.ResponseWriter, r *http.Request) {} middleware.ServeHTTP(w, r, next) // Check the status code assert.Equal(suite.T(), 200, w.Code) // Check the context variable has been set authenticatedAccount, err = accounts.GetAuthenticatedAccount(r) assert.NoError(suite.T(), err) assert.NotNil(suite.T(), authenticatedAccount) assert.Equal(suite.T(), "Test Account 1", authenticatedAccount.Name) assert.Equal(suite.T(), "test_client_1", authenticatedAccount.OauthClient.Key) // Send a request with correct client access token as bearer r, err = http.NewRequest("POST", "http://1.2.3.4/something", nil) assert.NoError(suite.T(), err, "Request setup should not get an error") r.Header.Set("Authorization", "Bearer test_client_token") w = httptest.NewRecorder() next = func(w http.ResponseWriter, r *http.Request) {} middleware.ServeHTTP(w, r, next) // Check the status code assert.Equal(suite.T(), 200, w.Code) // Check the context variable has been set authenticatedAccount, err = accounts.GetAuthenticatedAccount(r) assert.NoError(suite.T(), err) assert.NotNil(suite.T(), authenticatedAccount) assert.Equal(suite.T(), "Test Account 1", authenticatedAccount.Name) assert.Equal(suite.T(), "test_client_1", authenticatedAccount.OauthClient.Key) }
// Handlers requests to login with Facebook access token // (POST /v1/facebook/login) func (s *Service) loginHandler(w http.ResponseWriter, r *http.Request) { // Get the authenticated account from the request context authenticatedAccount, err := accounts.GetAuthenticatedAccount(r) if err != nil { response.UnauthorizedError(w, err.Error()) return } // Parse the form so r.Form becomes available if err = r.ParseForm(); err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Get the scope string scope, err := s.GetAccountsService().GetOauthService().GetScope(r.Form.Get("scope")) if err != nil { response.Error(w, err.Error(), http.StatusBadRequest) return } // Fetch the user data from facebook resp, err := s.adapter.GetMe(r.Form.Get("access_token")) if err != nil { response.UnauthorizedError(w, err.Error()) return } // Initialise variables var ( profile UserProfile user *accounts.User ) // Decode the response to struct if err = resp.Decode(&profile); err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } if profile.Email == nil { // There is an edge case where Facebook does not return a valid email // User could have registered with a phone number or have an unconfirmed // email address. In such rare case, default to {facebook_id}@facebook.com edgeCaseEmail := fmt.Sprintf("*****@*****.**", profile.ID) profile.Email = &edgeCaseEmail } // Build user request object userRequest := &accounts.UserRequest{ Email: *profile.Email, FirstName: profile.FirstName, LastName: profile.LastName, Picture: profile.GetPictureURL(), } // Get or create a new user based on facebook ID and other details user, err = s.GetAccountsService().GetOrCreateFacebookUser( authenticatedAccount, profile.ID, userRequest, ) if err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Check that the same account is being used if authenticatedAccount.ID != user.Account.ID { response.UnauthorizedError(w, ErrAccountMismatch.Error()) return } // Log in the user accessToken, refreshToken, err := s.GetAccountsService().GetOauthService().Login( user.Account.OauthClient, user.OauthUser, scope, ) if err != nil { response.Error(w, err.Error(), http.StatusInternalServerError) return } // Write the JSON access token to the response accessTokenRespone := &oauth.AccessTokenResponse{ UserID: user.ID, AccessToken: accessToken.Token, ExpiresIn: s.cnf.Oauth.AccessTokenLifetime, TokenType: tokentypes.Bearer, Scope: accessToken.Scope, RefreshToken: refreshToken.Token, } response.WriteJSON(w, accessTokenRespone, 200) }