Passing a variables in C# - windows

I am trying to pass a variable that identifies a staff member from their login details to the next screen to populate the Tester ID box.
Would I be better using a global variable that is then read when the next screen is set up or would I be better to put it into a variable and send it to the next screen?
The login code sits as follows:
public Login()
{
InitializeComponent();
}
private void LoginButton_Click(object sender, EventArgs e)
{
String Username1 = StaffUsername.Text;
String Password1 = StaffPassword.Text;
String HardUser = "Test";
String HardPass = "Merlin123";
if (Username1 == "" && Password1 == "")
{
MessageBox.Show("Please Enter Login Id and Password");
}
else
{
if (Username1.Equals(HardUser) && Password1.Equals(HardPass))
{
this.Hide();
AddingClients M1 = new AddingClients();
M1.Show();
}
else{
this.Hide();
Login Lg = new Login();
Lg.Show();
MessageBox.Show("Incorrect Username or Password Entered");
}
}
}
}
}
I am using a hardcoded username and password for now, but in the actual program, I would have this call on a database and compare the username and the password and then go through to the next screen.
Would lit be better to have a global variable that the login action throws over to the next screen or would it be easier having a variable that the next screen reads and then populates the text box required? How would I go about this?
Thanks

The way you do this is to use the Thread.CurrentPrincipal.
Once the user is confirmed to be who they say they are, you can do:
private static void SignUserIn(string userName)
{
GenericIdentity identity = new GenericIdentity(userName, null);
Thread.CurrentPrincipal = new GenericPrincipal(identity);
}
Then whenever you need the userName, you use Thread.CurrentPrincipal.Identity.Name.
To extend this a little further, its probably best to abstract this a little bit, so you can swap in and out providers e.g. you might want to use Windows Authentication.
So you could do it like this:
public interface IAuthenticator
{
bool IsValidUser ( string username, string password );
IPrincipal SignInUser ( string username );
void SignOutCurrentUser();
}
public class DbAuthenticator : IAuthenticator
{
public bool IsValidUser ( string username, string password )
{
// Check user here and return bool if valid
}
public void SignInUser(string userName, string[] roles = null)
{
GenericIdentity identity = new GenericIdentity(userName, roles);
Thread.CurrentPrincipal = new GenericPrincipal(identity);
return Thread.CurrentPrincipal;
}
public void SignOutUser()
{
Thread.CurrentPrincipal = WindowsPrincipal.GetCurrent();
}
}
Then in your code, inject the authenticator using some sort of DI pattern. So MEF would be like this:
[Export(typeof(IAuthenticator))]
public interface IAuthenticator { }
And in your form:
[Import]
internal IAuthenticator authenticator;
private static void SignUserIn(string userName)
{
authenticator.SignUserIn(username);
}

You should have a User object and pass it to other pages and functions. That way they become more testable.
But you also need to store the object somewhere globally so you can retrieve the currently logged in user when needed. The problem with that is that piece of code then depends on that user storage existing/working, but if it's only one place it's okay.
PS: your title should be: pass the user on or store globally?

Related

Correct Implementation of Forgot Password AspNetBoilerPlate

