ASP.NET Cookies are being set with no value - asp.net

I am trying to pass data from the login controller to the home controller via a cookie. This seems like it shouldn't be a big deal, but the cookie is being written with no value. Quite frustrating.
The code I'm using to set the cookie:
Customer user = new Customer();
int pass;
pass = MD5Hash(formResult.password);
if (pass == customer.CM_PASSWORD_HASH)
{
FormsAuthentication.SetAuthCookie(customer.CM_FULL_NAME, true);
HttpCookie userCookie = new HttpCookie("User");
userCookie.Values.Add("id", customer.CM_CUSTOMER_ID.ToString());
userCookie.Values.Add("companyid", customer.CM_COMPANY_ID.ToString());
userCookie.Values["type"] = "customer";
userCookie.Values["name"] = customer.CM_FULL_NAME;
HttpContext.Response.Cookies.Set(userCookie);
return RedirectToAction("Index", "Home");
}
This is what I'm trying to use to read the cookie:
if (Request.Cookies.AllKeys.Contains("User"))
{
HttpCookie userCookie = HttpContext.Request.Cookies["User"];
switch (userCookie.Values["type"])
{
case "customer":
Customer customer = new Customer();
customer.BridgeTrakId = Int32.Parse(Response.Cookies.Get("User").Values["id"]);
customer.CompanyId = Int32.Parse(Response.Cookies.Get("User").Values["companyid"]);
customer.Name = Response.Cookies.Get("User").Values["name"];
model.User = customer;
model.Equipment = DataAccess.EquipmentRepository.GetEquipment(customer.BridgeTrakId);
break;
default:
break;
}
}
The cookie gets created, and when I view it in the Chrome tools, the name is there, but the value is empty. When I view the userCookie in visual studio, it shows that it has a value.
Can anyone explain to me where I am losing the value, and how I can fix this.

You want to retrieve id, companyid and name same as you did for type.
HttpCookie userCookie = HttpContext.Request.Cookies["User"];
switch (userCookie.Values["type"])
{
case "customer":
Customer customer = new Customer();
customer.BridgeTrakId = Int32.Parse(userCookie.Values["id"]);
customer.CompanyId = Int32.Parse(userCookie.Values["companyid"]);
customer.Name = userCookie.Values["name"];
...
break;
default:
break;
}
Another Method
Request.Cookies["User"]["type"]
Request.Cookies["User"]["id"]
Request.Cookies["User"]["companyid"]
Request.Cookies["User"]["name"]
Note: I do not know the reason behind passing data. Ideally, you do not want to cookie just to pass data between controller. Instead, you want to use QueryString or SessionState.

Try setting the cookie like so.
HttpCookie cookie = new HttpCookie("Cookie");
cookie.Value = "Hello Cookie! CreatedOn: " + DateTime.Now.ToShortTimeString();
this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
return RedirectToAction("Index", "Home");

Related

vulnerability from security team in forget password controller in asp .net

I have a controller form application and the security team they said there is a vulnerability you can put any user_id fom postman inside the controller like this
ForgotPassword/user_id
how I can remove this vulnerability check the code below:
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult ForgotPassword(string emailId)
{
var helper = new Helper.Helper();
List<SqlParameter> args = new List<SqlParameter>();
args.Add(new SqlParameter("#Pin_email_id", emailId));
var req_resp = new Dictionary<string, object>();
try
{
using (DataSet dataset = helper.ExecuteSqlQuery("Web_Forgot_Password", args))
{
if (dataset != null && dataset.Tables.Count > 0 && dataset.Tables[0].Rows.Count > 0)
{
if (dataset.Tables[0].Rows[0]["Status"].ToString() == "Success")
{
req_resp["status"] = true;
req_resp["message"] = dataset.Tables[0].Rows[0]["Description"].ToString();
req_resp["code"] = dataset.Tables[0].Rows[0]["Code"].ToString();
string password = dataset.Tables[0].Rows[0]["user_password"].ToString();
SendForgotMail(emailId, dataset.Tables[0].Rows[0]["user_name"].ToString(), helper.Decrypt(password), dataset.Tables[0].Rows[0]["employee"].ToString());
return Json(req_resp);
}
else
{
req_resp["status"] = false;
req_resp["message"] = dataset.Tables[0].Rows[0]["Description"].ToString();
req_resp["code"] = dataset.Tables[0].Rows[0]["Code"].ToString();
return Json(req_resp);
}
}
else
{
req_resp["status"] = false;
req_resp["message"] = "Request Failed";
req_resp["code"] = "1005";
return Json(req_resp);
}
}
}
catch
{
var response = new
{
status = false,
message = "Request failed",
code = "1005"
};
return Json(response);
}
}
Well normally you store only password hashes in your database, which are not decryptable. Watching helper.Decrypt(password) in your code and sending the original password as a plain text in email is something painful. Normally I would just send a password reset link which can be used only once.
I checked the SqlParemater docs, it is added as a String value the way you use it, so it is not SQL injectable. Without the exact SQL I cannot tell much. I think they meant that it is SQL injectable, but then they should send evidence at least.

