angularJS post CORS - angularjs

I am new to AngularJS and still learning. I have this angularJS code below to check my log-in credentials in my API. But upon log-in(clicking my log-in button) it does not hitting my break point in my API Code. Both API and Log-in codes are running from my local machine. I attached the picture for the CORS error.
AngularJS
data = {username:'user', password:'pass' }
app.service('services', function ($http, $window) {
services = {};
//Set the link once in upon open of project
localStorage.setItem('link', 'http://localhost:63763/');
var surl = localStorage.getItem('link');
services.signin = function (data) {
var result = $http({
method: 'POST',
url: surl + 'api/auth/signin', data: data,
}).then(function (response) {
return response;
}, function (err) {
return err;
});
return result;
};
return services;
});
API
[HttpPost]
[Route("signin")]
public IHttpActionResult Authenticate([FromBody] UsersSigninDTO dto)
{
//Codes
}
Class DTO
public class UsersSigninDTO
{
[Required(ErrorMessage = "username is required.")]
public string username { get; set; }
[Required(ErrorMessage = "password is required.")]
public string password { get; set; }
}
[Error Picture]

I solve it. On API Code side I added these code under the WebApiConfig.cs
config.MapHttpAttributeRoutes();
EnableCorsAttribute CorsAttribute = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(CorsAttribute);

You are using 2 different ports when calling localhost, thus triggering CORS.
App seems to be loaded from localhost:51216 and the requests to API by localhost:63763
What if you load your app from localhost:63763 ?
Maybe you are running 2 webpack instances at the same time? Check your config.

Related

AngularJS/Spring MVC, HttpSession not persistent