Im using aspnetboilerplate (MVC) and wanted to implement a forgot password feature to allow the user to reset their own passwords using a link on the login screen.
I imagine this to work by generating a password reset code which is then emailed to the user.The user follows the link and is taken to a screen allowing them to reset the password.
Im stuck at the initial stage. i started with a copy of the login action after noticing that when attempting to log in the user object was returned. From here i attempt to set a password reset code.
[HttpPost]
[UnitOfWork]
public virtual async Task<JsonResult> ForgotPassword(ForgotPasswordViewModel forgotPasswordModel, string returnUrl = "", string returnUrlHash = "")
{
returnUrl = NormalizeReturnUrl(returnUrl);
if (!string.IsNullOrWhiteSpace(returnUrlHash))
{
returnUrl = returnUrl + returnUrlHash;
}
var loginResult = await _logInManager.LoginAsync(forgotPasswordModel.UsernameOrEmailAddress, "ForgotPassword", GetTenancyNameOrNull());
loginResult.User.SetNewPasswordResetCode();
switch (loginResult.Result)
{
case AbpLoginResultType.Success:
return Json(loginResult);
default:
throw _abpLoginResultTypeHelper.CreateExceptionForFailedLoginAttempt(loginResult.Result, forgotPasswordModel.UsernameOrEmailAddress, GetTenancyNameOrNull());
}
}
Checking the AbpUser table after the
loginResult.User.SetNewPasswordResetCode();
i cannot see any password reset code for the user, they are all null.
Could someone point me in the right direction.
Thanks in advance
Thanks to answer below for being correct, just for completion below is exactly what worked. Obviously ignore the json return at the end
public virtual async Task<JsonResult> ForgotPassword(ForgotPasswordViewModel forgotPasswordModel, string returnUrl = "", string returnUrlHash = "")
{
//var user = await GetUserByChecking(emailAddress);
var user = await _userManager.FindByEmailAsync(forgotPasswordModel.UsernameOrEmailAddress);
if (user == null)
{
throw new UserFriendlyException("User not found!");
}
user.SetNewPasswordResetCode();
//Send an email to user with the below password reset code
/* Uri.EscapeDataString(user.PasswordResetCode) */
return Json("");
}
public class AccountAppService: IAccountAppService
{
public UserManager UserManager {get; set; }
public async Task SendPasswordResetCode(string emailAddress)
{
var user = await UserManager.FindByEmailAsync(emailAddress);
if (user == null)
{
throw new UserFriendlyException("User not found!");
}
user.SetNewPasswordResetCode();
//Send an email to user with the below password reset code
/* Uri.EscapeDataString(user.PasswordResetCode) */
}
}

getCurrentUser not going null even i logged out using Parse sdk

How to manage session with Parse SDK?
I have used SharedPrefences to locally store the session user info, and checked on the start whether move the user to Home Screen or Login screen. Is this the right process or there is an option to maintain session automatically without using SharedPrefecences.
Just use SharedPrefences according to your Login and SignUp Activity besides you can also use Parse Session Management..
I don't know the solution to the first problem as even I failed to get it working. One of the workaround is to store the user information in shared preferences temporarily when he/she logs in and clear them when user logs out of the app.
private void setUserPreferences(String username){
SharedPreferences sharedPreferences=getSharedPreferences("DEFAULT_SP", Context.MODE_PRIVATE);
SharedPreferences.Editor editor=sharedPreferences.edit();
editor.putString("username", username);
editor.commit();
}
private String getUserPreferences(){
SharedPreferences sharedPreferences=getSharedPreferences("DEFAULT_SP", Context.MODE_PRIVATE);
return sharedPreferences.getString("username", null);
}
private void clearUserPreferences(){
SharedPreferences sharedPreferences=getSharedPreferences("DEFAULT_SP", Context.MODE_PRIVATE);
SharedPreferences.Editor editor=sharedPreferences.edit();
editor.clear();
editor.commit();
}
Now you can call these functions when you log into the app and log out of the app. Not a viable solution but its all what I've got for the time being.
Also, you cannot login using email-id in parse, you will need username for that. So what you can do is to find the username associated with that email and then log into parse using that username.
private String mUsername=null;
private void getParseUsername(String email){
ParseQuery<ParseObject> query = ParseQuery.getQuery("User");
query.whereEqualTo("email", email);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> parseList, ParseException e) {
if (e == null) {
//assuming you don't have same email id's in the parse database
//, I don't think that's even allowed.
mUsername = parseList.get(0).getString("");
} else {
Log.d("parseList", "Error: " + e.getMessage());
}
}
});
}
For retrieving user info, you can simply type this code:
ParseUser.getCurrentUser().getUsername()
For your fourth question, if I understand it correctly, you don't want user to register with a mobile number which is already registered.
private boolean mDuplicatePhoneNo=false;
private void isPhoneNumberDuplicate(String phoneNo)
ParseQuery<ParseObject> query = ParseQuery.getQuery("User");
//Here phone_no is the field name in which you have stored your phone numbers
//Make sure they are in string format.
query.whereEqualTo("phone_no", phone);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> parseList, ParseException e) {
if (e == null) {
if(phoneNo.equals(parseList.get(0).getString("phone_no"))){
mDuplicatePhoneNo=true;
}
} else {
Log.d("parseList", "Error: " + e.getMessage());
}
}
});
Also make sure to visit https://parse.com/docs/android/guide#getting-started
for a better guide.

How to get user context during Web Api calls?

