MVC FormsAuthentication IsInRole in View not working - c#

I am authenticating a user:
[Route("Login"), HttpPost, AllowAnonymous]
public LoginViewModelResponse Login(LoginViewModelRequest data)
{
if(!Membership.ValidateUser(data.Username, data.Password))
{
return new LoginViewModelResponse
{
DisplayMessage = "Invalid Username/Password!",
IsSuccess = false,
RedirectUrl = "/Home/"
};
}
FormsAuthentication.SetAuthCookie(data.Username, false);
ClaimsIdentity identity = new GenericIdentity(data.Username);
var roles = "Administrator,User".Split(',');
// var client = AuthorisationService.instance.GetAuthenticatedUser();// new ClientService().GetClientById(1);
var principle = new GenericPrincipal(identity, roles);
HttpContext.Current.User = principle;
System.Threading.Thread.CurrentPrincipal = principle;
if (User.IsInRole("Administrator"))
{
var b = 1;
}
return new LoginViewModelResponse
{
IsSuccess = true,
DisplayMessage = "OK",
RedirectUrl = "/Home/"
};
}
And the test for 'IsInRole' is working.
However, I have the following in my View (_layout), and the check for Administrator fails.
if (ViewContext.HttpContext.User.IsInRole("Administrator"))
{
<li class="dropdown">
...
Is there something I need to do to allow the View to understand "IsInRole"?
This works:
#if (ViewContext.HttpContext.User.Identity.IsAuthenticated == false)
But 'IsInRole' always evaluated to false.

Since you set FormsAuthentication cookie by yourself, you'll need to create Principle object and assign it to current thread on every request inside AuthenticateRequest event.
Global.asax.cs
public class Global : HttpApplication
{
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpCookie decryptedCookie =
Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (decryptedCookie != null)
{
FormsAuthenticationTicket ticket =
FormsAuthentication.Decrypt(decryptedCookie.Value);
var identity = new GenericIdentity(ticket.Name);
var roles = ticket.UserData.Split(',');
var principal = new GenericPrincipal(identity, roles);
HttpContext.Current.User = principal;
Thread.CurrentPrincipal = HttpContext.Current.User;
}
}
}
Sign-In method
public void SignIn(string username, bool createPersistentCookie)
{
var now = DateTime.UtcNow.ToLocalTime();
TimeSpan expirationTimeSpan = FormsAuthentication.Timeout;
var ticket = new FormsAuthenticationTicket(
1 /*version*/,
username,
now,
now.Add(expirationTimeSpan),
createPersistentCookie,
"" /*userData*/,
FormsAuthentication.FormsCookiePath);
var encryptedTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName,
encryptedTicket)
{
HttpOnly = true,
Secure = FormsAuthentication.RequireSSL,
Path = FormsAuthentication.FormsCookiePath
};
if (ticket.IsPersistent)
{
cookie.Expires = ticket.Expiration;
}
if (FormsAuthentication.CookieDomain != null)
{
cookie.Domain = FormsAuthentication.CookieDomain;
}
Response.Cookies.Add(cookie);
}

Related

asp.net mvc 4 login cookies not working

I am using this login method to create cookies as session works fine. but cookies is not working. is there any problem here in the code regarding cookies.
[HttpPost]
public ActionResult Login(login a)
{
if (ModelState.IsValid)
{
Database1Entities1 b = new Database1Entities1();
var obj = b.registras.Where(m => m.email.Equals(a.email) && m.pass.Equals(a.pass)).FirstOrDefault();
if(obj != null)
{
FormsAuthentication.SetAuthCookie(a.email, a.RememberMe);
Session["UserID"] = obj.Id.ToString();
Session["UserName"] = obj.name.ToString();
if (a.RememberMe)
{
HttpCookie usercookie = new HttpCookie("UserIDa");
usercookie.Expires = DateTime.Now.AddMinutes(2);
usercookie.Values.Add("email",a.email);
usercookie.Values.Add("pass",a.pass);
HttpContext.Response.Cookies.Add(usercookie);
// var authTicket = new FormsAuthenticationTicket(1,a.email,DateTime.Now, DateTime.Now.AddMinutes(20), a.RememberMe,"", "/");
// HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(authTicket));
//Response.Cookies.Add(cookie);
//HttpCookie newcook = Request.Cookies["UserIDa"];
HttpContext.Request.Cookies.Get("UserIDa");
}
ViewBag.message = "congratz u login";
return RedirectToAction("welcome","Home");
}
else { }
}
return View(a);
}