We are developing a web application, we're using Spring MVC (along with Spring Boot and Spring Security) and AngularJS.
Therefore, we have two distinct servers running for the application.
We are trying to store the user session backend, to ensure a proper level of security, so we tried to use the HttpSessionobject, but every time we want to retrieve the existing session, a new instance is created (we've checked the session ids).
Here's what we're doing to login :
$scope.authenticate = function () {
var postObject = new Object();
postObject.mail = $scope.userName;
postObject.password = $scope.userPassword;
$http({
url: "http://localhost:8080/login",
method: "POST",
dataType: "json",
data: postObject,
headers: {
"Content-Type": "application/json"
}
}).success(function successCallback(response, status) {
if (status == 200) {
$scope.messageAuth = "Login successful"
$scope.go('/services');
}
})
.error(function errorCallback(error, status) {
$scope.messageAuth = "Error " + response;
});
};
Then, we check the credentials, if they are correct, we store the user information into a new session :
#RestController
public class UserController {
#Resource
UserService userService;
#CrossOrigin
#RequestMapping(value = "/login", method = RequestMethod.POST, produces = "application/json")
public ResponseEntity<User> loginSubmit(#RequestBody User user, HttpServletRequest request, HttpSession session) {
if (isAuthorized(user)) {
User authenticatedUser = this.userService.getUserByMail(user.getMail());
authenticatedUser.setPassword(null);
session.invalidate();
HttpSession newSession = request.getSession(true);
newSession.setAttribute("USER_ROLE", authenticatedUser.getRole());
System.out.println("/login : SESSION ID = " + newSession.getId());
System.out.println("/login : " + newSession.getAttribute("USER_ROLE"));
return ResponseEntity.ok(authenticatedUser);
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(null);
}
}
#RequestMapping("/user")
public String user(Principal user, HttpServletRequest request, HttpSession session) {
System.out.println("/user : SESSION ID = " + session.getId());
System.out.println("/user : " + (String) request.getSession(false).getAttribute("USER_ROLE"));
return (String) session.getAttribute("USER_ROLE");
}
And finally, from the Angular app, we'd like to get the user information by calling /user like this :
var f = function() {
$http.get('http://localhost:8080/user').success(function successCallback(response) {
console.log(response);
}).error(function() {
console.log('error');
})
};
We've already tried pretty much every we found about how to manage a session with Spring Security, maybe the problem comes from the Angular part?
Any help would be greatly appreciated,
Thanks in advance
We found the solution, we just needed to add a few config lines in our app.js file :
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.withCredentials = true;
More information here : link
Hopefully it will help someone, someday!

$http.post request can't find method in controller

I have a AddCategory() method in my Controller:
[RoutePrefix("api")]
public class CategoryController : ApiController
{
....
[Route("addCategory")]
[HttpPost]
public void AddCategory(string category)
{
var getCat = category;
}
At the my Home.html i have button Save New Category i wrote the $http.post method for it:
var testString = "TEST String";
var req = {
method: 'POST',
url: '/api/addCategory',
data: testString,
};
$http(req).then(function successCallback(response) {
console.log("Success");
}, function errorCallback(response) {
console.log("Eror");
});
But i have the next error:
angular.js:11442 POST http://localhost:6059/api/addCategory 404 (Not
Found)
At the Network bookmark in Development console i finded the error:
may be it's important but i disabled XML in WebApiConfig.cs:
var json = GlobalConfiguration.Configuration.Formatters;
json.JsonFormatter.UseDataContractJsonSerializer = true;
json.Remove(json.XmlFormatter);
May be somebody knows how i can change it ? Thanks for your answers!
You method Post need to return IHttpActionResult. or your request http always returns code 404.
Try this :
[RoutePrefix("api")]
public class CategoryController : ApiController
{
....
[Route("addCategory")]
[HttpPost]
public IHttpActionResult AddCategory(string category)
{
var getCat = category;
if(getCat != null)
return Ok();
return NotFound();
}
I advice you to use Api Rest in C# with $resource angular. In my mind, it's the best pattern.
The problem is related to the service you are calling, 404 means not found:
404 http error
therefore something in the service URL or in your local server is not working.

angularjs $http service doesn't set cookie on POST but does with GET

The server side for my project provides WebApi 2.2
Client side is mobile application written in Ionic
Everything runs locally in chrome, mobile app in emulation mode.
1) On the server CORS is enabled and every API controller is decorated with:
[EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)]
2) angular $http service is also configured to work with CORS:
$httpProvider.defaults.headers.post['Accept'] = 'application/json, text/javascript';
$httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
$httpProvider.defaults.withCredentials = true;
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
delete $httpProvider.defaults.headers.common['X-FirePHP-Version'];
3) After user authenticates itself, I'm sending back form API controller a cookie:
var cookie = new CookieHeaderValue("user-id", result.Entity.ToString());
cookie.Path = "/";
cookie.HttpOnly = true;
cookie.Secure = true;
response.Headers.AddCookies(new CookieHeaderValue[]{ cookie });
I can see this cookie in the response header:
Set-Cookie:user-id=306d5247-1d3b-4120-b412-6ce45105397a; path=/; secure; httponly
4) In WebApi pipeline I registered global DelegatingHandler to read cookies sent with requests
The strange thing, for me, is that when I do make POST call (this request is preflighted), then in delegating handler cookies collection is empty. While changing the method AcceptVerb (both on the controller and in javascript service) to GET fixes my problem and my cookie is present.
My js service is:
var setData= function (model) {
var deferred = $q.defer();
var url = stringHelper.format(endpoints.setData, sessionId);
var config = {
url: url,
method: 'POST',
data: {
name: model.name,
email: model.email
}
};
$http(config).then(function (result) {
deferred.resolve(true);
}, function (error) {
$log.debug(error);
deferred.reject(error);
});
return deferred.promise;
}
Important notice: Making POST calls to the same endpoint from Postman works correctly.
Does anyone have a similar problem?
Thanks
I finally figured it out:
1) after comparison of working GET request with failing POST, I noticed that GET wasn't preflighted with OPTIONS, while POST was
2) in the CORS definig materials I read that OPTIONS are not sending any cookies
As a resolution I added checking request method in my DelegatingHandler - so it's passing OPTIONS methods down into pipeline without checking for autentifiaction cookie.
Hope that will help someone :)
Here's my WebApi DelegatingHandler:
public class UserCookieHandler : DelegatingHandler
{
static public string ServerSessionId = "server-session-id";
static public string UserSessionId = "user-session-id";
const string LoginUri = "api/secured/login/login";
async protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string sessionId = string.Empty;
if (request.Method != HttpMethod.Options && !request.RequestUri.PathAndQuery.Contains(LoginUri))
{
string cookie = request.GetCookie(ServerSessionId);
if (cookie == null)
{
return request.CreateErrorResponse(HttpStatusCode.Forbidden, "Please log in");
}
else
{
sessionId = cookie;
try
{
Guid guid = Guid.Parse(sessionId);
}
catch (FormatException)
{
request.CreateErrorResponse(HttpStatusCode.BadRequest, "Please log in again");
}
}
request.Properties[ServerSessionId] = sessionId;
}
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
return response;
}
}

