Using FormsAuthentication on webMethod - asp.net

I have a page that has a comment section. This section communicates to a WebMethod in order to insert a new comment.
[WebMethod]
public static bool insertComment(string commentString)
{
//userName validation here
string userName = (FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name);
return new CommentClass().InsertComment(commentString, userName);
}
The problem is: "An object reference is required for the non-static field".
I know I could send the information from a hidden field, or a div, however, that information field may be changed easily.
So which way could be used to know which user is posting, in server side?
thanks a lot!

Request object is an instance that lives in Page, so you need a reference to access this object in a static context. You can use HttpContext.Current.Request for accessing the Request in this context.
[WebMethod]
public static bool insertComment(string commentString)
{
//userName validation here
string userName =
(FormsAuthentication.Decrypt(
HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name);
return new CommentClass().InsertComment(commentString, userName);
}

Related

ASP.NET Core 3.1: POST-REDIRECT-GET: Passing parameters

I'm trying to implement POST-REDIRECT-GET technique where I post a JSON string to my razor OnPost method. This in turn redirects to OnGet method that takes in that string parameter. How do I hide this input parameter string to my OnGet method?
Edit: I tried using ViewData but the value is always null in my OnGet method even though I set it before redirect.
public async Task<IActionResult> OnPostData(string input_JSON)
{
TempData["InputJSON"] = input_JSON;
return RedirectToPage("GetData");
}
public async Task<IActionResult> OnGetGetData()
{
string tempData = TempData["InputJSON"] as string;
//do somethig with string;
}
I do form post in my javascript and when the new window opens, I see the input_string in my URL. How do I pass parameters between methods?
https://learn.microsoft.com/en-us/aspnet/core/security/gdpr?view=aspnetcore-2.2#tempdata-provider-and-session-state-cookies-arent-essential
According to Microsoft, TempData provider and session state cookies aren't essential. I had to make it essential in my Startup.cs file's ConfigureServices:
services.Configure<CookieTempDataProviderOptions>(options => {
options.Cookie.IsEssential = true;
});

How to return a custom view OR a JSON when the Authorization fail, instead of showing a username and password dialog

I am working on an asp.net mvc 4 web application , and i wrote the following custom authorization class:-
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CheckUserPermissionsAttribute : AuthorizeAttribute
{
public string Model { get; set; }
public string Action { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (!httpContext.Request.IsAuthenticated)
return false;
//code goes here
if (!repository.can(ADusername, Model, value)) // implement this method based on your tables and logic
{
return false;
//base.HandleUnauthorizedRequest(filterContext);
}
return true;
// base.OnAuthorization(filterContext);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
var viewResult = new JsonResult();
viewResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
viewResult.Data = (new { IsSuccess = "Unauthorized", description = "Sorry, you do not have the required permission to perform this action." });
filterContext.Result = viewResult;
}
else
{
var viewResult = new ViewResult();
viewResult.ViewName = "~/Views/Errors/_Unauthorized.cshtml";
filterContext.Result = viewResult;
}
base.HandleUnauthorizedRequest(filterContext);
}
}
}
but the only problem i am facing now is that if the authorization fail then the user will be prompted to enter username and password, although i have override the HandleUnauthorizedRequest to return a view or JSON based on if the request is AJAX or not. so can you advice why the user is being prompted to enter his username and password when the authorization fail, instead of receiving the _unauthorized view or the JSON containing an error message
but the only problem i am facing now is that if the authorization fail
then the user will be prompted to enter username and password,
although i have override the HandleUnauthorizedRequest to return a
view or JSON based on if the request is AJAX or not.
That's because you are absolutely always hitting the following line in your HandleUnauthorizedRequest method:
base.HandleUnauthorizedRequest(filterContext);
You know what this line do? It calls the base method. You know what the base method do? It returns 401 status code. You know what happens when 401 status response code is returned in an ASP.NET application in which you are using Forms Authentication? You get the login page.
So yeah, if you are using AJAX or something and intend to be returning some JSON or something make sure that the base stuff is never called. By the way in your else condition you seem to be attempting to render some ~/Views/Errors/_Unauthorized.cshtml view which obviously is useless once again because you are also calling the base method which will simply redirect to the login page.
I think that at this stage of my answer you already know what to do: get rid of this last line of your HandleUnauthorizedRequest method in which you are throwing all your efforts into the trash by calling the base method.
And if you want to do things properly and return 401 status code and not get the login page but instead return some custom JSON you could use the SuppressFormsAuthenticationRedirect property on the Response object. And if you are using some legacy version of the .NET framework which doesn't have this property you might find the following blog post useful in which Phil Haack explains how to handle this case.