Login users at the same time problems in signalr

I'm working on a social network with ASP.NET and signalr. I have a simple login page, if it finds the user in the database it creates an Application variable and redirect the user to the profile page and in this page i invoke my Connect method declared in my hub class, this method takes the userid in the session and it give the friend list of this user. That works great when two or many users logged in at different time. The thing is, when two or several users logged in at the same time, the connect method declared in my hub takes the last user id stored in the Application variable and it give the friend list of this last user id and it send it to all user connected.
I can't find the correct approach.
Loggin Page code:
protected void btn_login_Click(object sender, EventArgs e)
{
Tbl_User user = new Tbl_User();
user = FonctionCommun.Login(txt_UserName.Text , txt_PassWord.Text);
if (user != null)
{
Application["UserID"] = user.UserID.ToString();
Response.Redirect("Profile.aspx");
}
else {
Label1.Visible = true;
}
}
My connect method code:
public void connect()
{
UserID = Guid.Parse(HttpContext.Current.Application["UserID"].ToString());
string OutPut = "";
if (ListOnlineUser.Count(x => x.UserID == UserID) == 0)
{
ListOnlineUser.Add(new OnlineUsers { UserID = UserID, ConnetionID = Guid.Parse(Context.ConnectionId) });
objchat.SetOnline(UserID);
ListFriends = objchat.GetFriendLoginStatus(UserID);
}
foreach (Tbl_User item in ListFriends)
{
if (item.Status == "1")
{
OnlineUsers onlineFriend = ListOnlineUser.FirstOrDefault(x => x.UserID == Guid.Parse(item.UserID.ToString()));
if (onlineFriend != null)
{
using (FIESTA_ADVISOREntities BD = new FIESTA_ADVISOREntities())
{
Tbl_User Obj_User = BD.Tbl_User.Where(o => o.UserID == UserID).FirstOrDefault();
if (Obj_User.ProfileImage != null)
{
string ext = BD.Assets.Where(o => o.url == Obj_User.ProfileImage).Select(o => o.MimeType).FirstOrDefault();
UserDetaille res = new UserDetaille() { UserID = Guid.Parse(Obj_User.UserID.ToString()), Username = Obj_User.UserName, ProfileImage = Obj_User.ProfileImage.ToString(), Ext = ext };
OutPut = JsonConvert.SerializeObject(res);
}
else {
UserDetaille res = new UserDetaille() { UserID = Guid.Parse(Obj_User.UserID.ToString()), Username = Obj_User.UserName, ProfileImage = "111", Ext = "png" };
OutPut = JsonConvert.SerializeObject(res); }
Clients.Client(onlineFriend.ConnetionID.ToString()).OnNewUserConnect(OutPut);
}
}
}
}
Clients.Caller.ShowFriends(ListFriends);
}
Try session variable instead of application variable. Application variable shared through out application working. So Whenever new user this is override. But if you use session variable that will never override by any other user
Also you can use query string in signalr in which you can pass userid as query string so in each request userid will be in query string
$.connection.hub.qs = 'userid=' + "UserId";

Redirecting with credentials to another website

