If I have the DecryptionKey and ValidationKey set to AutoGenerate in the machineKey section of the machine.config, how do i look up from .NET the actual generated keys which have been created?
We wish to use the same keys to encrypt and validate our own cookies.
Any clues/tips gratefully received.
I know this doesn't answer your question but to encrypt and validate your own cookies you don't need to know the actual values of the DecryptionKey and the ValidationKey. Just use Encrypt and Decrypt methods:
var ticket = new FormsAuthenticationTicket(
1,
"username",
DateTime.Now,
DateTime.Now.AddMinutes(10),
false,
"some user data");
string encryptedTicked = FormsAuthentication.Encrypt(ticket);
// TODO: use the encrypted ticket in a cookie
Using AutoGenerate will just cause you grief as you, or rather your users, will too often encounter exceptions. Between the time when the data was encrypted and when it's decrypted the keys can and will change (application restart via app pool recycle, Web.config touched, etc.).
Related
I want to store my credintial like email and password hardcode on my code, when I create jwt token then I want to use it. Can I do this??
If it possible how to access email and password.
First of all you can use credentials class and some collection of them in memory.
Secondly, you can use database
But: It is in general not recommended to store the user's password anywhere without encryption
Example: User -> Max#gmail.com, Password -> qwerty123 must be stored as: Max#mail.com and pass as awofi12312ASOIFDAOSF#?#?"!£!". No matter where: in memory, in db.
For usage you must also implement decryption in order to check credentials from encrypted value to it's decrypted state (from -> awofi12312ASOIFDAOSF#?#?"!£!" to -> qwerty123)
You can use the settings file to overcome this problem. Go to the Add New Item window and select the settings file. Then it will open a table and put "email" and "password" to identify the references. And also you need to select the data type and if you want to add a default value, you can add that one here too.
So you can read data by this line,
bool dataSaved = savedSetting.Default.dataSaved;
And also you can write data by this code,
savedSetting.Default.dataSaved = true;
savedSetting.Default.Save();
I am creating a windows service that has to send an email out at specific intervals to various people. I am using an account on a server that I need to connect with securely.
I found this reference: https://nimblegecko.com/how-to-store-login-details-securely-in-application-config-file/
the code I was trying to implement is this:
var configuration = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
configuration.AppSettings.Settings["username"].Value = EncryptString("new username", configPassword);
configuration.AppSettings.Settings["password"].Value = EncryptString("new password", configPassword);
configuration.Save();
My question is encoding the username and password as fixed text still seems to result in the same exposure as hard-coding it right?
any help would greatly be appreciated?
Uhm... Don't store in AppConfig settings.
If you cannot use a database for that (storing hashed and encrypted strings) get a new file for that, you can even protect it to allow only the service user account to read/modify it, or store it on the service profile directory (its user account profile directory)
I would do it using an ini file structure more easy to read than an xml, where each line contains something like
var mergedCredential = string.Format("{0}|{1}", "user#here.com" , "P#ssw0rd");
User1HashedCredentials=EncryptString("new username", mergedCredential);
I used a pipe to "merge" the credential as you can prevent users to use it on username
When you decrypt you split by "|"
var credentials = DecryptString("new username", User1HashedCredentials);
var splitted = credentials.Split('|');
Username = splitted[0]
Password = splitted[1]
An example of ini file:
[Users]
Count=5
[SendEmailSection]
User1=dsaa$#asdasd$##rr==
User2=dggggjh7/sd$##rr==
User3=dsaasd"/$%asdasd$##rr==
User4=dsas/&"dasd$##rr==
User5=dsAa&s3dasd$##rr==
Which is easier to mantain and modify. You can even make your own specialized ini reader/writer Read sections, split by "="
I do not suggest to store credential in app.config file. if you are planned to store there then you should store with proper encryption and decryption.
for you info you can refer this link
But I would suggest you to use window credential manager to store your password
for more details you can use their nuget package and their sample
Nuget
Another reference
Github
You can find it in your app's Preferences.
Right click on your project. Select add. Add .settings form. Then crate a table which contains email, password etc.
How about this system. I need some comments and maybe critical security part for this.
System which I use is maybe little bit complicated but 100% custom and should be good. This is a system for custom authentication in sending request to Asp.NET
WebApi
System works with sending 2 request
Everything what you need is 2 pairs of data. 1st one is public and 2nd one is secret.
Second pair of data be must be known to both sides (sender and receiver)
public: ApiKey and RequstID where ApiKey is "normal" and requstID have to be unique always;
secret: UserName and Password (both side have to know these data)
Sender:
Send 1st request with 3 parameters: 1st= ApiKey, 2nd=RequstID, 3rd=Hash(ApiKey+RequestID+USerName+Pass)
Server:
Read RequstID
Read ApiKey and get data about users UserName and Pass for this ApiKey
From the own side: Hash(ApiKey+RequestID+USerName+Pass)
Check is Hash from Sender same us from Server
If is False:
BadRequest - or whatever...
if is True
Before all - Create on database on table for collect data about request.
This is table with columns (e.g.):
ID(autoincrement), RequstID, Token, TokenValidateDateTime
Before create new row, check is there already this RequestID and if there is return BadRequest.
If there is not - make new row.
RequstID is RequstID from request;
Token - Generate token (e.g. Guid.NewGuid().ToString());
TokenValidateDateTime= DateTime.Now.AddMinutes(2) - or some other value ...
In response for the first request send back this this Token (from item 2)
In the second request, Sender have to use AGAIN same RequstID and Token (from response before)
Server will check
Combination RequstID and Token
Token validation (depend on current date time);
Is everything is OK, user is validated
if is not - BadRequest, or whatever
Any suggestions or comments are welcome :)
It sounds similar to traditional website username / password authentication which returns a session cookie.
But you're also including a api key & request id and a hash. The hash won't add to much value unless there's a shared salt, as once someone works out your hashing technique it will be vulnerable to dictionary attacks.
Also generating a Guid token isn't "cryptographically secure", it is designed to be unique but it's often based upon the system clock meaning it is predictable.
Building bespoke security mechanisms are generally unadvised; doing bespoke encryption is defiantly a "no no" (which you aren't doing as far as I'm aware). Bespoke authentication is probably less risky, but seeing as there are many frameworks already existing that have been critiqued by security experts I'd suggest researching if any of those suit first.
I'd recommend looking at asp.net core's security options: https://learn.microsoft.com/en-us/aspnet/core/security/?view=aspnetcore-2.1
I have been trying to work out how to enable 2f login with Google Authentication in my Identity server 4 application.
2fa works fine with both email and phone.
if i check
var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user);
it has two email and phone. I am assuming that this would be the two factor providers that have been set up for this user.
Now if i check _usermanager again there is a field called tokenproviders. Which appears to contain default, email, phone, and authenticator. I assume these are the ones that Asp .net identity is configured to deal with.
I have worked out how to create the secret needed to genreate the QR code for the authecator app. As well has how to build the QR code and to test the code
var code = _userManager.GenerateNewAuthenticatorKey();
var qr = AuthencatorHelper.GetQrCodeGoogleUrl("bob", code, "My Company");
var user = await _signInManager.TwoFactorAuthenticatorSignInAsync(codeFromAppToTestWith, true, false);
if (user == null)
{
return View("Error");
}
Now the problem. I have gone though every method I can find on the user trying to work out how to add another token provider to the user.
How do I assign a new token provider to the user and supply the secret code needed to create the authentication codes?? I am not even seeing any tables in the database setup to handle this information. email and phone number are there and there is a column for 2faenabled. But nothing about authenticator.
I am currently looking into creating a custom usermanager and adding a field onto the application user. I was really hoping someone had a better idea.
From what I can see, you are generating a new authenticator key each time the user needs to configure an authenticator app:
var code = _userManager.GenerateNewAuthenticatorKey();
You should be aware that using GenerateNewAuthenticatorCodeAsync will not persist the key, and thus will not be useful for 2FA.
Instead, you need to generate and persist the key in the underlying storage, if it not already created:
var key = await _userManager.GetAuthenticatorKeyAsync(user); // get the key
if (string.IsNullOrEmpty(key))
{
// if no key exists, generate one and persist it
await _userManager.ResetAuthenticatorKeyAsync(user);
// get the key we just created
key = await _userManager.GetAuthenticatorKeyAsync(user);
}
Which will generate the key if not already done and persist it in the database (or any storage configured for Identity).
Without persisting the key inside the storage, the AuthenticatorTokenProvider will never be able to generate tokens, and will not be available when calling GetValidTwoFactorProvidersAsync.
I'm trying to implement the "Writing Information to UserData" section of this article, but it doesn't work properly when the cookie is part of the URI.
My code:
// Create the cookie that contains the forms authentication ticket
HttpCookie authCookie = FormsAuthentication.GetAuthCookie( userName, createPersistantCookie );
// Get the FormsAuthenticationTicket out of the encrypted cookie
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt( authCookie.Value );
// Create a new FormsAuthenticationTicket that includes our custom User Data
FormsAuthenticationTicket newTicket = new FormsAuthenticationTicket( ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration, ticket.IsPersistent, "foo");
// Update the authCookie's Value to use the encrypted version of newTicket
authCookie.Value = FormsAuthentication.Encrypt( newTicket );
// Manually add the authCookie to the Cookies collection
HttpContext.Current.Response.Cookies.Add( authCookie );
// Determine redirect URL and send user there
string redirUrl = FormsAuthentication.GetRedirectUrl( userName, createPersistantCookie );
HttpContext.Current.Response.Redirect( redirUrl, false );
When cookieless is used, the page redirects but doesn't get the correct URI with the cookie information in it, so it loops back to my Login page where Request.IsAuthenticated returns false. An endless loop ensues.
How do I redirect to the proper URI?
I found this to be an interesting problem, so I set about doing some digging, testing, and a little bit of debugging into the .net framework source.
Basically, what you are trying to do will not work. Anything you put into the Response.Cookies collection will just be ignored if the browser doesn't support cookies. You can check Request.Browser.Cookies to see if cookies are supported.
In asp.net, both session state and authentication support a cookieless mode, but this does not extend to other cookies. In fact, it seems that session and authentication can be set to different modes of operation themselves even.
The authentication system can store it's own data in the URI, but it does so by directly manipulating the URI itself. Sadly, Microsoft doesn't appear to have exposed these capabilities to code outside the authentication module.
Basically, if you use the methods like FormsAuthentication.GetAuthCookie() and FormsAuthentication.SetAuthCookie() then the authentication system will take care of putting that information into the URI for you automagically... but it doesn't allow you to supply a customized authentication ticket to these methods... so you are stuck with the default auth ticket.In these cases, you are on your own for storing any custom data.
Anyway...
There really isn't much advantage to storing custom data directly in an authentication ticket if the authentication system has gone cookieless... in cookieless mode, things like "persistant cookie" have no meaning so you'll be regenerating the data at least once per session anyway.
The most common suggestion for cases where you are cookieless but still need custom data like this is to enable cookieless sessions, and just store your custom data as a session variable. The session ID will get put into the URI, but the custom data will stay in memory on the server. The usage pattern is identical no matter if your sessions are cookieless or not.
If you really wanted to, you could come up with a system of storing the custom data in the URI manually. The easiest thing to do would be to put the custom data into query strings or use pathdata. I can't see any real advantage to this over sessions variables unless you are just deperate not to use server memory (adding a little memory to a server is cheap, ugly URLs and manually writing code to deal with them is not cheap).
Thank you for the great explanation, Stephen. In cases where the user does not allow cookies, I'm just going to have to avoid the UserData and load the data from the database.
Before the code listed above I'll do:
if( !HttpContext.Current.Request.Browser.Cookies || !FormsAuthentication.CookiesSupported )
{
FormsAuthentication.RedirectFromLoginPage( userName, false);
return;
}