ASP.NET Web API how to authenticate user

I'm trying to create a simple user authentication function but I just can't get it to work.
Here is the code I'm working on:
public class LoginController : ApiController
{
private void SetPrincipal(IPrincipal principal)
{
Thread.CurrentPrincipal = principal;
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
}
public bool Login(string token)
{
//Check token
if (.....)
{
//Authenticate user
var identity = new GenericIdentity("Test user");
SetPrincipal(new GenericPrincipal(identity, new string[]{"Test role"}));
}
}
[Authorize]
public string TestFun()
{
return "Hello " + User.Identity.Name;
}
}
So, if I try to call method TestFun() first, it returns error code 401 like it should.
However when I call method Login() it should somehow save user credentials, but this is where I get lost, I just can't get it to work.
TestFun() always returns error code 401 even if I call Login() first.
If I try to put return "Hello " + User.Identity.Name; in the Login() function it returns correct username, but in the TestFun() the user is not available.
I've even tried using Sessions and FormsAuthentication but I just can't get it to work, even on this really simple example.
Can someone please tell me what am I missing?
Thanks!
The Login method sets the principal for current request only. Just after the request completes, the principal context is wiped out so that the server can handle other requests for other users. When a new request comes, eons later from the server perspective, the principal context no longer exists and if nothing restores it, the request is unauthenticated.
To fix this you have to return something from your login method to the client. Not only bool but rather - an authentication token. Something the client could use to authenticate further requests.
It could be anything. Forms cookie would be fine as long as the client remembers to append it to further requests. Another common practice is to have a custom authentication token returned to the client and then appended by the client in a custom authentication header. And as forms cookies are handled by the Forms Authentication module, custom headers would need a custom mvc authentication filter or custom asp.net authentication module so that the token is readed, the identity is extracted and restored just before the request is about to execute.
If you don't like to bake your own token infrastructure, I would also recommend OAuth2 tokens. There is a great book that contains easy to follow examples on this and other possible authentication methods:
http://www.amazon.com/Pro-ASP-NET-Web-API-Security/dp/1430257822/ref=sr_1_1?ie=UTF8&sr=8-1&keywords=web+api+security
I just got the same issue, yes, I agreed we need to save that principal into somewhere (cookie, session) for other action to use, so, in SetPrincipal function I added
HttpContext.Current.Session["user"] = HttpContext.Current.User;
Now, the issue is how to get it back for other action, the idea popups in my mind is to extend AuthorizeAttribute and override IsAuthrized function, it will read the session first and if it found the session, it will return true, otherwise it will return false.
namespace BinZ
{
public class MyAuthorizeAttribute:AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext) {
HttpContext.Current.User = HttpContext.Current.Session["user"] as IPrincipal;
return HttpContext.Current.User != null;
}
}
}
Please remember to replace [Authorize] to [MyAuthorizeAttribute] in WebApi controller.
It works for me very well.
Cheers

protecting against CSRF in asp.net web application when using ajax

