Getting The Current User Name In ASP.NET Application - c#

I am running a webpage that needs to be able to read the login id of the current user. Here is the code I am using:
string id = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
Currently this returns the correct login but when I use it in this method:
protected Boolean isPageOwner()
{
string id = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
alert("User: " + id);
if (id.Equals(pageOwnerID))
{
return true;
}
if (accessPermission.ContainsKey(id))
{
return true;
}
return false;
}
the method returns false even though the id returned is identical to pageOwnerID. I'm really not sure which part of this I am having a problem with.
On a side note, my login id is of the form string1/string2 but the code retrieves it as string1 + string2 without the slash.
Any advice is appreciated.
Regards.

Try using this to retrieve the username....
if (System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
{
string username = System.Web.HttpContext.Current.User.Identity.Name;
}
It sounds like windows authentication is not being used - you need to disable anonymous access and enable windows integrated security.
Add this to your web.config...
<system.web>
<authentication mode="Windows"/>
<authorization>
<deny users="?"/>
</authorization>
</system.web>

If you need the current logged in user's identity from within any layer (or Project in your solution) then use:
string userId = Thread.CurrentPrincipal.Identity.GetUserId();

Related

How to debug this "value cannot be null. Parameter name: password" error?

Basically, I am trying to create an admin role (canEdit) that can add/remove products in the application. Analyzing the "IdentityResult Create" extension method I found out it has +1 override.
One has the parameters: manager, TUser user
The other has parameters: manager, TUser user, string password
This is an error I kept getting towards the end of the Wingtip Toys Microsoft asp.net tutorial. In my code which is identical to the tutorial except for the name of the Application (mine is gamestore as you see), I think I must use the 2nd method as the admin role has a password.
But I have tried different things and to understand and fix this by analyzing the metadata extensions for all those light blue classes and interfaces, etc you see, but I wasn't able to fix this at all.
Edit
I am adding code. The bolded line below is the erroring line.
namespace GameStore.Logic
{
internal class RoleActions
{
internal void AddUserAndRole()
{
// Access the application context and create result
variables.
Models.ApplicationDbContext context = new
ApplicationDbContext();
IdentityResult IdRoleResult;
IdentityResult IdUserResult;
var roleStore = new RoleStore<IdentityRole>(context);
var roleMgr = new RoleManager<IdentityRole>(roleStore);
if (!roleMgr.RoleExists("canEdit"))
{
IdRoleResult = roleMgr.Create(new IdentityRole { Name =
"canEdit" });
}
var userMgr = new UserManager<ApplicationUser>(new
UserStore<ApplicationUser>(context));
var appUser = new ApplicationUser
{
UserName = "canEditUser#gamestore.com",
Email = "canEditUser#gamestore.com",
};
**IdUserResult = userMgr.Create(appUser,
ConfigurationManager.AppSettings["AppUserPasswordKey"]);**
if(!userMgr.IsInRole(userMgr.FindByEmail("
canEditUser#gamestore.com").Id, "canEdit"))
{
IdUserResult = userMgr.AddToRole(userMgr.FindByEmail("
canEditUser#gamestore.com").Id, "canEdit");
}
}
}
}
Below is the config file for this Admin folder, but there is no password involved as you see..
<?xml version="1.0"?>
<configuration>
<system.web>
<authorization>
<allow roles="canEdit"/>
<deny users="*"/>
</authorization>
</system.web>
</configuration>
Where do you expect
ConfigurationManager.AppSettings["AppUserPasswordKey"]
to get the password from? You did not put a value in the configuration file for it to read.
I have to say that it would be very strange to put the passowrd for a new user in the ap config file.
I mean you say 'see there is no password here', well exactly, so why is your code trying to read a password from there?

SignalR unable to receive broadcast when in Microsoft Edge

We have problem getting message from Hub when we're in Microsoft Edge.
The connection is established, sending message from Client -> Server works as expected, but we're not receiving any response from server push. The same code works in Chrome & Firefox though.
Below is some code that we're using:
JS:
$.connection.hub.start()
.done(function () {
$.connection.myHub.server.broadcastMessage().done(function (data) {
console.log("broadcastMessage result: " + data); //work as expected when client request data from server, server does return the data
});
})
.fail(function () {
console.log("Connection failed!");
});
$.connection.myHub.client.showMessage = function (msg) {
alert(msg); //not working, in Microsoft Edge we're not receiving anything, this function is not triggered at all
};
C#:
public string BroadcastMessage() {
Clients.All.showMessage("ABC");
return "Hello World";
}
We're not completely unable to receive any broadcast 100% of the time though, however it does happens 95% of the time.
Although we're not able to receive any broadcast from server, but subsequent request from Client -> Server works as expected.
public override Task OnConnected() are not hit when we're in Edge too, but the code block does hit when we're in Chrome / Firefox.
Any idea? Is this a problem with SignalR or Edge?
P/S: We're using JQUERY 3.3.1 & SignalR 2.3.0
UPDATE 1:
We tried to remove everything and made a empty project to see if it's a problem with SignalR. Apparently if it's a completely new project, SignalR doesn't have this problem, but after I implemented Form Authentication, the problem starts to happen, I'm guessing is it because sometime when server trying to broadcast message to client, it's not authenticated or the cookies are not set?
Below is the code we used to implement our Forms Authentication:
Global.asax
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (HttpContext.Current.User != null)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
if (HttpContext.Current.User.Identity is FormsIdentity identity)
{
FormsIdentity id = identity;
FormsAuthenticationTicket ticket = id.Ticket;
string userData = ticket.UserData;
string[] roles = userData.Split(',');
HttpContext.Current.User = new GenericPrincipal(id, roles);
}
}
}
}
Web.Config
<authentication mode="Forms">
<forms name="LoginCookie" loginUrl="/Account/Login" protection="None" path="/" defaultUrl="/Account/Login" timeout="3600" />
</authentication>
Code in Web.Config to block folder access
<location path="CMS/Admin" allowOverride="true">
<system.web>
<authorization>
<allow roles="Admin" />
<deny users="*" />
</authorization>
</system.web>
</location>
The sample page were placed inside /CMS/Admin.
Try to change your c# code in:
public string BroadcastMessage() {
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<myHub>();
context.Clients.All.showMessage("ABC");
return "Hello World";
}
Without IHubContext context = GlobalHost.ConnectionManager.GetHubContext<myHub>(); i don't able to work with signalR

Access Login Control from Different Page

I have a website in C# where users are authenticated to a SQL database via login control. Everything is working fine currently as I'm using the web.config to to direct to the Login.aspx page if the user isn't logged in. What I would like to do though is access the login controls from another page but additionally pass another parameter.
So for example...
The web.config has the following:
<authentication mode="Forms">
<forms defaultUrl="~/Default.aspx" loginUrl="~/Login.aspx" slidingExpiration="true" timeout="20"></forms>
</authentication>
<authorization>
<deny users="?"/>
</authorization>
The Login.aspx page looks like the following
protected void LoginControl_Authenticate(object sender, AuthenticateEventArgs e)
{
bool authenticated = this.ValidateCredentials(LoginControl.UserName, LoginControl.Password);
if (authenticated)
{
FormsAuthentication.RedirectFromLoginPage(LoginControl.UserName, LoginControl.RememberMeSet);
}
}
private bool IsAlphaNumeric(string text)
{
return Regex.IsMatch(text, "^[a-zA-Z0-9-]+$");
}
private bool ValidateCredentials(string userName, string password)
{
bool returnValue = false;
if (this.IsAlphaNumeric(userName) && userName.Length <= 25 && password.Length <= 50)
{
string sqlConn = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
using (SqlConnection sqlConnection1 = new SqlConnection(sqlConn))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = ("ValidateUser");
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("LoginName", userName.Trim());
cmd.Parameters.AddWithValue("LoginPass", HashData.HashString(password.Trim()));
cmd.Parameters.AddWithValue("Type", "Read");
cmd.Connection = sqlConnection1;
sqlConnection1.Open();
if (cmd.ExecuteScalar() == null)
{
returnValue = false;
}
else
{
returnValue = true;
}
}
}
}
return returnValue;
}
}
Now what I would like to do is utilize the same login control across other pages so that I can see if the same user is logged in but pass a different "Type" parameter such as "Edit".
So the way I would like it to work is this... The users accesses the site and is redirected to the Login.aspx page. The login control runs my stored procedure verifying they are "Read" type and redirects them to the Default.aspx. From here a user can click an Edit button. Once they do, the same login control would check if they have "Edit" rights by running the same stored procedure but instead passing that as the "Type" parameter. At this point if the results are false the user would be prompted to login if their current rights don't allow it, or the page would just load if the current user has those rights. Is there a way to do what I"m looking for or would I need to just user either multiple login controls or different folder structure and do this all with web.config?
What you can do is create a Master page and put the Login Control in the Master page. Have each page that you want to be able to authenticate inherit from the Master page, which would give it access to the Login Control.
Problem solved...
What I ended up doing was to let the login control authorize a user with the lowest level rights. When a user attempts to access a page that requires higher rights, I'm first checking if
if (User.Identity.IsAuthenticated == true)
If true, then I run a new query that checks if User.Identity.Name is of the correct "Type".

