asp.net identity webservice android - c#

I've a simple ASP.net webform application with identity+owin for authentication. This works perfectly fine.
Now I need to create a webservice(.asmx) to get my users authenticated through service. So the service can accept the UserName+Password and authenticate them.
This is required to authenticate the users for android app.
I don't want to use any other authentication like google or facebook..etc...
And no MVC either.
Can anyone pls point me towards solution.
bellow is my login.aspx page's code behind. What should I put in my webservice.?
Android app developer is another guy. I just need to make sure my webservice works fine.
protected void SignIn(object sender, EventArgs e)
{
var userStore = new UserStore<IdentityUser>();
var userManager = new UserManager<IdentityUser>(userStore);
var user = userManager.Find(UserName.Text, Password.Text);
if (user != null)
{
var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
var userIdentity = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);
authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = false }, userIdentity);
string cs = ConfigurationManager.ConnectionStrings["DB_6"].ConnectionString;
using (SqlConnection conn = new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand("spGetUser", conn);
SqlDataAdapter Adpt = new SqlDataAdapter();
DataSet login = new DataSet();
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#PEmail", UserName.Text);
Adpt.SelectCommand = cmd;
Adpt.Fill(login);
foreach (DataRow dr in login.Tables[0].Rows)
{
string PFName = login.Tables[0].Rows[0]["PFName"].ToString();
string PLName = login.Tables[0].Rows[0]["PLName"].ToString();
string PType = login.Tables[0].Rows[0]["PType"].ToString();
int PersonID = int.Parse(login.Tables[0].Rows[0]["PersonID"].ToString());
using (SqlConnection con = new SqlConnection(cs))
{
SqlCommand cmd1 = new SqlCommand("spInsLoc", con);
cmd1.CommandType = CommandType.StoredProcedure;
cmd1.Parameters.Add("#PersonID", SqlDbType.Int).Value = PersonID;
cmd1.Parameters.Add("#OrgID", SqlDbType.Int).Value = 0;
cmd1.Parameters.Add("#Location", SqlDbType.NVarChar).Value = hdnLocation.Value;
cmd1.Parameters.Add("#strOwner", SqlDbType.VarChar).Value = UserName.Text;
cmd1.Parameters.Add("#dbTstamp", SqlDbType.DateTime2).Value = DateTime.Now;
con.Open();
cmd1.ExecuteNonQuery();
}
}
}
catch { }
finally { }
}
Response.Redirect("~/Login.aspx");
}
else
{
StatusText.Text = "Invalid username or password.";
LoginStatus.Visible = true;
}
}
protected void SignOut(object sender, EventArgs e)
{
var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
authenticationManager.SignOut();
Response.Redirect("~/Login.aspx");
}

