html/Javascript Clientside User Login - javascript

I am adding authentication to my web application. It is an asp.net mvc single page application. Currently the web application is using the asp.net mvc for only one thing, authentication. I check the Request.IsAuthenticated in the AppController, if it isnt authenticated than I serve the login page (else I save the app.html page). In my AccountController I have the following Logon Action:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
//VALIDATE USER NAME AND PASSWORD
if (Repository_Security.CheckUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "App");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Really its just taking a user name and password and validating against the database. Than sets the AuthCookie if it passes.
My question is, is this possible if I do this entirely clientside in the browser in javascript and ajax data calls? Than be able to add a check in my clientside code to see if the user is authenticated, else throw them to a login page?
Any ideas? thanks.

Yes, and MVC is perfect for working clientside Ajax.
You can modify your controller to return JSON, and with a jquery ajax call you can process the returned json using clienside javascript.
Change the last line (return View(model)) to look something like the following
return Json(new {IsSuccess=successVariable, RedirectUrl=myRedirectUrl, Message=failedErrorMessage});
Adjust your Redirect lines to instead set myRedirectUrl variable.
Update
If you want to get rid of MVC in your project (as it's an overkill for such a simple task), add a web service (asmx) to your site. Inside create a webmethod similar to following:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public LogonResponse Logon(LogonModel model){
... do login logic as your original code...
return new LogonResponse() { IsSuccess = successVar, RedirectUrl=myRedirectUrl, Message=failedErrorMsg};
}

You can do that from client-side as well... but if your application need full security then this model will open-up many security loop holes.

When you call FormsAuthentication.SetAuthCookie() it sends a Set-Cookie header back to the client so their browser can store the authentication cookie. You can just check for the existence of this cookie client-side with JavaScript. If it exists then continue, if it doesn't then do a redirect (window.location.href) to the login page, e.g.:
if (document.cookie.indexOf(".ASPXAUTH") >= 0) alert("You are logged in");
else window.location.href = "http://www.domain.com/login";

Related

Java Idap Authentication for HTML webpage

I want to add Idap authentication to the web applications that I developed with HTML and AngularJS.
But I don't understand how I should do it. I looked online and only found answer to how to set up IDAP in JAVA.
{
String uid = "User";
String password = "Password";
String BASE = "ou=People,dc=objects,dc=com,dc=au";
String userDN = "uid=" + uid + ",ou=people," + BASE;
String HOST = "ldap://ldap.example.com:389";
String INIT_CTX = "com.sun.jndi.ldap.LdapCtxFactory";
// Setup environment for authenticating
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, INIT_CTX);
env.put(Context.PROVIDER_URL, HOST);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, userDN);
env.put(Context.SECURITY_CREDENTIALS, password);
env.put(Context.REFERRAL, "follow");
try
{
DirContext authContext =
new InitialDirContext(env);
System.out.println("I am authenticated");
}
catch (AuthenticationException ex)
{
System.out.println("authentication failed");
}
catch (NamingException ex)
{
ex.printStackTrace();
}
}
So the above code is just a tryout from me, and it works fine.
I will make it into a function later and i want to use it to authenticate the users that come to use my web application.
I have no idea how to do that though. I mean I know I should create a HTML page that request users to enter ID and Password. then I can use AngularJS to capture those data.
But then what?
How do I use the Java function in AngularJS or HTML? I mean once authenticated, It should jump to the index.html page.
Thanks guys, Sorry i am new to web development.
Java runs on the backend only. You grab the username/password in Angular and POST it back to your Java application. Typically, you'd set this up with Dropwizard or Spring Boot. The backend then returns either success or failure to Angular which then sets the browser location to your index.html.
Read up on Jersey, REST and Dropwizard, there's lots of examples. Alternatively, you can run a Tomcat server and let this do the LDAP auth via container managed security - you only need to supply the LDAP info in the web.xml.

Best way to prevent parameter tampering and send values with Javascript?