Angular controller doesn't pass value to web api method with $http

This is my angularjs code:
var uname = resetPasswordRequestData.email
var request = $http({
method: "post",
url: workModule.config.Config.CommonUrl + "api/ResetPasswordRequest",
data: uname
});
web api code:
public class PerformPasswordResetController : ApiController
{
public int PerformResetPassword([FromBody]string uname)
{
CrmUser contact = null;
if (ModelState.IsValid)
{
try
{
contact = new PasswordResetProvider().GetUserByName(uname);
}
catch (Exception ex)
{
return 1;
}
}
}
My problem is when I make the call from Fiddler it works, but when I run the code it nicely rout to the web api method but in web api controller "uname" argument is null. when I pass some data from fiddler it pass that data to "uname" (in web api controller uname is not null)
can anyone help me?
I strongly suggest you use a Model class to receive the data on your server.
Something like this:
public class UserModel {
public string UserName { get; set; }
}
public class PerformPasswordResetController : ApiController
{
public int PerformResetPassword([FromBody]UserModel user)
{
...Do your stuff
}
}
And on your angular code:
var model = {
userName: resetPasswordRequestData.email
};
var request = $http({
method: "post",
url: workModule.config.Config.CommonUrl + "api/ResetPasswordRequest",
data: model
});
Also, if you don´t want (or can´t) change your server code, try this please:
var uname = resetPasswordRequestData.email
var request = $http({
method: "post",
url: workModule.config.Config.CommonUrl + "api/ResetPasswordRequest",
data: {
uname: uname
}
});

400 Bad Request when accessing a Sprint Rest method with AngularJs

I am trying to access an update rest method with AngularJs, but it is giving me 400 bad request error.
Here is my code.
#RestController
#RequestMapping("/api/loggedInUser")
public class UserController {
#RequestMapping(value = "/{id}",method = RequestMethod.PUT)
public AppUser updateLoggedInUser(#RequestBody AppUser user){
return userService.updateAppUser(user);
}
}
Here is the code for accessing the service from AngularJs:
App.factory('LoggedInUserService', ['$resource', function($resource) {
console.log('service injected');
return {
getLoggedInUser: $resource('api/loggedInUser', {}, {
query: {method: 'GET'}
}),
updateLoggedInUser: $resource('api/loggedInUser/:id', {}, {
update: {method: 'PUT', params: {id: '#id'}}
})
};
}]);
Here is the code for accessing the service in my app.js file.
.run(function($location, $rootScope, LoggedInUserService) {
LoggedInUserService.getLoggedInUser.query(function(loggedInUser) {
$rootScope.loggedInUser = loggedInUser;
console.log($rootScope.loggedInUser.username);
if (loggedInUser.role[0].authority === 'ADMIN_ROLE' && loggedInUser.pristineAccess) {
$rootScope.loggedInUser.isAdmin = true;
$rootScope.pristineAccess = false;
LoggedInUserService.updateLoggedInUser.update($rootScope.loggedInUser);
$location.path('/admin');
} else {
$rootScope.loggedInUser.isAdmin = false;
$location.path('/dashboard');
}
});
});
When I remove the #RequestBody annotation I don't get a 400 error but the parameter doesn't get populated.
What am I doing wrong here? I used the same kind of code in another place in the same application and it worked fine. The only difference here is that the rest method argument parameter is an entity object and not a pojo.
add consumes = MediaType.APPLICATION_JSON_VALUE to your controller method and check your POST content with web developers tool or firebug or simmilar tool
#RequestMapping(value = "/{id}", consumes = MediaType.APPLICATION_JSON_VALUE,method = RequestMethod.PUT)
public AppUser updateLoggedInUser(#RequestBody AppUser user){
return userService.updateAppUser(user);
}

Resources