I have two websites A and B. On A I have the login option and if the user is authenticated I need to send it to B with same credentials. I have access to the code of both websites. My first approach was trying to log the user on A and figure out how could I make a Post to a action method on a controller on B(this is a recurrent question here in stackoverflow) I found this website and I don't know if it is useful: http://www.codeproject.com/Articles/833007/Redirect-and-POST-in-ASP-NET-MVC. My second approach is putting all the data that I wanted to submit to B in Browser Session, call a Redirect to B and then in a method("GET") try to read all that data and check if I can proceed with the logic on B.
I want to know which is the best approach to make this happen, and also if the later is wrong or not.
I have this code on my website A:
[HttpPost]
public ActionResult Login(LoginModel user)
{
//hardcoding InternalUser
user.AccountType = ((int)AccountTypeEnum.Internal).ToString();
var validator = new LoginModelValidator();
var result = validator.Validate(user);
if (!result.IsValid)
{
return View((LoginModelDecorator) user);
}
var service = new AuthenticationServiceAgent(user.Username, user.Password);
var securityService = new SecurityServiceAgent(service.GeToken());
var state = securityService.ProcessAccount(service.GeToken() != null, user.Username);
if (state == (int)UserAccessEnum.Processed)
{
var type = securityService.GetAccountTypeByUser(user.Username);
//CHeck user type
var accountType = Enum.GetName(typeof(AccountTypeEnum), int.Parse(user.AccountType));
var types = type.Split(',').Select(n => n.Split(':')[0]).ToList();
var containsTheUserType = user.AccountType == "1"
? types.Contains("XXX") || types.Contains(accountType)
: types.Contains(accountType);
if (containsTheUserType)
{
//var cPrincipal = service.GetClaims();
var claims = securityService.GetIdentity().Select(claim => new Claim(claim.ClaimType, claim.Value)).ToList();
if (claims.Count != 0)
{
var cPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Custom"));
type.Split(',')
.ToList()
.ForEach(
ty =>
cPrincipal.Identities.First()
.AddClaim(new Claim("http://claims/custom/accounttype", ty)));
var token = new SessionSecurityToken(cPrincipal)
{
IsReferenceMode = true
};
FederatedAuthentication.WSFederationAuthenticationModule.SetPrincipalAndWriteSessionToken(
token, true);
Session["SEC_TOKEN"] = service.GeToken();
//Do I need to post?: SecurityToken, types and claims
//here is where I am redirecting the user
return Redirect("http://localhost:12345/Account/Login");
}
ModelState.AddModelError("LoginError", "Invalid Username or Password!");
}
ModelState.AddModelError("AccountTypeError", "You don't have access");
}
switch (state)
{
case (int)UserAccessEnum.BlockedAccount:
ModelState.AddModelError("StateError", "Your account is Blocked");
break;
case (int)UserAccessEnum.ChangePassword:
ModelState.AddModelError("StateError", "You need to change your password");
break;
case (int)UserAccessEnum.NoProcessed:
ModelState.AddModelError("StateError", "Error, please contact the system administrator");
break;
}
return View((LoginModelDecorator) user);
}
In my website B:
public ActionResult Login()
{
List<Claim> claims = //I need to get the claims from somewhere SESSION?
var type = //type used in the other Loging method
var securityToken = //securityToken used on the other Login method
if (claims.Count != 0)
{
var cPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Custom"));
type.Split(',')
.ToList()
.ForEach(
ty =>
cPrincipal.Identities.First()
.AddClaim(new Claim("http://claims/custom/accounttype", ty)));
var token = new SessionSecurityToken(cPrincipal)
{
IsReferenceMode = true
};
FederatedAuthentication.WSFederationAuthenticationModule.SetPrincipalAndWriteSessionToken(
token, true);
Session["SEC_TOKEN"] = securityToken;
return RedirectToAction("Index", "Home");
}
return null;
}
Any idea of how to complete the gaps that I have?

DotNetOpenAuth Claims request for OpenID does not return all values

I would like to obtain Birth Date from DotNetOpenAuth OpenID provider.
I have set up openID server as google right now and executing code like this:
Request
IAuthenticationRequest authenticationRequest = openid.CreateRequest(Request.Form["openid_identifier"]);
var fields = new ClaimsRequest();
fields.Email = DemandLevel.Require;
fields.FullName = DemandLevel.Require;
fields.BirthDate = DemandLevel.Require;
authenticationRequest.AddExtension(fields);
return authenticationRequest.RedirectingResponse.AsActionResultMvc5();
Response:
switch (response.Status) {
case AuthenticationStatus.Authenticated:
Session["FriendlyIdentifier"] = response.FriendlyIdentifierForDisplay;
FormsAuthentication.SetAuthCookie(response.ClaimedIdentifier, false);
ClaimsResponse untrustedExtension = response.GetUntrustedExtension<ClaimsResponse>();
ClaimsRequest claimsRequest = response.GetExtension<ClaimsRequest>();
if (!string.IsNullOrEmpty(returnUrl)) {
return Redirect(returnUrl);
} else {
return RedirectToAction("Index", "Site");
}
}
Problem is that with this Claims Request I get only email address, and I would like to obtall all of specified information.
Is it possible to obtain that informations?

More than 1KB cookie is not saving in my MVC4 application