I have an web front end calling an ASP Web Api 2 backend. Authentication is managed with ASP Identity. For some of the controllers I'm creating I need to know the user making the call. I don't want to have to create some weird model to pass in including the user's identity (which I don't even store in the client).
All calls to the API are authorized using a bearer token, my thought is the controller should be able to determine the user context based on this but I do not know how to implement. I have searched but I don't know what I'm searching for exactly and haven't found anything relevant. I'm going for something like...
public async Task<IHttpActionResult> Post(ApplicationIdentity identity, WalkthroughModel data)
Update
I found the below which looked very promising... but the value is always null! My controller inherits from ApiController and has an Authorize header.
var userid = User.Identity.GetUserId();
Update 2
I have also tried all of the solutions in Get the current user, within an ApiController action, without passing the userID as a parameter but none work. No matter what I am getting an Identity that is valid and auth'd, but has a null UserID
Update 3
Here's where I'm at now.
[Authorize]
[Route("Email")]
public async Task<IHttpActionResult> Get()
{
var testa = User.Identity.GetType();
var testb = User.Identity.GetUserId();
var testc = User.Identity.AuthenticationType;
var testd = User.Identity.IsAuthenticated;
return Ok();
}
testa = Name: ClaimsIdentity,
testb = null,
testc = Bearer,
testd = true
The user is obviously authenticated but I am unable to retrieve their userID.
Update 4
I found an answer, but I'm really unhappy with it...
ClaimsIdentity identity = (ClaimsIdentity)User.Identity;
string username = identity.Claims.First().Value;
That gets me the username without any db calls but it seems very janky and a pain to support in the future. Would love if anyone had a better answer.
What if I need to change what claims are issued down the road? Plus any time I actually need the user's id I have to make a db call to convert username to ID
A common approach is to create a base class for your ApiControllers and take advantage of the ApplicationUserManager to retrieve the information you need. With this approach, you can keep the logic for accessing the user's information in one location and reuse it across your controllers.
public class BaseApiController : ApiController
{
private ApplicationUser _member;
public ApplicationUserManager UserManager
{
get { return HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>(); }
}
public string UserIdentityId
{
get
{
var user = UserManager.FindByName(User.Identity.Name);
return user.Id;
}
}
public ApplicationUser UserRecord
{
get
{
if (_member != null)
{
return _member ;
}
_member = UserManager.FindByEmail(Thread.CurrentPrincipal.Identity.Name);
return _member ;
}
set { _member = value; }
}
}
I use a custom user authentication (I dont use AspIdentity because my existing user table fields was far different from IdentityUser properties) and create ClaimsIdentity passing my table UserID and UserName to validate my bearer token on API calls.
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
User user;
try
{
var scope = Autofac.Integration.Owin.OwinContextExtensions.GetAutofacLifetimeScope(context.OwinContext);
_service = scope.Resolve<IUserService>();
user = await _service.FindUserAsync(context.UserName);
if (user?.HashedPassword != Helpers.CustomPasswordHasher.GetHashedPassword(context.Password, user?.Salt))
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
}
catch (Exception ex)
{
context.SetError("invalid_grant", ex.Message);
return;
}
var properties = new Dictionary<string, string>()
{
{ ClaimTypes.NameIdentifier, user.UserID.ToString() },
{ ClaimTypes.Name, context.UserName }
};
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
properties.ToList().ForEach(c => identity.AddClaim(new Claim(c.Key, c.Value)));
var ticket = new AuthenticationTicket(identity, new AuthenticationProperties(properties));
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(identity);
}
And how I use the ClaimsIdentity to retrieve my User table details on User ApiController Details call.
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("Details")]
public async Task<IHttpActionResult> Details()
{
var user = await _service.GetAsync(RequestContext.Principal.Identity.GetUserId<int>());
var basicDetails = Mapper.Map<User, BasicUserModel>(user);
return Ok(basicDetails);
}
Notice the
ClaimTypes.NameIdentifier = GetUserId() and ClaimTypes.Name = GetUserName()

MVC 3 where to encrypt the user's password?