FormAuthentication .ASPXAUTH cookie showing null after few moments in ASP.NET MVC

I have implemented FormAuthentication in asp.net mvc 5 and create FormsAuthenticationticket on LogIn and it creates successfully but after few moments that cookie is showing in browser but in application it's getting null.
Please help to solve this issue.
Any help will be appreciated Thanks
LOGIN FORM
public ActionResult Login([Bind(Include = "Username, Password")] LoginModel loginModel, string ReturnUrl)
{
if (ModelState.IsValid)
{
Egov_Users eGov_Users = db.Egov_Users
.Where(p => p.UserType.Type != "O" && p.UserName == loginModel.Username)
.FirstOrDefault();
if (eGov_Users == null)
{
ModelState.AddModelError("", "Invalid username");
return View();
}
else
{
if (eGov_Users.Password != loginModel.Password)
{
ModelState.AddModelError("", "Invalid Password");
return View();
}
var loginDetail = new LoginDetails();
var serializer = new JavaScriptSerializer();
loginDetail.userID = eGov_Users.UserId;
loginDetail.username = eGov_Users.UserName;
loginDetail.firstName = eGov_Users.FirstName;
loginDetail.lastName = eGov_Users.LastName;
var userData = SerializeUserInfoInternal(loginDetail);
FormsAuthentication.SetAuthCookie(loginDetail.username, false);
var cookie = FormsAuthentication.GetAuthCookie(
FormsAuthentication.FormsCookieName, false);
var ticket = FormsAuthentication.Decrypt(cookie.Value);
var durationInHours = 8;
FormsAuthenticationTicket newTicket = new FormsAuthenticationTicket(
ticket.Version,
loginDetail.username,
DateTime.Now,
DateTime.Now.AddHours(durationInHours),
true,
userData);
// Encrypt the ticket.
string encTicket = FormsAuthentication.Encrypt(newTicket);
cookie.Value = encTicket;
Response.Cookies.Add(cookie);
int cookieSize = System.Text.UTF8Encoding.UTF8.GetByteCount(cookie.Values.ToString());
Session["CookieSize"] = cookieSize;
if (string.IsNullOrEmpty(ReturnUrl))
{
return RedirectToAction("Index", "Users");
}
}
}
return RedirectToAction("Login", "Login");
}
GLOBAL ASAX
protected void Application_PostAuthenticateRequest()
{
var ticket = GetTicketFromCurrentCookie();
if (ticket == null)
{
Global.WriteLog("Application_PostAuthenticateRequest", "ticket becomes null");
return;
}
var user = DeserializeUserInfoInternal(ticket.Name, ticket.UserData);
if (user == null)
{
return;
}
var principal = new AppUserPrincipal(user);
HttpContext.Current.User = principal;
}
private static FormsAuthenticationTicket GetTicketFromCurrentCookie()
{
var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie == null)
{
Global.WriteLog("GetTicketFromCurrentCookie", "Cookie becomes null");
return null;
}
var ticket = FormsAuthentication.Decrypt(cookie.Value);
return ticket;
}
static LoginDetails DeserializeUserInfoInternal(string name, string userData)
{
var deserialize = new JavaScriptSerializer();
var loginDetails = deserialize.Deserialize<LoginDetails>(userData);
return loginDetails;
}
use below code to get the cookie value
HttpContext.Current.Request.Cookies.Get(".ASPXAUTH");

User Claims seem to be getting replaced somewhere along the pipeline