In my mvc 4 application, i'm creating auth cookie with some other information. It works fine i f the data is less than 1KB, but when it exceeds 1Kb, cookie never creates.
As per my knowledge, max cookie size is apx 4KB. My code is below.
if (result.Status == ActionStatus.Success)
{
AuctionSiteApplication = result.Data;
CreateCustomAuthorisationCookie(AuctionSiteApplication.User.Email, obj.RememberMe, new JavaScriptSerializer().Serialize(AuctionSiteApplication));
if ((AuctionSiteApplication.User.UserType == UserType.SUAdmin) || (AuctionSiteApplication.User.UserType == UserType.Admin))
{
return RedirectToAction("Index", "Dashboard", new { area = "Admin" });
}
else
{
return RedirectToAction("Index", "Home", new { area = "" });
}
}
protected void CreateCustomAuthorisationCookie(String user_name, Boolean is_persistent, String custom_data)
{
FormsAuthenticationTicket auth_ticket =
new FormsAuthenticationTicket(
1, user_name,
DateTime.Now,
DateTime.Now.AddMinutes(30),
is_persistent, custom_data, ""
);
String encrypted_ticket_ud = FormsAuthentication.Encrypt(auth_ticket);
HttpCookie auth_cookie_ud = new HttpCookie(Cookies.UserCookie, encrypted_ticket_ud);
if (is_persistent) auth_cookie_ud.Expires = auth_ticket.Expiration;
System.Web.HttpContext.Current.Response.Cookies.Add(auth_cookie_ud);
}
protected override void OnAuthorization(AuthorizationContext filter_context)
{
if (Request.RawUrl.ToLower().Contains("www.")) filter_context.Result = RedirectPermanent(Request.RawUrl.ToLower().Replace("www.", ""));
HttpCookie auth_cookie = Request.Cookies[Cookies.UserCookie];
#region If auth cookie is present
if (auth_cookie != null)
{
FormsAuthenticationTicket auth_ticket = FormsAuthentication.Decrypt(auth_cookie.Value);
AuctionSiteApplication = new JavaScriptSerializer().Deserialize<AuctionSiteApplication>(auth_ticket.UserData);
System.Web.HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(auth_ticket), null);
ViewBag.AuctionSiteApplication = AuctionSiteApplication;
base.OnAuthorization(filter_context);
}
#endregion
// Rest Code
...
}
Below is the data which i am trying to store in cookie which is not saving
{"User":{"UserID":1,"Email":"abctest#pqr.com","FirstName":"abc","LastName":"Arora","UserType":2,"UserCompanies":[{"CompanyId":35,"CompanyName":"New Company","CompanyRoleId":96,"IsAdmin":true},{"CompanyId":36,"CompanyName":"tryrtyr","CompanyRoleId":103,"IsAdmin":true},{"CompanyId":37,"CompanyName":"abc","CompanyRoleId":109,"IsAdmin":false},{"CompanyId":35,"CompanyName":"New Company","CompanyRoleId":98,"IsAdmin":false},{"CompanyId":37,"CompanyName":"abc","CompanyRoleId":109,"IsAdmin":false},{"CompanyId":37,"CompanyName":"abc","CompanyRoleId":109,"IsAdmin":false},{"CompanyId":37,"CompanyName":"abc","CompanyRoleId":109,"IsAdmin":false},{"CompanyId":37,"CompanyName":"abc","CompanyRoleId":109,"IsAdmin":false},{"CompanyId":37,"CompanyName":"abc","CompanyRoleId":109,"IsAdmin":false},{"CompanyId":36,"CompanyName":"tryrtyr","CompanyRoleId":105,"IsAdmin":false}],"IsAuthenticated":true},"Company":{"CompanyId":0,"CompanyName":null,"CompanyRoleId":96,"IsAdmin":true}}
Below is the data which i am trying to store in cookie which is saving properly
{"User":{"UserID":2,"Email":"abc#pqr.com","FirstName":"abc","LastName":"Arora","UserType":1,"UserCompanies":[{"CompanyId":35,"CompanyName":"New Company","CompanyRoleId":0,"IsAdmin":false},{"CompanyId":36,"CompanyName":"tryrtyr","CompanyRoleId":0,"IsAdmin":false},{"CompanyId":37,"CompanyName":"abc","CompanyRoleId":0,"IsAdmin":false}],"IsAuthenticated":true},"Company":{"CompanyId":0,"CompanyName":"SUAdmin","CompanyRoleId":2,"IsAdmin":false}}
I still think there is no reason to store these datas in the cookie. You have to verify them against your database every time so you gain nothing.
However the problem is that your data is 968 (1KB) character and after the encription it's larger than 4KB.
UPDATE:
I try and my test result that the encrypted string generated by Enrypt method is 4032 byte. I think it's too close to the limit. With the other data of the cookie I'm sure it's exceeds the limit.

Resources