AngularJS and Web API form authentication - angularjs

I'm new to AngularJS and I'm starting to create a sample application, this application has 2 views:
Login View
Welcome View
Everything is working fine with my AngularJS dummy application but now I start implementing the Login functionality on server side:
[HttpPost]
public JsonResult Login(string credentials)
{
bool returnVal = false;
if (!string.IsNullOrEmpty(credentials))
{
FormsAuthentication.SetAuthCookie("DUMMY USER", true);
}
return Json(new
{
success = returnVal
},
JsonRequestBehavior.AllowGet);
}
And on Welcome Controller I have:
[Authorize]
public JsonResult GetPersons()
{
return Json(new
{
success = false
},
JsonRequestBehavior.AllowGet);
}
Then in order to implement the Forms Authentication I have to set in the Web.Config:
<authentication mode="Forms">
<forms loginUrl="/login" name=".ASPXFORMSAUTH" protection="All" timeout="1" slidingExpiration="true" />-->
</authentication>
The problem is that when doing that it will redirects the URL, so I get the following error:
GET http://localhost:21871/login?ReturnUrl=%2fperson%2fGetPersons 404 (Not Found)
And because AngularJS can't understand that route then I can't keep going.
Any clue on how to address this or maybe there is a better way to do it.
Thanks

You can use any authentication/authorization mechanism that you like. But when you are calling $http.get() or $http.post() you expect to receive a JSON object. But if you are not authenticated you will be redirected to login page which is an HTML page. Hence your code which is checking for success will fail.
You need to create a new custom authorize filter (like MyAuthorize) that authenticate/authorizes your user by any available technology (SimpleMembership, OAuth, etc) and if authentication fails then instead of returning a RedirectResult, returns a JSON object with an Error flag. Then you can check that flag after each $http.get() or $http.post(), and redirect the user from client side. We always develop our own communication service that calls $http.get() or $http.post and always make that check over there.

Related

Terminate user session when the browser or tab closes

I want to ultimately have user sessions end once the browser or tab is closed, and so far i had no luck. I have tried to enable offline_access in the IdentityServer config and in the client config but that doesn't seem to help. I am seeking some help with having my setup function in this way.
I use the flow of SignIn that redirects you too the IS4 login page then upon successful login you get redirected to the client app.
Here's how I handle it: I'm using a JavaScript sessionStorage variable to sense when the user has closed the browser (or tab).
<script>
var readValue = sessionStorage['checksession'];
</script>
If the browser was closed the variable will be undefined. In that case, I call a server-side page method to redirect the user to the login form:
<script>
var readValue = sessionStorage['checksession'];
if (readValue == null) {
// Redirect to Login
PageMethods.BrowserClosed();
}
</script>
Server side page method must be static and marked as [WebMethod]:
[WebMethod]
public static void BrowserClosed()
{
Util.hasClosedBrowser = true;
}
The static web method updates a boolean property in a static utility class (Util.cs) that I use in my asp.net project.
In Util.cs:
public static bool hasClosedBrowser { get; set; }
In the asp.net Page.Load event, I am looking for a "true" value in the "hasClosed" property defined in the utility class. If it's true, I call the Logout() method, which redirects to the login form:
if (Util.hasClosedBrowser)
{
Logout();
return;
}
At the end of the .aspx page after all of the elements, in a script tag I am setting the sessionStorage variable:
sessionStorage['checksession'] = "somevalue";
You can use any value in the sessionStorage cookie that you want, just know that it has to be a string unless you want to format it as a JSON string.
What's great about this approach is it correctly redirects to the Login form when the browser or the tab page was closed, but does not fire when the user simply refreshes the page (assuming the session hasn't actually expired). On a refresh, and as long as the session has not expired, the user's login state remains intact because the variable will still be present in sessionStorage.
Cheers,
-=Cameron

Session Handling in Angular JS, with Spring MVC

I am creating a project in AngularJs at frontend and Spring MVC in backend.
Now assume when a used logged in and if he wants to update his information, for this i have created an api which request for emailid and update the rest object in database of that email id
Now i have some questions,
1.) I dont want to use CookieStore or others sessionStorage or localstorage (because of my personal vulnerability experience and also i want to use session only) in Angular, how can i do it in angular with Spring MVC.
2.) How can i retrieve the email id from session to update data?
3.)If a user goes to another page how can i maintain that session in another page, how can i check that session is there and user is authentic to see the page
Read a lot about it but unable to find the exact solution with session. Answer over there is manage it by cookieStore.or localstorage, Please help
Let's try and see what is happening here using cookies is the right way to this, you may think it is not safe but is the safest way to do it. With cookies you will be sharing the same session in all tabs, so you can handle in all tabs and share it.
There is also an alternative option and is using URL rewriting, quoting #vanje in this question in stackoverflow
the session is only identified via a URL parameter containing the session ID. So every internal URL of your web application has to be enhanced with this parameter using the method HttpServletResponse.encodeURL(). If you are using a web framework like Wicket, chances are good that this is already done for you.
Lets go now with the Angular JS - Spring MVC approach:
There is no need to access the session within the Angular JS front-end, if you need to use it and you are using JSP you may use scriplet to retrieve the information openening a <%= session.getAttribute("user") %> , but as I said there is no need to do this. You may call your function, and retrieve this information in your controller in Spring.
You have a controller in angular JS that calls with http to your REST controller in Spring such like this. assuming that you save your user first in session:
$scope.getUserInfo= function () {
$http.get(appContextPath +'/rest/getuser/').success(function (data) {
$scope.user= data;
});
};
You may have a request mapping for the URL above:
#RequestMapping(value = "/rest/getuser", method = RequestMethod.GET)
#ResponseBody
public User getUserInfo (HttpSession session) {
User nUser = session.getAttribute("user");
return nUser;
}
I think the best way is to create a method in your AngularJS controller and then call it.
Java code:
#RequestMapping(value = "/menu/get", method = RequestMethod.GET, headers="Accept=*/*")
public #ResponseBody Empleado showMenu(HttpSession session) {
Empleado empleado = (Empleado) session.getAttribute("empleado");
return empleado;
}
AngularJS code:
angular.module('myModule')
.controller('myMenuController', ['$scope', '$http'
function($scope, $http){
getEmpleadoInfo = function () {
$http.get(myContextPage + '/menu/get')
.then(function(data) {
$scope.empleado = data;
})
}
getEmpleadoInfo();
}]);
This way, when you load the page, the object will be loaded on the scope.