I am posting a form to the controller and making it asynchronous. I am storing values in input form hidden. When a button is clicked, a javascript function is called. It both fetches the value from an input field, as well as a value from input form hidden. It then sends a json string to the controller to handle this request.
Controller:
[HttpPost, Authorize]
public ActionResult DoSomeStuff (string leagueName, string doSomething) {
var service = new Service(_db);
var league = service.GetLeague(leagueName);
if (league != null) {
// validate doSomething
league.Action = doSomething;
_db.SaveChanges();
}
return new EmptyResult();
}
Javascript:
$(document).on("click", "#submitForm", function () {
var json = {
"leagueName": $("input[name=leagueName]").val(),
"doSomething": $("input[name=doSomething]").val()
};
$.post("/Home/DoSomeStuff/", json, function () {
// async display something
});
}
Html:
<input type="text" name="doSomething">
<button type="submit" id="submitForm"</button>
<input type="hidden" name="leagueName" value="#item.League.LeagueName" />
What is the best way to let javascript fetch a stored value (more secure way then input type hidden)?
How can I prevent some user from altering the value from the input type
hidden field?
How can I prevent some user from altering the value from the input
type hidden field?
You cannot!
What is the best way to let javascript fetch a stored value (more
secure way then input type hidden)?
The general rule is, do not trust data coming from client. You should always validate it on server before doing anything.
If you are worried about a user update the league name field value in the form to some other users league name and post it, What you should be doing is, explicitly checking whether the user has proper permission to do something on the posted league in your server code.
[HttpPost, Authorize]
public ActionResult DoSomeStuff (string leagueName, string doSomething) {
var service = new Service(_db);
var league = service.GetLeague(leagueName);
// Now check whether the current user has access/permission
// to perform some operation on this league.
// Ex : if(!service.IsUserAuthorizedToDoSomething(league))
// {
// return View("NotAuthorized");
// }
//to do: Return something
}
If the value needs to come from the client (and be part of the HTTP request) then there's absolutely nothing you could do to prevent the client from modifying its contents. If the client is not supposed to modify the contents of some fields then those fields have nothing to do in your markup and be part of the postback HTTP requests (be it as hidden fields or whatever markup element comes to your mind). They should safely reside on your server (database?) and be retrieved using some identifier coming from the client. Obviously whether the client can access the information related to this identifier is subject to something called authorization. Basically you should first know who your client is (authentication) and then verify in your data model if this client has access to the corresponding records. It's as simple as that.
[HttpPost]
[Authorize]
public ActionResult DoSomeStuff (string id, string doSomething)
{
var service = new Service(_db);
var league = service.GetLeagueById(id);
if (!HasAccessToLeague(User.Identity.Name, league))
{
// you are not suppose to modify the contents of this league
// throw him a 404 or something
}
else
{
if (league != null)
{
// validate doSomething
league.Action = doSomething;
_db.SaveChanges();
}
}
return new EmptyResult();
}
obviously the implementation of the HasAccessToLeague(string username, string leagueId) method will greatly depend on your data model and how your authorization logic.
Also you used XSS in your question title but here your problem is not about XSS or javascript but rather designing authorization layer in your web application.
of course its possible to do this! After all, your server app manages to track who the currently logged on user is using insecure client storage.
When a user logs on, the server will generate a secret message and store it in an encrypted token that's passed to the client and bak in a cookie (which is just another piece of unsecured client data storage). When you send requests to the server, it gets the cookie, decrypts it, and checks the data inside to tell who the user is.
You can do the same - for the hidden fields, encrypt them, put them in a hidden input (or a cookie if you prefer) and send them back to the server. However, you can only use them in your client javascript if you send them plain text as well, which means you need to still perform some checking on the server, but that checking can be as simple as comparing the encrypted values with the hidden form values, if any do not match, reject the request.
things to bear in mind though, encrypion is slow. It can be quicker to fetch the values from a DB instead, though you might use a cache for these. YMMV.
An alternative option is to generate a javascript file with the values in and ensure that the client browser cannot edit them using security features such as content-security-policy. The disadvantage is an inability to use these values in html (as obviously the user can edit them there) so you'll have to pass data back to the server via js calls.

Adding Captcha in Registration Form using Ajax , Jquery or JavaScript?

Iam writing code for Registration page in Jquery, when i came to using devexpress captcha in registration page, that one is not validating from jquery.so, i replacing captcha to jquery captcha. can any one help me how to write the captcha in Jquery.
Here is a nice library I use in MVC called reCAPTCHA plugin for .NET: https://code.google.com/p/recaptcha/
There is a Nuget package available for it. Nuget id: recaptcha current verion 1.0.5.0
Now to use it: in your View
Inside your view above or bellow your Submit button: You add this code:
<p>
#Html.Raw(#Html.GenerateCaptcha())
#Html.ValidationMessage("captcha")
</p>
Then in your controller action add the RecaptchaControlMvc.CaptchaValidator attribute and also add an addition bool paramater for the recapccha e.g. captchaValid
HttpPost, RecaptchaControlMvc.CaptchaValidator]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
public ActionResult Register(RegistrationViewModel model, bool captchaValid)
{
// If the bool is true The Recapcha validation was successful.
// If not then you can add a model error with the property name for the: `#Html.ValidationMessage("captcha")`
if (!isLoan && !captchaValid)
{
ModelState.AddModelError("captcha", "Verification word is incorrect. Try again.");
}
if (ModelState.IsValid)
{
// go an ddo your registration or login
}
else
{
// handle errors and other messages
}
return View(model);
}
The Library will take care of the rest.