You need use Post&Get method in web service.
Create new android app and use volley or native java library for Http Req.
this is sample code for a request;
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL("http://yoursite.com?name=foo?pass=foo");
urlConnection = (HttpURLConnection) url
.openConnection();
InputStream in = urlConnection.getInputStream();
InputStreamReader isw = new InputStreamReader(in);
int data = isw.read();
while (data != -1) {
char current = (char) data;
data = isw.read();
System.out.print(current);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
and your web service will response the request.
ex: yoursite.com?name=foo?pass=foo RESPONSE->TRUE or FALSE

Related

Why do I have to click twice to execute method in Label MouseDown event

I'm working on an assignment for College and the requirements are that I have to use multi-threading, now everytime I login, I have to click twice to change the UI for the MainWindow. Any idea what I might be doing wrong?
If I use the code from the user_login method it works fine, UI updates quickly, but when I use multi-threading I have to click the label twice in order to change my UI.
I've done the same using a button control but also has the same result for both tests given above.
private void tbLogin_MouseDown(object sender, MouseButtonEventArgs e)
{
//Assign Class Property Values
login.Student_Email = txtstd_Email.Text;
login.Student_Password = txtstd_Password.Password;
Thread user_login_thread = new Thread(() => User_Login(login.Student_Email,
login.Student_Password));
user_login_thread.Start();
if (login.UserLoggedIn)
{
foreach (Window window in Application.Current.Windows)
{
if (window.GetType() == typeof(MainWindow))
{
//Change page on login
(window as MainWindow).frmView.Source = new Uri("Views/Dashboard.xaml", UriKind.Relative);
}
}
}
user_login_thread.Join();
if (chkRemember.IsChecked == true)
{
Properties.Settings.Default.Student_Email = login.Student_Email;
Properties.Settings.Default.Student_Password = login.Student_Password;
Properties.Settings.Default.Save();
}
}
private void User_Login(string email, string password)
{
//Security object
Secure security = new Secure();
conn.Open();
string sql = "SELECT Student_Number, Student_FullName, Student_Email, Student_Password FROM
Student_Data WHERE Student_Email=#Email";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add("#Email", System.Data.SqlDbType.VarChar, 55).Value = email;
cmd.Parameters.Add("#Pass", System.Data.SqlDbType.VarChar, 55).Value = password;
SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read() &&
login.Student_Password.Equals(security.Decrypt(reader["Student_Password"].ToString())))
{
login.UserLoggedIn = true;
}
else
{
_ = MessageBox.Show("Login Unsuccessful", "Student Login Unsuccessfull",
MessageBoxButton.OKCancel, MessageBoxImage.Error);
}
}
conn.Close();
}
The primary issue is that you are not waiting for the query to finsih before checking if (login.UserLoggedIn).
I'd advise you to use async and await for this instead of threading.
You have some other issues also:
connection and reader objects need using blocks.
Do not cache the connection, create a new one when you need it.
Reversible encryption on a password is a bad idea, use hashing instead. Pass the hash to the server for it to verify, don't bring it back to the client app.
Don't block the thread with message boxes while the connection is open.
Don't read more columns than you need.
If you only have one column and row use ExecuteScalar
private async void tbLogin_MouseDown(object sender, MouseButtonEventArgs e)
{
//Assign Class Property Values
login.Student_Email = txtstd_Email.Text;
login.Student_Password = txtstd_Password.Password;
await User_Login(login.Student_Email, login.Student_Password));
.....
private async Task User_Login(string email, string password)
{
//Security object
Secure security = new Secure();
const string sql = #"
SELECT 1
FROM Student_Data
WHERE Student_Email = #Email
AND Student_Password = #Pass;
";
using (var conn = new SqlConnection(yourConnString))
using (var cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add("#Email", SqlDbType.VarChar, 55).Value = email;
cmd.Parameters.Add("#Pass", SqlDbType.VarChar, 55).Value = security.Encrypt(password);
await conn.OpenAsync();
login.UserLoggedIn = await comm.ExecuteScalarAsync() != null;
}
if (!login.UserLoggedIn)
{
_ = MessageBox.Show("Login Unsuccessful", "Student Login Unsuccessfull",
MessageBoxButton.OKCancel, MessageBoxImage.Error);
}
}

Discord.net task call issue

