Singleton To Ensure Password Security - c#

I am making a little project that requires me to access one of my email accounts frequently to send emails. With that being said, I obviously know the log-in information ahead of time, and in order to protect the password from being created into a SecureString multiple times, I have created a Singleton class:
public sealed class Sender
{
#region Private Member Variables
private readonly static Sender SingletonSender = new Sender(); // Singleton object
private readonly SecureString password;
private const String defaultEmailAddress = "xxxxxxxxxxxxx";
#endregion
#region Properties
public static Sender ReminderSender
{
get { return SingletonSender; }
}
#endregion
#region Constructors
private unsafe Sender()
{
Char[] passwordCharacters = {/* password characters */};
fixed (Char* pwChars = passwordCharacters)
{
password = new SecureString(pwChars, passwordCharacters.Length);
}
password.MakeReadOnly();
passwordCharacters = null;
}
#endregion
// Additional methods
}
Now, I am wondering if this is the correct way to protect the password from being exposed unnecessarily? Additionally, if anyone has a better strategy to solve this, I would love to hear it. Note, that my goal of this application is to have it deployed on various PC's not just on my own.

Run the code in a web app, and have the various PCs ask the server to run this code on their behalf.
Do you really want to make sure the user's have .NET 4.5? (answer: no)
You could probably get a Rails app on Heroku in less overall time.
By the way, if you are using Gmail, you can put an OAUTH token on the user's machine instead of your password, which you can revoke. It's still a password of sorts, but at least it's not your password.
https://developers.google.com/gmail/oauth_overview

Related

Dynamics CRM Online Object caching not caching correctly

I have a requirement where we need a plugin to retrieve a session id from an external system and cache it for a certain time. I use a field on the entity to test if the session is actually being cached. When I refresh the CRM form a couple of times, from the output, it appears there are four versions (at any time consistently) of the same key. I have tried clearing the cache and testing again, but still the same results.
Any help appreciated, thanks in advance.
Output on each refresh of the page:
20170511_125342:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125358:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125410:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125342:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125437:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125358:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125358:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
20170511_125437:1:55a4f7e6-a1d7-e611-8100-c4346bc582c0
To accomplish this, I have implemented the following code:
public class SessionPlugin : IPlugin
{
public static readonly ObjectCache Cache = MemoryCache.Default;
private static readonly string _sessionField = "new_sessionid";
#endregion
public void Execute(IServiceProvider serviceProvider)
{
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
try
{
if (context.MessageName.ToLower() != "retrieve" && context.Stage != 40)
return;
var userId = context.InitiatingUserId.ToString();
// Use the userid as key for the cache
var sessionId = CacheSessionId(userId, GetSessionId(userId));
sessionId = $"{sessionId}:{Cache.Select(kvp => kvp.Key == userId).ToList().Count}:{userId}";
// Assign session id to entity
var entity = (Entity)context.OutputParameters["BusinessEntity"];
if (entity.Contains(_sessionField))
entity[_sessionField] = sessionId;
else
entity.Attributes.Add(new KeyValuePair<string, object>(_sessionField, sessionId));
}
catch (Exception e)
{
throw new InvalidPluginExecutionException(e.Message);
}
}
private string CacheSessionId(string key, string sessionId)
{
// If value is in cache, return it
if (Cache.Contains(key))
return Cache.Get(key).ToString();
var cacheItemPolicy = new CacheItemPolicy()
{
AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration,
Priority = CacheItemPriority.Default
};
Cache.Add(key, sessionId, cacheItemPolicy);
return sessionId;
}
private string GetSessionId(string user)
{
// this will be replaced with the actual call to the external service for the session id
return DateTime.Now.ToString("yyyyMMdd_hhmmss");
}
}
This has been greatly explained by Daryl here: https://stackoverflow.com/a/35643860/7708157
Basically you are not having one MemoryCache instance per whole CRM system, your code simply proves that there are multiple app domains for every plugin, so even static variables stored in such plugin can have multiple values, which you cannot rely on. There is no documentation on MSDN that would explain how the sanboxing works (especially app domains in this case), but certainly using static variables is not a good idea.Of course if you are dealing with online, you cannot be sure if there is only single front-end server or many of them (which will also result in such behaviour)
Class level variables should be limited to configuration information. Using a class level variable as you are doing is not supported. In CRM Online, because of multiple web front ends, a specific request may be executed on a different server by a different instance of the plugin class than another request. Overall, assume CRM is stateless and that unless persisted and retrieved nothing should be assumed to be continuous between plugin executions.
Per the SDK:
The plug-in's Execute method should be written to be stateless because
the constructor is not called for every invocation of the plug-in.
Also, multiple system threads could execute the plug-in at the same
time. All per invocation state information is stored in the context,
so you should not use global variables or attempt to store any data in
member variables for use during the next plug-in invocation unless
that data was obtained from the configuration parameter provided to
the constructor.
Reference: https://msdn.microsoft.com/en-us/library/gg328263.aspx