Anti-forgery token issue in ASP.NET MVC integration with Angular JS

Good day!
I'm dealing with an issue for some time now and can't seem to find a solution. I have an usual ASP.NET MVC project on 'top' of which I added an Angular JS project. I also have a Web API, but this is not relevant for my issue. The web application itself is the Angular project, making calls to the API.
I used the default authentication system from ASP.NET MVC using the default Login.cshtml View and default AcountController methods for login/logout.
The problem I'm dealing with is the following:
A user enters the website and is prompted with the login form. After inserting valid account details, he is redirected to the main page (index, from the angular js project). IF the user clicks on the Back button of the browser, he is prompted with login form again and if he inserts his user and password again (or any other sign-in details), I receive a HttpAntiForgeryException with the following message: "The provided anti-forgery token was meant for a different claims-based user than the current user."
I tried disabling the back button with javascript (window.history.forward(1);), but it doesn't work apparently on older browser versions and it's by far an elegant solution. I tried reloading the login page (because after clicking back, if you reload the page you will be redirected to the index page (since the session is still valid)) and none of these solutions really work.
Any ideas?
Thank you in advance!
Update: so far I've included AntiForgeryConfig.SuppressIdentityHeuristicChecks = true; in Application_Start() and also this:
public class HandleAntiForgeryError : ActionFilterAttribute, IExceptionFilter {
#region IExceptionFilter Members
public void OnException(ExceptionContext filterContext)
{
var exception = filterContext.Exception as HttpAntiForgeryException;
if (exception != null)
{
var routeValues = new RouteValueDictionary();
routeValues["controller"] = "Account";
routeValues["action"] = "Login";
filterContext.Result = new RedirectToRouteResult(routeValues);
filterContext.ExceptionHandled = true;
}
}
#endregion }
[HandleAntiForgeryError]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
}
The only issue left is when I click back and try to login with another user it fails. Meaning I remain logged in with the previous user. I expect this to be normal, but is there a way to change that (as in when I click back and enter other user's credentials, to get logged in with those new credentials (even though I'm already logged in)).
SOLVED: In my code I had the following line:
if (User.Identity.IsAuthenticated)
return RedirectToAction("Index", "App");
That is why after logging in with another user I was being redirected to index being logged in with the old credentials.
I had this same issue and i solved this issue by adding following line in Application_Start() event in Global.asax in my case:
AntiForgeryConfig.SuppressIdentityHeuristicChecks = true;
Also add this in Application_Error():
Exception ex = Server.GetLastError();
if (ex is HttpAntiForgeryException)
{
Response.Clear();
Server.ClearError(); //make sure you log the exception first
Response.Redirect("~/Home/Index", true);
}

Can I detect valid JSONP return?

I want to send/receive data to a web service on a different server that does not have CORS enabled. I have to use JSONP to do it. The service requires authentication and most of the time the user is in an SSO environment and the SSO mechnaism easily passes them to the service without issue.
When not inside the SSO environment, the user is redirected (301) to a login page, which of course returns invalid javascript because the file would start with <!Doctype...
Is there a way to see if the returned data is operable? I know exactly what the first 15 chars should be anytime the user can successfully access the service. I would like to check the return and then do something like:
if(dataIsValid){ //continue normally, build page with returned data }
else{ //redirect to non-SSO login page }
Or anything that resembles that kind of a workflow.
I assume you're using jQuery since you've added a relevant tag.
var dataIsValid = true;
var data = {};
try {
data= $.parseJSON(data);
} catch (exc){
dataIsValid = false;
}
//...

Categories

Resources