trying to get the username used to sign into the website

I'm using the following code to check the user's credentials and if successful I put them to make-request.aspx, but on make-request.aspx I want to check the value of the username they entered so I can show certain content.
Here's the authentication code:
foreach (string key in ConfigurationSettings.AppSettings.Keys)
{
dominName = key.Contains("DirectoryDomain") ? ConfigurationSettings.AppSettings[key] : dominName;
adPath = key.Contains("DirectoryPath") ? ConfigurationSettings.AppSettings[key] : adPath;
if (!String.IsNullOrEmpty(dominName) && !String.IsNullOrEmpty(adPath))
{
if (true == AuthenticateUser(dominName, userName, txtPassword.Text,adPath, out strError))
{
Response.Redirect("../make-request.aspx");// Authenticated user redirects to default.aspx
}
dominName = string.Empty;
adPath = string.Empty;
if (String.IsNullOrEmpty(strError)) break;
}
Everything works fine but I'm not sure how to get the username they entered into the form. Here's code that I've tried that is getting username of the machine username -- I think. Any help would be appreciated!
I've tried all three of these:
//string userName = Environment.UserName;
string userName = HttpContext.Current.User.Identity.Name;
//string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
Here's the authentication/auth section of web.config:
<authentication mode="Windows" />
<authorization>
<allow users="*" />
<!--<deny users="*"/>-->
</authorization>
You are authenticating the user but not setting forms authentication cookie. Here's what you need to do:
FormsAuthentication.SetAuthCookie(userName, false);
Response.Redirect("../make-request.aspx");
Also make sure you have proper authentication/authorization set in your web.config. If you are not sure if it is setup correctly, share it here so we can take a look.
Set FormsAuthentication as below:
<authentication mode="Forms">
<forms loginUrl="Login.aspx"/>
</authentication>
<authorization>
<deny users="?"/>
</authorization>
The HttpContext.Current.User.Identity.Name will work as long as the user is currently logged in when it is ran. In one of my sites, I use the following (written in VB):
Dim u As MembershipUser = Membership.GetUser(Membership.GetUserNameByEmail(HttpContext.Current.User.Identity.Name))
Tip: You can test if the user is already logged in by checking the value of HttpContext.Current.User.Identity.IsAuthenticated.
However . . .
. . . Using the current HTTP context is only necessary in content pages or web APIs. Alternatively, you can use MembershipUser u = Membership.GetUser(); from the master page, and then use u.Username to retrieve the username or u.ProviderUserKey to retrieve the GUID of the user.
If Session Is Nothing OrElse Session(Current_User) Is Nothing Then
udtGeneral = GetdoGeneralInstance()
susername = Request.ServerVariables("LOGON_USER").Split("\")(1).ToString()
'Either of these work i believe
susername = Request.ServerVariables(7).Split("\")(1).ToString()
'Dim susername1 = Request.Browser.Capabilities("extra").ToString.Split(";")(14).ToString.Split(":")(1).ToString
Session("ipAddress") = Request.ServerVariables("REMOTE_ADDR").ToString()
End If

Asp.Net Authentication Module

I have created an authentication module in ASP.Net but I do not want the logic in the authentication module to be executed if the resource is configured for anonymous access since the logic is expensive.
There are pages that require authentication in the same directory with pages that do not require authentication. I have no control over this. Is there an easy way to determine that a resource is configured to allow anonymous access prior to the URLAuthorizationModule?
Currently, I am doing the following which does "feel" right. Any help would be appreciated.
public static bool AllowEveryone()
{
bool rslt = false;
AuthorizationSection config = (AuthorizationSection)WebConfigurationManager.GetSection("system.web/authorization");
if (config.Rules != null && config.Rules.Count > 0)
{
AuthorizationRule r = config.Rules[0]; //doing this based on implementation of urlauthorization module in reflector...
if (r.Action == AuthorizationRuleAction.Allow && r.Users.Contains("*"))
{
return true;
}
//todo: check for allow anon ? case
}
return rslt;
}
I'm not sure how your code fits in with the Membership and Role provider system, but have you tried putting per-URL overrides in the web.config file?
<location path="MyAnonymousPage.aspx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
In a regular ASP.Net site this can be accomplished with the following code:
IPrincipal anonUser = new GenericPrincipal(new GenericIdentity(string.Empty, string.Empty), new string[0]);
bool allowAnon = UrlAuthorizationModule.CheckUrlAccessForPrincipal(requestPath, anonUser, "get");
However, I am having problems getting it to behave as expected in SharePoint.

Categories