**Edit: If anyone has any clue how i can better ask or inform you guys about this problem please let me know.
So I am creating custom claims and trying to add them to my user. I see the claims in the User.Identity right after I add them and slightly down the line in the pipeline but by the time it gets to my Global.asax the User.Identity has lost all but one of my claims. I also think the user is changing from a claimsPrinciapl to a GenericPrincipal during the same time. I dont know if I am understanding this or explaining this very well. Not even sure what all code to post but I will post some below.
This is where my user is Authenticated and cookies and claims are create. Note i have been trying a lot of stuff so this might have some weird code:
private AuthenticationResponse AuthenticateUserByService(string userName, string password, bool rememberMe)
{
Authenticator auth = new Authenticator(AppInfo.AuthServiceAddress, AppInfo.ClientId, AppInfo.Secret);
AppInfo.rememberMe = rememberMe;
AuthenticationResponse response = auth.Authenticate(userName, password);
if (response.IsError)
{
// MessageBox.Show(response.ErrorDescription);
return null;
}
if (response.AppUser == null)
{
//MessageBox.Show("No error or user! Unknown reason.");
return null;
}
var cookieHelper = new Helpers.CookieHelper();
//FormsAuthenticationTicket authtick = new FormsAuthenticationTicket(1, response.AppUser.Username, DateTime.Now, DateTime.Now.AddSeconds(response.AppUser.ExpiresIn *2), true, response.AppUser.RefreshToken);
var authtick = cookieHelper.CreateAuthTicket(response.AppUser, true);
var authCookie = cookieHelper.CreateAuthCookie(authtick);
Response.Cookies.Add(authCookie);
var tokenCookie = cookieHelper.CreateTokenCookie(response.AppUser, true);
Response.Cookies.Add(tokenCookie);
// If caching roles in userData field then extract
string[] roles = response.AppUser.Permissions.Select(x => x.PermissionName).ToArray(); // = authTicket.UserData.Split(new char[] { '|' });
// Create the IIdentity instance
IIdentity id = new FormsIdentity(authtick);
var newIdent = new ClaimsIdentity(id);
foreach (var item in roles)
{
newIdent.AddClaim(new Claim(ClaimTypes.Role, item));
}
ClaimsPrincipal cp = new ClaimsPrincipal(newIdent);
// Create the IPrinciple instance
IPrincipal principal = cp; //new GenericPrincipal(id, roles);
Thread.CurrentPrincipal = cp;
AppDomain.CurrentDomain.SetThreadPrincipal(cp);
// Set the context user
HttpContext.User = principal;
//IOwinContext context = Request.GetOwinContext();
//var authManager = context.Authentication;
//authManager.SignIn(newIdent);
this.AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = true }, newIdent);
return response;
In the above code, I can see my user and his claims right after I set the HttpContext.User.
Below is just me checking out the User to make sure it was successful:
private AppUser AuthenticateUser(string userName, string password, bool rememberMe)
{
//bool userAuthenticated = false;
AuthenticationResponse userAuthenticated = null;
bool success = false;
try
{
userAuthenticated = AuthenticateUserByService(userName, password, rememberMe);
var c = User.Identity;
success = !userAuthenticated.IsError;
}
catch { }
}
At one point the claims disappeared by the time I set c to the user.
And i figured this might be important so below is where i create my cookies and tickets:
internal class CookieHelper
{
internal FormsAuthenticationTicket CreateAuthTicket(AppUser appUser, bool isPersistent)
{
return new FormsAuthenticationTicket(
1,
appUser.Username,
DateTime.Now,
DateTime.Now.AddSeconds((appUser.ExpiresIn * 2)),
isPersistent,
appUser.RefreshToken == null ? "" : appUser.RefreshToken,
FormsAuthentication.FormsCookiePath);
}
internal HttpCookie CreateAuthCookie(FormsAuthenticationTicket authTicket)
{
// Encrypt the ticket.
string encAuthTicket = FormsAuthentication.Encrypt(authTicket);
// Create the cookie.
HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encAuthTicket);
authCookie.Expires = authTicket.Expiration;
return authCookie;
}
internal HttpCookie CreateTokenCookie(AppUser appUser, bool isPersistent)
{
// Create token ticket
FormsAuthenticationTicket tokenTicket = new FormsAuthenticationTicket(
1,
appUser.Username,
DateTime.Now,
DateTime.Now.AddSeconds(appUser.ExpiresIn),
isPersistent,
appUser.AccessToken);
// Encrypt the ticket.
string encTokenTicket = FormsAuthentication.Encrypt(tokenTicket);
// Create the cookie.
HttpCookie tokenCookie = new HttpCookie("Mellon", encTokenTicket);
tokenCookie.Secure = false;
tokenCookie.Name = "Mellon";
//tokenCookie.Path = Request.ApplicationPath;
tokenCookie.Expires = tokenTicket.Expiration;
return tokenCookie;
}
}
I feel like questions will need to be asked of me to get the right info for help. I am just lost and at this point my tunnel vision is killing me. Any insight or hints or jsut some love at this point would help. Thanks in advance.
Update
This is where I check if cookie is still valid and perform a refresh if its still valid.
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
HttpCookie tokenCookie = Request.Cookies["Mellon"];
if (authCookie == null)
{
FormsAuthentication.SignOut();
HttpContext.Current.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
return;
}
// Extract the forms authentication cookie
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
if (authTicket == null || authTicket.Expired)
{
FormsAuthentication.SignOut();
HttpContext.Current.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
return;
}
// Extract the forms authentication cookie
//FormsAuthenticationTicket newAuthTicket;
if (tokenCookie == null)
{
RefreshCookies(authTicket);
return;
}
else
{
FormsAuthenticationTicket tokenTicket = FormsAuthentication.Decrypt(tokenCookie.Value);
// If the access token is stil good, then continue on.
if (tokenTicket.Expired)
{
RefreshCookies(authTicket);
return;
}
}
var tick = (FormsIdentity)HttpContext.Current.User.Identity;
if (tick == null)
{
FormsAuthentication.SignOut();
HttpContext.Current.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
return;
}
if (authTicket.UserData != tick.Ticket.UserData) // .Ticket.UserData)
{
RefreshCookies(authTicket);
}
}
Basically what I have is my AuthToken which holds me refresh token and a second cookie that holds me AccessToken. Those are created in the AuthenticateUserByService method which gets all that info from our webapi and is returned in response.AppUser. So I can't use forms.setauthcookie because that would overwrite what is already in there.
Image proof of whats going on:
As I said in my comment, it's rather tough to digest the snippets you have posted, So I'll break down into smaller logical chunks.
Let's start of with an Authentication Service Class:
Authentication Service calls the client repository and returns a User
public class AuthenticationService
{
IUserRepository _userRepo;
public AuthenticationService()
{
_userRepo = new UserRepository();
}
public User GetUser(string username, string password)
{
return _userRepo.FindByCredentials(username, password);
}
public User GetUserByUserName(string username)
{
return _userRepo.FindByUserName(username);
}
}
In the Global.asax we need to authenticate with pre-flight request.
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
//Check the request for a cookie
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
//Decrypt the Auth Cookie vale
var ticket = FormsAuthentication.Decrypt(authCookie.Value);
//Instantiate Auth Service
var _authService = new AuthenticationService();
//Get user by encrypted name stored in ticket
var user = _authService.GetUserByUserName(ticket.Name);
if (user != null)
{
// Create a ClaimsIdentity with all the claims for this user.
Claim emailClaim = new Claim("Email", (!string.IsNullOrWhiteSpace(user.Email)) ? user.Email: "");
Claim AddressClaim = new Claim("Address", (!string.IsNullOrWhiteSpace(user.Address)) ? user.Address: "");
Claim userNameClaim = new Claim(ClaimTypes.Name, (!string.IsNullOrWhiteSpace(user.Username)) ? user.Username : "");
//Add claims to a collection of claims
List<Claim> claims = new List<Claim>
{
emailClaim ,
AddressClaim ,
userNameClaim
};
//Create forms Identity
FormsIdentity formsIdentity = new FormsIdentity(ticket);
//Create Claims Identity
ClaimsIdentity claimsIdentity = new ClaimsIdentity(formsIdentity);
//Add Claims
claimsIdentity.AddClaims(claims);
//Create Claims Principal
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
//Assign principal to current user
HttpContext.Current.User = claimsPrincipal;
}
}
}
Login Controller:
[HttpPost]
[AllowAnonymous]
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
var user = _authService.GetUser(model.UserName, model.password);
if (user != null)
{
FormsAuthentication.SetAuthCookie(model.UserName,model.RememberMe);
return Redirect(model.ReturnUrl); }
}
}
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
As I've said this is a naïve attempt, please consider a little more security, but this is working sln I've quickly put together and I can access the claims.
Having looked at your code, it feels that your just missing adding the Claims of the user.
Basically what is happening is the claims are getting overwritten in my global.asax. My fix so far has been to just rebuild my claims in my global.asax.