I have my own password encryption dll that I am using to check the user's password when they login, this is referenced in my User entity.
Now I have created the ability for a user to register which is working fine, apart from the passwords are yet to be encrypted.
My question is quite simple, where should I put the encryption of the new user's password? I'm not sure as I am aware that the user's password shouldn't be transmitted in plain text, therefore I don't know where the best place to call the encryption function:
User Entity (where the encryption dll is already used for validation).
The User repository where the save user method is.
The User controller where the user creation views are controlled.
Somewhere else that I haven't considered!
Thanks very much
First of all, for client - server communication, I would suggest you to use SSL for the sensitive information (like passwords) not to be transferred in plain text format.
Afterwards, it's the common practice not to save passwords anywhere (even with encryption, but the hashed values of them.
You can put the hash function to the set method of password property. Here is an example:
public class Member
{
private string _username;
public string Username
{
get { return _username; }
set { _username = value.ToLowerInvariant(); }
}
public string Passhash {get;set;}
public void SetPassword(string password)
{
Passhash = Crypto.Hash(password);
}
public bool CheckPassword(string password)
{
return string.Equals(Passhash, Crypto.Hash(password));
}
}
public static class Crypto
{
public static string Hash(string value)
{
return Convert.ToBase64String(
System.Security.Cryptography.SHA256.Create()
.ComputeHash(Encoding.UTF8.GetBytes(value)));
}
}
Edit:
As Craig Stuntz pointed out, the Hash code in this example is very simple. See the following post for a more secure way to hash your password: Hashing passwords with MD5 or sha-256 C#
In a service layer method that will be responsible for doing 2 things:
call your encryption layer to hash the password (not to encrypt it)
call your user repository to persist the user entity to the database with the hashed password
The controller action will of course talk to the service layer.
Don't do your own password hashing and don't even think about encrypting passwords.
The effort of making this secure are tremendous. Use an existing method based on publicly available specs and algorithms.
//ENCODE
public string base64Encode(string sData)
{
try
{
byte[] encData_byte = new byte[sData.Length];
encData_byte = System.Text.Encoding.UTF8.GetBytes(sData);
string encodedData = Convert.ToBase64String(encData_byte);
return encodedData;
}
catch(Exception ex)
{
throw new Exception("Error in base64Encode" + ex.Message);
}
}
//DECODE
public string base64Decode(string sData)
{
try
{
System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
System.Text.Decoder utf8Decode = encoder.GetDecoder();
byte[] todecode_byte = Convert.FromBase64String(sData);
int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
char[] decoded_char = new char[charCount];
utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
string result = new String(decoded_char);
return result;
}
catch (Exception ex)
{
throw new Exception("Error in base64Decode" + ex.Message);
}
}
How to call
string encode= base64Encode(val);
string decode= base64Decode(val);
This is very helpful to decode and encode your string(password)

Login Procedure that does not require a Email Address

I have been asked to create a site where the user isn't required to provide a email to login because of privacy issues. In the past I have simple said this isn't advisable but in this case the client has stringently requested it. My initial thoughts are to potentially create administrators with a email whom could create generic logins (username and a password) and pass them to members of there group on site. Then at least I have a point of contact for login resets and such.
Has anyone had any experience with such situations where they have needed to create logins without the use of a email address? Could you direct me towards any relevant materials or tutorials that may be of use. I'm using MVC3 to develop this project.
I hope I understand your question right and you want to implement a login using username and password instead of email adress and password.
In that case you would have to implement your own custom membership provider and a custom roleprovider if needed.
You want to check the following page for more information:
Custom Membership Provider # Codeproject
EDIT
Fyi you dont need to implement every function - just implement the ones you need.
Custom membership provider from some of my older mvc3 projects. Removed most of the not-implemented functions for shorter code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
namespace Domain.Models
{
public class PlatformMembershipProvider : MembershipProvider
{
public SalesModelContainer ******** = new SalesModelContainer();
public override bool ChangePassword(string username, string oldPassword, string newPassword)
{
var user = ********.UserSet.Single(s => s.Email == username);
if (user.Password == oldPassword)
{
user.Password = newPassword;
return true;
}
else
{
return false;
}
}
public override string GetUserNameByEmail(string email)
{
var user = ********.UserSet.Single(s => s.Email == email);
return user.CompanyName;
}
public override void UpdateUser(System.Web.Security.MembershipUser user)
{
throw new NotImplementedException();
}
//TODO: use MD5 for password encryption
public override bool ValidateUser(string username, string password)
{
bool returnValue;
var user = ********.UserSet.SingleOrDefault(s => (s.Email == username) && (s.Password == password));
if (user != null)
returnValue = true;
else
returnValue = false;
return returnValue;
}
}
}

Resources