AngularJS : How to encode decode JSON data in Services

I have used CakePHP + AngularJS for the application
I have below code in Sevices file
test.factory('Dashboard', function ($http, $q) {
return {
userDirectory: function (){
return $http.get(hostName + 'dashboards/userDirectory.json');
}
}
});
The above code calls dashboards's controllers userDirectory function and return JSON data this is how it's work.
Some one raised one issue, When he hit url "http://hostname/dashboards/userDirectory.json" he can see the response data in browser and that is not authenticated. Is there any way through which I can secure it.
By any encoding/decoding or What you prefer.
Decode/encode doesn't make any sense here if the client can decode it the user can get the data as well.
Just send data the user is allowed to see and use, even if he is authorized for that request, remove everything else that is not needed.
Use a JWT token to authorize them
https://github.com/ADmad/cakephp-jwt-auth
http://www.bravo-kernel.com/2015/04/how-to-add-jwt-authentication-to-a-cakephp-3-rest-api/
http://florian-kraemer.net/2014/07/cakephp-and-token-based-auth-with-angular-js/

SQL query failure in ASP.NET Web API on wake from sleep

We are experiencing an edge-case error with ASP.NET Web Api 2 and MSSQL. The situation is this:
An external process is storing a complex token in a database record
along with a simpler token that identifies the record.
The external process then redirects the user to an endpoint in our API passing the simple token in the url.
The API uses the simple token to look up the database and retrieve the complex token
The user is then redirected to another url with the complex token injected into the window object of the response.
Here is the problem:
Two simultaneous requests, from different users, come in to retrieve complex tokens the server. The first request fails. The second request gets served the complex token that is associated with the first request.
This only occurs when the Windows Server is waking from sleep.
At all other times the users send in their simple token and receive back the correct complex token.
Can anybody shed any light on what is causing the problem and how to fix?
A simplified version of the code that is associated with this case is here:
// The Controller action that receives the simple Token
public ActionResult GetToken(string simpleToken)
{
ApiOutput.UserToken.Token = QueryToken(simpleToken);
return RedirectToAction("Index");
}
// The method that retrieves the complex token from the database
public static string QueryToken(string simpleToken)
{
using (var _wdb = new AppDbContext())
{
var data = _wdb.TokenData.FirstOrDefault(d => d.SimpleToken == simpleToken);
return data.ComplexToken;
}
}
// Controller Index action
public ActionResult Index()
{
return View();
}
<!-- The Index view where the complex token is returned -->
#{ Layout = null; }
#using myApp.Models
#model ApiOutput.UserToken
<!DOCTYPE html>
<html>
<body>
<script>
window.dbtoken = "#ApiOutput.UserToken.Token";
</script>
</body>
</html>

CakePHP: Redirect to login from custom component

In a custom component I am making API calls. If the API call returns 403 I want to logout the user and redirect to the login. With the following code I get a response object without knowing if the response is a redirect or if the response is containing the data of the request. Besides get I have also other methods implemented in the Component so that I have at the end over 50 times a call to the RestAPIComponent.
Calling the RestAPIComponent
public function view($id)
{
$resource = $this->__getSingularResourceName();
$$resource = $this->RestApi->get($id)->json;
$this->set(compact($resource));
}
RestAPIComponent
public function get($id = null, array $query = [], $action = null)
{
$path = (is_null($id) === false) ? $id : '';
$response = $this->_http->get($path . '/' . $action, $query, $this->_getAuthHeader());
return $this->_handleResponse($response);
}
private function _handleResponse(Response $response)
{
if ($response->statusCode() == 403) {
$this->Cookie->delete(TOKEN);
$this->Cookie->delete(USER);
$controller = $this->_registry->getController();
return $controller->redirect($controller->Auth->logout());
} else {
return $response;
}
}
There may be following reasons behind it, getting the 403 error using auth component --
1.It is possible to get a 403 via code. Check this out from the CakePHP docs (http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#handling-unauthenticated-requests): If authenticator returns null, AuthComponent redirects user to login action. If it’s an ajax request and AuthComponent::$ajaxLogin is specified that element is rendered else a 403 http status code is returned.
2.Multiple Ajax calls shouldn't be the causing factor of a 403 error.
3.The standard routing is handled by CakePHP itself. If you need some different routing, you should configure this in routes.php. I would say using .htaccess is only for a really extreme routing need and should be a last resort.
4.Yes that could be a cause, since you would no longer be logged in, thus get Auth 403s
For more detail -- you could visit the link Common reasons behind 403 errors

Resources