FormsAuthenticationTicket Not passing role to global.asax using Asp.Net MVC 5

I am creating role manullay using FormsAuthenticationTicket. I have 2 roles (admin and user). I try to set role using FormAuthenticationTicket but failed. No role pass in global.asax file...
Here is my code: (Login Controller Class)
string[] names = new string[2] { "admin", "user"};
var ticket = new FormsAuthenticationTicket(
version: 1,
name: loginmodel.Email,
issueDate: DateTime.Now,
expiration: DateTime.Now.AddMinutes(30),
isPersistent: false,
userData: String.Join("|", names));
var encryptedTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
HttpContext.Response.Cookies.Add(cookie);
when i check ticket data: It contains UserData = "admin|user" but empty in global file.
Global.asax Code:
public override void Init()
{
base.AuthenticateRequest += OnAuthenticateRequest;
}
private void OnAuthenticateRequest(object sender, EventArgs eventArgs)
{
if (HttpContext.Current.User != null)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
var decodedTicket = FormsAuthentication.Decrypt(cookie.Value);
var roles = decodedTicket.UserData.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
var principal = new GenericPrincipal(HttpContext.Current.User.Identity, roles);
HttpContext.Current.User = principal;
}
}
}
In var decodeTicket = UserData is always null :(

The page isn't redirecting properly when use Roles in Aothorizee

I have this Action Method , And I use Authorize with Roles like as :
[HttpGet]
[Authorize(Roles = "member")]
public virtual ActionResult Profile()
{
...
}
And I have this Method For Login and add cooki:
SetAuthCookie(loginVM.UserName, RoleOfTheMember.Name, loginVM.RememberMe);
RoleOfTheMember.Name has value :"Member"
And this SetAutoCooki :
private void SetAuthCookie(string memberName, string roleofMember, bool presistantCookie)
{
var timeout = presistantCookie ? FormsAuthentication.Timeout.TotalMinutes : 30;
var now = DateTime.UtcNow.ToLocalTime();
var expirationTimeSapne = TimeSpan.FromMinutes(timeout);
var authTicket = new FormsAuthenticationTicket(
1,memberName,now,now.Add(expirationTimeSapne),presistantCookie,roleofMember,FormsAuthentication.FormsCookiePath
);
var encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
{
HttpOnly = true,
Secure = FormsAuthentication.RequireSSL,
Path = FormsAuthentication.FormsCookiePath
};
if (FormsAuthentication.CookieDomain != null)
{
authCookie.Domain = FormsAuthentication.CookieDomain;
}
if (presistantCookie)
authCookie.Expires = DateTime.Now.AddMinutes(timeout);
Response.Cookies.Add(authCookie);
}
But when Call This Action I getting This ERROR By Browser :
The page isn't redirecting properly
Whats A problems ?
I don't use any RoleProvider . Do I use Implement Role Provider?

Categories

Resources