I'm trying to create a discord bot in .NET with a command to put a user on markers. For example, a server admin gives a user 50 markers and the user would get all of his roles removed and would be given a role called "Markers". Then, a text channel will appear where the user needs to spam 50 messages to remove the markers and he'd get everything back. I have made commands for giving markers and removing them but when I try to remove someone's markers by calling the function from the Program.cs it gives a null pointer exception for some reason. Here's the code:
Program.cs event:
private async Task MessageRecieved(SocketMessage arg)
{
//Checking if the user has markers
var roles = (arg.Author as SocketGuildUser).Roles;
bool imaMarkere = false;
foreach (var role in roles)
{
if (role.Id == 844558286611152917)
imaMarkere = true;
}
if (arg.Channel.Id == 844558185024585770 && imaMarkere)
{
int markerCount = 0;
using (SqliteConnection con = new SqliteConnection(connectionString))
{
con.Open();
string query = $"select markercount from markers";
var com = con.CreateCommand();
com.CommandText = query;
var rdr = com.ExecuteReader();
if (rdr.Read())
{
markerCount += Convert.ToInt32(rdr["markercount"]) - 1;
}
rdr.Close();
//Removing 1 marker per message recieved
if (markerCount > 0)
{
com.CommandText = $"update markers set markercount={markerCount} where userid='{arg.Author.Id}'";
com.ExecuteNonQuery();
}
//If no markers are left returning the user roles
else
{
Commands c = new Commands();
await c.Skini(arg.Author as IGuildUser);
}
con.Close();
}
}
else return;
}
Commands.cs
[Command("skini"), RequireUserPermission(GuildPermission.Administrator, ErrorMessage = "Nemate potrebnu dozvolu ``ADMINISTRATOR``")]
public async Task Skini(IGuildUser user = null)
{
if(user == null)
{
await ReplyAsync($"{Context.User.Mention},kome da skinem?");
}
string rolesString = "";
string[] roles;
using (SqliteConnection con = new SqliteConnection(connectionString))
{
con.Open();
var com = con.CreateCommand();
string readQuery = "select pastroles from markers";
com.CommandText = readQuery;
var rdr = com.ExecuteReader();
if (rdr.Read())
{
rolesString += rdr["pastroles"].ToString();
}
rdr.Close();
string deleteQuery = $"delete from markers where userid = '{user.Id}'";
com.CommandText = deleteQuery;
com.ExecuteNonQuery();
con.Close();
}
roles = rolesString.Split(",");
foreach (var roleid in roles)
{
var role = Context.Guild.GetRole(Convert.ToUInt64(roleid));//this line is where the exception happens
if(!role.IsEveryone)
await user.AddRoleAsync(role);
}
var roleMarkeri = Context.Guild.GetRole(844558286611152917);
await user.RemoveRoleAsync(roleMarkeri);
var EmbedBuilder = new EmbedBuilder()
.WithTitle("**MARKERI**")
.WithColor(Color.Blue)
.WithDescription($":white_check_mark: {Context.User.Mention} je **skinuo** markere {user.Username}")
.WithFooter(footer =>
{
footer
.WithText("Marker log");
});
Embed embed = EmbedBuilder.Build();
await ReplyAsync(embed: embed);
}

C# Mysql datareader - how to get other coloumn using datareader

Im trying to validate the password from my database that has been hash and salted. I Created an column in my user table username, hash and salt. Now i want to know i can i access the other column value using datareader.
I tried this method but i got an red line. also this is my failed attempt
public static bool VerifyPassword(string enteredPassword, string storedHash, string storedSalt)
{
var saltBytes = Convert.FromBase64String(storedSalt);
var rfc2898DeriveBytes = new Rfc2898DeriveBytes(enteredPassword, saltBytes, 10000);
return Convert.ToBase64String(rfc2898DeriveBytes.GetBytes(256)) == storedHash;
}
private void bunifuFlatButton1_Click(object sender, EventArgs e)
{
string userhash;
string usersalt;
MySqlConnection mysqlCon = new MySqlConnection(connectionString);
MySqlCommand cmd = new MySqlCommand("SELECT * FROM login.info WHERE username = #user", mysqlCon);
MySqlDataReader rd;
rd = cmd.ExecuteReader();
cmd.Parameters.Add("#user", MySqlDbType.VarChar).Value = username.Text;
mysqlCon.Open();
while (rd.Read())
{
userhash = rd.GetString("hash");
usersalt = rd.GetString("salt");
bool isPasswordMatched = VerifyPassword(textpass.Text, userhash.Hash, usersalt.Salt);
// i got redline error in here. i only follow instruction.. link below
if (isPasswordMatched)
{
//Login Successfull
}
else
{
//Login Failed
}
}
}
by the way, i only follow this instruction from this thread. How to validate salted and hashed password in c#
Here is another way of writing your code, not really an answer, but...not perfect mind, but at least it will dispose of the objects and also call them in the correct order. Please read upon on IDisposable and Sql Injection.
private void bunifuFlatButton1_Click(object sender, EventArgs e)
{
using (MySqlConnection mysqlCon = new MySqlConnection(connectionString))
{
// Use a named list of fields please. And cleanse the text.
using (MySqlCommand cmd = new MySqlCommand("SELECT * FROM login.info WHERE username = #user", mysqlCon))
{
cmd.Parameters.Add("#user", MySqlDbType.VarChar).Value = username.Text; // Let's hope user name is not Jimmy DropTables!!
mysqlCon.Open();
using (MySqlDataReader rd = cmd.ExecuteReader())
{
while (rd.Read())
{
string userhash = rd.GetString("hash");
string usersalt = rd.GetString("salt");
bool isPasswordMatched = VerifyPassword(textpass.Text, userhash, usersalt);
// Note that we are passing in strings, not props of an unknown object
if (isPasswordMatched)
{
//Login Successfull
}
else
{
//Login Failed
}
}
}
mysqlCon.Close();
}
}
}