Dependency Injection ASP.NET : Unaware about the dependencies until Runtime

I am using ASP.NET Core and using DI to build Hashing functionality. Since I don't know the type of hashing used at this stage (we are storing it in persistent storage).
The ICrypto Contract
public interface ICrypto
{
string HashPassword(string plainPassword);
bool VerifyHashedPassword(string hashedPassword, string providedPassword);
}
I have several Implementations of ICrypto and they just wrap other libraries and provide the implementation of ICrypto Signatures. For example:
CryptoMD5
CryptoSHA1
CytpoOther
Now, in UserService I inject the ICyrpto to hash passwords for example:
Public class UserService
{
ICrypto _crypto;
public UserService(ICrypto crypto)
{
_crypto = crypto;
}
public bool Login (string username, string password)
{
//code omitted
var hash = _crypto.HashPassword(password);
}
}
Adding Dependencies to the Container in Startup class
//get encryption type stored in cache, db or somewhere
var cryptoType = //get param
if (cryptoType = "SHA1")
{
services.AddTransient<ICrypto, CryptoSHA1>();
}
else if (cryptoType = "MD5")
{
services.AddTransient<ICrypto, CryptoMD5>();
}
I am looking for a way to do this according to best practices and will reflect what Steves has mentioned.
In case the cryptoType value you get from the database is constant during the lifetime of the application (which means, if you want to change it, you're fine with restarting the application), this means that the cryptoType is a configuration value and you can simply wire your application as you described:
var cryptoType = //get param
if (cryptoType = "SHA1")
{
services.AddTransient<ICrypto, CryptoSHA1>();
}
else if (cryptoType = "MD5")
{
services.AddTransient<ICrypto, CryptoMD5>();
}
If however you need to swap implementations dynamically (which I find very unlikely in your specific case, but let's assume for the sake of argument), the solution is to implement a proxy and wrap the real implementations. Example:
public interface DatabaseCryptoSelectorProxy : ICrypto
{
private readonly CryptoSHA1 sha;
private readonly CryptoMD5 md5;
public DatabaseCryptoSelectorProxy(CryptoSHA1 sha, CryptoMD5 md5) {
this.sha = sha;
this.md5 = md5;
}
public string HashPassword(string plainPassword) =>
GetCrypto().HashPasswords(plainPassword);
public bool VerifyHashedPassword(string hashedPassword, string providedPassword) =>
GetCrypto().VerifyHashedPassword(hashedPassword, providedPassword);
private ICrypto GetCrypto() {
var cryptoType = // get param
if (cryptoType = "SHA1") return this.sha;
if (cryptoType = "MD5") return this.md5;
throw new InvalidOperationException("Unknown cryptotype: " + cryptotype);
}
}
This proxy has a few clear advantages:
It makes the consumers of ICrypto oblivious to the fact that some complex dispatching is happening based on some data from a database.
It prevents having to execute this query during object graph construction, since this would make this process unreliable and hard to verify.
Some notes though about your design around password hashing from a security perspective. I don't see any strong reason to switch from crypto methods the way you are doing, and especially not the switch to algorithms like MD5. Instead, I advise using PBKDF2 in the form of Rfc2898DeriveBytes. An example of how to do this can be shown here. By concatenating the number of hash iterations to the hashed password (for instance by simply doing + "|" + iterations), you can later on increase the number of used iterations by keeping up with the industry standard and it allows you to automatically rehash the user's password on login if his number if you detect the number of used iterations an old value.
Additionally, if you think that you ever need to move away from PBKDF2, you can prefix the hash with the used algorithm, this way you can again use a proxy that passes a hashed password on to the right implementation based on the algorithm-prefix. By storing the algorithm in the password hash in the database, you can migrate transparently without having to convert all existing passwords at once (which is impossible, because you can't decrypt a hashed password).

Using Windsor Castle and WcfFacility to create WCF proxies with Message Security and username credentials

OK we are using message security with username credentials (and X509 certificate encryption) to communicate with our WCF service. I am not happy with this approach but that is not the point of question and I do not want to get into that.
I am using Windsor Castle to generate proxies in ASP NET Web Forms + MVC hybrid. We are using forms authentication and use user's credentials to communicate with WCF services - this will help auditing all calls. As I said, I am not happy with this approach but that is not the point.
I have created CustomCredentials class which inherits AbstractCredentials class and WcfFacility happily uses it to configure my proxies. As you will see below, all my setup is just a few lines. I have created unit test below which demonstrates all I am doing: creating a proxy, making a call and then releasing it in a loop. Now I am expecting this test to work but it does not and I get
Expected: 10 But was: 1
I have not included binding but that is irrelevant, as I said I am using Message Security with X509 certificates.
I know that for channel factory with message security, once opened you cannot change credentials. Is this the same issue?
Is this a bug in WcfFacility or a limitation?
Here is the code
[TestFixture]
public class Harness
{
private IWindsorContainer _container;
public static int NumberOfTimesCredentialsConfigured = 0;
[SetUp]
public void Setup()
{
_container = new WindsorContainer().AddFacility<WcfFacility>();
Component
.For<IFrameworkUsers>()
.ActAs(DefaultClientModel
.On(WcfEndpoint.FromConfiguration("FrameworkUsersService"))
.Credentials(new CustomCredentials()))
.LifeStyle.Transient);
}
[Test]
public void MultipleProxyTest()
{
const int Runs = 10;
NumberOfTimesCredentialsConfigured = 0;
for (int i = 0; i < Runs; i++)
{
IFrameworkUsers frameworkUsers = _container.Resolve<IFrameworkUsers>();
frameworkUsers.CreateUserSession();
_container.Release(frameworkUsers);
}
Assert.AreEqual(Runs, NumberOfTimesCredentialsConfigured);
// FAILS!!! Expected: 10 But was: 1
}
[TearDown]
public void TearDown()
{
}
}
public class CustomCredentials : AbstractCredentials
{
#region Overrides of AbstractCredentials
protected override void ConfigureCredentials(ClientCredentials credentials)
{
credentials.UserName.UserName = "testuser";
credentials.UserName.Password = "abcdef";
Harness.NumberOfTimesCredentialsConfigured++;
}
#endregion
}
I posted on castle forum and no reply. It is a problem by design in WCF Facility in which they cache service channels which is OK with no security but does not work with security.
Your credentials and IWcfEndpoint in general (which is the result of DefaultClientModel.On(...) call) are created only once when the container is configured. If you want to provide different credentials each time - you need to make them dynamic dependency like below:
_container.Register(Component.For<IFrameworkUsers>()
.AsWcfClient()
.DependsOn(
(k, d) => d["endpoint"] =
new DefaultClientModel(WcfEndpoint.FromConfiguration("FrameworkUsersService"))
.Credentials(new CustomCredentials())
)
.LifeStyle.Transient);
String endpoint here is the name of dependency consumed by WcfFacility. I'm not sure where exactly, but it is resolved in some interceptor (you may set breakpoint in the lambda and debug your test to look at call stack). I assume it is made to match name of AsWcfClient(IWcfEndpoint endpoint) method argument.
So the answer is no, it is nor bug nor limitation of WcfFacility.

How to invalidate a C# WCF session if login is incorrect

I am writing a remote service for an application using WCF, in which login information is kept in a database. The service requires session establishment through a login or account creation call. There is no ASP involved.
Now, when a client starts a session by calling an exposed IsInitiating method, I check the account data provided against the information on the database and, if it is not correct, I want to invalidate that session and force the client to start again with a call to an IsInitiating method.
Looking at some other questions, I have found pros and cons for two ways to invalidate a session. One does so the hard way, by throwing a FaultException; the other with softer manners, storing accepted session IDs.
Now, the first one, although achieving what I desire, is way too aggressive, given that incorrect logins are part of the normal flow of the application. The second one, on the other hand, allows the client to continue calling non-initiating methods, eventhough they will be rejected, while also incurring in a considerable code overhead on the service due to the added thread safety requirements.
So, the question: Is there a third path which allows the service to invalidate the session initialization and communicate it to the client, so it is forced to make a new IsInitiating call?
A reduced version of the code I have:
[DataContractAttribute]
public class AccountLoginFault
{
public AccountLoginFault (string message)
{
this.Message = message;
}
[DataMemberAttribute]
public string Message { get; set; }
}
[ServiceContract (SessionMode = SessionMode.Required)]
public interface IAccountService
{
[OperationContract (
IsInitiating = true)]
[FaultContractAttribute (
typeof (AccountLoginFault),
ProtectionLevel = ProtectionLevel.EncryptAndSign)]
bool Login (AccountData account, out string message);
}
[ServiceBehavior (
ConcurrencyMode = ConcurrencyMode.Single,
InstanceContextMode = InstanceContextMode.PerSession)]
public class AccountService : IAccountService
{
public bool Login (AccountData account, out string message)
{
UserManager userdb = ChessServerDB.UserManager;
bool result = false;
message = String.Empty;
UserData userData = userdb.GetUserData (account.Name);
if (userData.Name.Equals (account.Name)
&& userData.Password.Equals (account.Password))
{
// Option one
// Get lock
// this.AcceptedSessions.Add (session.ID);
// Release lock
result = true;
} else
{
result = false;
// Option two
// Do something with session context to mark it as not properly initialized.
// message = "Incorrect account name or password. Account provided was " + account.Name;
// Option three
throw new FaultException<AccountLoginFault> (
new AccountLoginFault (
"Incorrect account name or password. Account provided was " + account.Name));
}
return result;
}
}
Throwing an exception is by far the easiest option because WCF enforces that the session cannot be re-used. From what I gather, what you would like the third party component to accomplish comes quite close to this functionality. But, instead of forcing the client to call IsInitialized again, you would force the client to create a new connection. This looks like a very small difference to me.
An alternative would be to have a private variable bool _authorised and check this variable at every method call.
Do something like this:
public ConnectResponseDTO Connect(ConnectRequestDTO request) {
...
if(LoginFailed)
OperationContext.Current.OperationCompleted += FaultSession;
}
private void FaultSession(object sender, EventArgs e) {
var context = (OperationContext) sender;
context.Channel.Abort();
}
This will fault the channel and the client will havce to reesatablish the session.

How do I maintain user login details in a Winforms application?

Hi can I'm very new to windows forms. Here I want to maintain state (like session in web applications) in windows forms.
Actually i want to store user login details in session. But i think there is no concept of session in winforms. So what is the alternative method to handle this type of situation.
Regards,
Nagu
There is no concept of Session variables in windows forms. What you can do is:
Create a internal class that holds the User name and password and any other variables and enumerations needed across the application (Something like Common.cs). These can be accessed through public properties across the application.
Have a parameterized constructor for all the forms and send the user name and the password whenever you are showing the form.
public class MyForm : Form
{
private string userName;
private string password;
}
Since windows forms are statefull (opposed to stateless for web forms), you can just use a field in your Form class.
You need to think more in terms of scope than session; as long as an object remains in scope you will be able to pull values from its public properties/fields.
In your case it would make sense to store the user details in a static class:
public static class LoginInfo
{
public static string UserID;
}
Now you can access the UserID simply from anywhere in your code:
MessageBox.Show(LogInfo.UserID);
In winforms you can use variables that are exposed to other forms through methods or properties.
You can also use static variables.
In the following example, you would have a controller for each window or group of windows. The controllers would be passed to one another depending on how they need to collaborate (what knowledge they need to share, etc). The important thing is to keep your application state in the controllers and limit the windows to handling user input and events.
// pseudocode, because I do not know WinForms that much
class MainController
{
private Guid securityToken;
public Guid SecurityToken
{
get { return securityToken; }
set { securityToken = value; }
}
}
class LoginWindowController
{
MainController mainController;
LoginWindow loginWindow;
public LoginWindowController(MainController mainController)
{
this.loginWindow = new LoginWindow(this);
this.mainController = mainController;
}
public void Show()
{
loginWindow.IsVisible = true;
}
public void HandleLogin()
{
Guid token =
myobject.Authenticate(loginWindow.Username, loginWindow.Password);
if (token != Guid.Empty)
{
mainController.SecurityToken = token;
}
}
}
In reply to your comment to my first reply:
You are creating the new instance of the Login form. How is that supposed to have values. It is a Login form and hence I believe you will be closing it as the user enters user name and password and clicks OK or whatever.
Then, there is no way you can get the values from the Login form as it is closed. If you need to stick to this approach, this could be a way:
Do not close the Login form, just hide it.
Pass the current instance to the next form. Like this:
In Login form:
NextForm nxt = new NextForm(this);
The constructor of NextForm will look like:
public NextForm(LoginForm frm){
// Code here
}
Now in NextForm, you can access the properties through "frm".
from a program i was using with a login form to store global variables and to store the password as a secure string. Within the program I am able to "run as" a specific user when I call processes. You can use it for other things besides process.start.
//to run process as another user
//create these global variables on the first
//form or piece of code in your program
class usernameGlobalVariable
{
public static string var = "";
}
class passwordGlobalVariable
{
public static SecureString var;
}
// use these as event handlers for text fields
//for your login form
private void usernameTextBox_TextChanged(object sender, EventArgs e)
{
usernameGlobalVariable.var = usernameTextBox.Text;
}
private void passwordTextBox_TextChanged(object sender, EventArgs e)
{
SecureString passWord = new SecureString();
foreach (char c in passwordTextBox.Text.ToCharArray())
{
passWord.AppendChar(c);
}
passwordGlobalVariable.var = passWord;
}
//put this on form that launches program
//this assigns variables for process.start
//change fileName to path and name of program
// use \\ in paths
string fileName = "c:\\hdatools\\Ping2.exe";
string arguments = "";
string domain = "domain";
//start the process
//put this on the page along w the above variables that
//launches the app as another user
//the .var variables are global
{
Process.Start(
fileName,
arguments,
usernameGlobalVariable.var,
passwordGlobalVariable.var,
domain);
}
It's unclear to me whether you are talking about a web application or a stand along application based upon one of your responses. If you are talking about a web application, you can use the Session properties on the Page object.
It would set the variables like this:
Session["username"] = "Username";
Session["fullname"] = "User's full name";
You could then access like:
lblGreetings.Text = "Hi " + Session["fullname"];
Is that what you were after?

Categories