I have an asp web application I wanted to update to prevent cross site request forgery attacks.
I have used the Microsoft auto-generated code from VS 2012, and added it to the master page as described here. It is working well, but one page posts JSON via an AJAX request to a webmethod
I would like to check this ajax request as well.
The forseeable problems are:
var responseCookie = new HttpCookie(AntiXsrfTokenKey)
{
//Set the HttpOnly property to prevent the cookie from
//being accessed by client side script
HttpOnly = true,
this can obviously be changed, but this would then seem to increase site vulnerability. Is this a significant issue?
I can send the value of the viewstate hidden input with the ajax request, but this will then need to be decoded back into key value pairs to do the equivalent of:
(string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
Is there an easy way to use existing asp.net methods to do this?
Thank you for any help.
Here is what i have discovered. I ended up using the LosFormatter, as described by geedubb, by adding the following code to the MasterPage, and assigning the value to a hidden input which is posted back with the ajax request. I did not realise when I posted the question that HttpCookie.HttpOnly property still posts back the cookie on an ajax request, and so can be left set to false.
internal string GetToken()
{
// call the static method to guarantee LosFormatter remains threadsafe
return GetToken(_antiXsrfTokenValue);
}
private static string GetCurrentUserName()
{
var currentUser = HttpContext.Current.User.Identity;
return (currentUser == null) ? string.Empty : currentUser.Name;
}
private static string GetToken(string token)
{
var los = new System.Web.UI.LosFormatter(true, token);
var writer = new System.IO.StringWriter();
var data = new Dictionary<string,string>();
data.Add("TokenValue",token);
data.Add("UserNameKey", GetCurrentUserName());
los.Serialize(writer, data);
return writer.ToString();
}
internal static void Validate(string token)
{
var request = HttpContext.Current.Request;
var requestCookie = request.Cookies[AntiXsrfTokenKey];
var antiXsrfTokenValue = requestCookie.Value;
var los = new System.Web.UI.LosFormatter(true, antiXsrfTokenValue);
var xsrfData = (Dictionary<string,string>)los.Deserialize(token);
if (xsrfData["TokenValue"] != antiXsrfTokenValue || xsrfData["UserNameKey"] != GetCurrentUserName())
{
throw new System.Security.Authentication.AuthenticationException("Validation of Anti-XSRF token failed.");
}
}
Initially, I had tried sending the value of the _VIEWSTATE hidden input, using the same code
var los = new System.Web.UI.LosFormatter(true, antiXsrfTokenValue);
var ajaxViewState = los.Deserialize(token)
but this threw an error stating the supplied key could not deserialze the string. obviously setting
Page.ViewStateUserKey = _antiXsrfTokenValue;
has a more complex key than the supplied key alone. I would be interested if anyone knew how to deserialize a viewstate string with a userKey.
The only problem with the method I have provided is the size of the string posted back - 1976 characters long for a GUID + 6 character username!!!!
If approaching this problem again, I would reference the System.Web.WebPages.dll (used in an mvc project), and use the same methods which create the Html.AntiForgeryToken in MVC
namespace System.Web.Helpers
{
/// <summary>
/// Provides access to the anti-forgery system, which provides protection against
/// Cross-site Request Forgery (XSRF, also called CSRF) attacks.
/// </summary>
public static class AntiForgery
{
public static void GetTokens(string oldCookieToken, out string newCookieToken, out string formToken)
public static void Validate()

Spring login need custom msg on screen

I want to display custom message which will be fetched from database when user try to login on login page. This message can be changed by administrator. So always need to be fetched from database.
We are using acegi spring.
Do anybody know how to do this?
Jaydeep.
set your login page to be served from a controller, then you can set a modelattribute with your custom message and show it on the login screen
e.g.
#ModelAttribute("customMessage")
public String populateCustomeMessage() {
String msg // Code to get message from db and set it into a string
return msg;
}
#RequestMapping(value = "/login.html", method = RequestMethod.GET)
public String handleRequest() {
return "login";
}
Following link somewhat discusses on the topic you need (but not fetching from database)
how to display custom error message in jsp for spring security auth exception

Resources