Application_AuthenticateRequest Executing first before a Forms authentication ticket is created

I am having trouble while using role based security with Forms Authentication, every time I try and login for the first time ticket seems to have no UserData as Application_Authenticate request is executing first, and my if statements is not executing as the roles are none after first post back.
please help!
My Sign In click event:
protected void signin_click(object sender, EventArgs e)
{
if (con.State == ConnectionState.Closed)
{
con.Open();
}
HashData ob = new HashData();//Custom Class used for Hashing Passwords
SqlCommand cmd = new SqlCommand("Logincheck", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#username", SqlDbType.VarChar, 50).Value = txt_username.Text.Trim();
string pass = ob.Encrypt(txt_pass.Text.Trim());
cmd.Parameters.Add("#password", SqlDbType.VarChar, 50).Value = pass;
SqlParameter result = new SqlParameter("#result", SqlDbType.Int) { Direction = ParameterDirection.Output };
SqlParameter userrole = new SqlParameter("#userrole", SqlDbType.VarChar,50) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(result); cmd.Parameters.Add(userrole);
cmd.ExecuteNonQuery();
int rslt = Convert.ToInt32(result.Value);
if (rslt == -1)
{
string message = "Login Failed";
string url = "Login.aspx";
string script = "window.onload = function(){ alert('";
script += message;
script += "');";
script += "window.location = '";
script += url;
script += "'; }";
ClientScript.RegisterStartupScript(this.GetType(), "Redirect", script, true);
}
string u_role = userrole.Value.ToString();
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket
(1, txt_username.Text.Trim(), DateTime.Now,
DateTime.Now.AddMinutes(30), false, u_role,
FormsAuthentication.FormsCookiePath);
string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
if (ticket.IsPersistent)
{
cookie.Expires = ticket.Expiration;
}
Response.Cookies.Add(cookie);
if (User.IsInRole("admin"))
{
Response.Redirect("~/Admin/Admin.aspx");
}
if (User.IsInRole("manager"))
{
Response.Redirect("~/Manager/Manager.aspx");
}
if (User.IsInRole("teamlead"))
{
Response.Redirect("~/Teamlead/Teamlead.aspx");
}
if (User.IsInRole("qa"))
{
Response.Redirect("~/Default.aspx");
}
cmd.Dispose();
con.Close();
}
And my Global.ASAX File
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)
{
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
string userData = ticket.UserData;
string[] roles = userData.Split(',');
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(id, roles);
}
}
}
}
Found the solution myself, User.IsInRole will be effective after the forms authentication ticket is made and our principal object is made,i.e. after postback.
So to solve this i used static roles from database only to redirect.
protected void signin_click(object sender, EventArgs e)
{
if (con.State == ConnectionState.Closed)
{
con.Open();
}
HashData ob = new HashData();//Custom Class used for Hashing Passwords
SqlCommand cmd = new SqlCommand("Logincheck", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#username", SqlDbType.VarChar, 50).Value = txt_username.Text.Trim();
string pass = ob.Encrypt(txt_pass.Text.Trim());
cmd.Parameters.Add("#password", SqlDbType.VarChar, 50).Value = pass;
SqlParameter result = new SqlParameter("#result", SqlDbType.Int) { Direction = ParameterDirection.Output };
SqlParameter userrole = new SqlParameter("#userrole", SqlDbType.VarChar,50) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(result); cmd.Parameters.Add(userrole);
cmd.ExecuteNonQuery();
int rslt = Convert.ToInt32(result.Value);
if (rslt == -1)
{
string message = "Login Failed";
string url = "Login.aspx";
string script = "window.onload = function(){ alert('";
script += message;
script += "');";
script += "window.location = '";
script += url;
script += "'; }";
ClientScript.RegisterStartupScript(this.GetType(), "Redirect", script, true);
}
string u_role = userrole.Value.ToString();
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket
(1, txt_username.Text.Trim(), DateTime.Now,
DateTime.Now.AddMinutes(30), false, u_role,
FormsAuthentication.FormsCookiePath);
string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
if (ticket.IsPersistent)
{
cookie.Expires = ticket.Expiration;
}
Response.Cookies.Add(cookie);
// Response.Redirect("Redirecting.aspx");
if (u_role == "admin")
{
Response.Redirect("~/Admin/Admin.aspx");
}
if (u_role == "admin" || u_role == "manager")
{
Response.Redirect("~/Manager/Manager.aspx");
}
if (u_role == "teamlead" || u_role == "admin" || u_role == "manager")
{
Response.Redirect("~/Teamlead/Teamlead.aspx");
}
if (u_role == "qa")
{
Response.Redirect("Default.aspx");
}
cmd.Dispose();
con.Close();
}
So it is working fine now,
Thanks.

SignalR Content dont update if send to Client.Caller

Hello and thanks for reading this.
This is my NotificationHub.cs
public class NotificationHub : Hub
{
private static readonly ConcurrentDictionary<string, User> Users = new ConcurrentDictionary<string, User>(StringComparer.InvariantCultureIgnoreCase);
private static List<User> UserList = new List<User>();
Int16 totalNewMessages = 0;
string UserID;
[HubMethodName("check")]
public Task Check(string id)
{
string profileId = id; //Context.QueryString["id"];
string connectionId = Context.ConnectionId;
var user = Users.GetOrAdd(profileId, _ => new User
{
ProfileId = profileId,
ConnectionIds = id
});
lock (user.ConnectionIds)
{
Groups.Add(connectionId, user.ProfileId);
}
return base.OnConnected();
}
[HubMethodName("sendNotifications")]
public Task SendNotifications(string id)
{
UserID = id;
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
{
string query = "SELECT NotificationNumber FROM [dbo].[NotificationStatus] WHERE UserID=" + UserID;
connection.Open();
using (SqlCommand command = new SqlCommand(query, connection))
{
command.Notification = null;
DataTable dt = new DataTable();
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
var reader = command.ExecuteReader();
dt.Load(reader);
if (dt.Rows.Count > 0)
{
totalNewMessages = Int16.Parse(dt.Rows[0]["NotificationNumber"].ToString());
}
}
}
User CurrentUser = UserList.FirstOrDefault(i => i.ProfileId == UserID);
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
//return context.Clients.All.RecieveNotification(totalNewMessages);
return context.Clients.Client(Users.Values.FirstOrDefault(i => i.ProfileId == UserID).ConnectionIds).RecieveNotification(totalNewMessages);
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
NotificationHub nHub = new NotificationHub();
nHub.SendNotifications(UserID);
}
}
}
These 2 lines is what I want to focus on.
//return context.Clients.All.RecieveNotification(totalNewMessages);
return context.Clients.Client(Users.Values.FirstOrDefault(i => i.ProfileId == UserID).ConnectionIds).RecieveNotification(totalNewMessages);
If i use the first line it returns the totalNewMessages back to ALL people on the website, but i only want to to return back to the user that requested it.
The second line is my attempt to return the totalNewMessages back tot he specific user, but it dont work.
How can i return the totalNewMessages Back to only the specific user?
I came across this problem a while back. I got it working by returning the messages depending on the user who's logged in
string userName = HttpContext.Current.User.Identity.Name;
return context.Clients.User(userName).RecieveNotification(totalNewMessages);
Also look into parameterized queries to prevent sql injection. There's a handy documentation for what you're trying to achieve here

Categories

Resources