I've inherited quite a complex ASP.NET website, which uses AspNetSqlMembershipProvider member authentication. There's a reset password feature on the site which resets a users password and emails it to them. However, users are struggling because the new auto-generated password is very complex: 14 characters of punctuation, numbers and letters. Some users (it has an elderly user-base) don't even know how to create some of the characters on their keyboards.
So I've been asked to force the auto-generated passwords to be 7 characters in length and if possible only contain alphanumeric characters.
I've read this post http://weblogs.asp.net/owscott/archive/2005/05/11/Changing-the-Password-Complexity-in-ASP.NET-V2.0.aspx which someone on a different Stack Overflow question posted as a helpful link, but it doesn't seem to relate to auto-generated passwords, only user-generated ones.
The line in the web.config file is like this:
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=y03f5f7f11d50a34" connectionStringName="theSite" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" applicationName="theSiteApp" requiresUniqueEmail="true" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression=""/>
Does anyone know how to tame auto-generated passwords?
I've found a solution - albeit a little hacky: forums.asp.net/p/1148079/2175576.aspx.
Related
Or to edit a store to introduce a specific key?
My goal is to set a key from a legacy ASP.NET Webforms site that uses the Membership provider. As such it has a MachineKey element in web.config where a ValidationKey is specified.
If I could have this key set in .NET Core Data Protection, I believe I could then implement a password hash using code similar to the example given here: https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/consumer-apis/password-hashing?view=aspnetcore-2.1. With the correct key set, I should then be able to produce hashes matching those for the legacy site.
But it seems like the entire philosophy of Data Protection is that it sets the keys for you automatically and you should have nothing to do with them. Is there a way around this?
EDIT:
In ASP.NET WebForms, using the Membership provider to hash passwords for users, I have the following entry in my web.config:
<system.web>
<machineKey validationKey="*********"
decryptionKey="*********"
validation="HMACSHA256"
decryption="AES" />
</system.web>
When a password is hashed, the value in the "validationKey" attribute is involved in the hashing, isn't it? If the validationKey was different, then given the same password/salt combination, the produced hash would be different? Or is this where I'm going wrong?
If the above is correct, then my question is, how do I use the same key value in ASP.NET Core, so that when I hash with the same password/salt combination I produce the same hash as I have in my legacy database? How do I provide .NET Core with the validationKey value in order to hash? Or it's not even involved?
Does anybody know what type of <KeyInfo> does ADFS expect to find in field of a SAMLRequest message?
There are several options to choose from. I'm using Keycloak SAML library, which knows to send this field in <KeyValue> format only (which contains modulus & exponent of the RSA public key). Can ADFS digest this?
<ds:KeyInfo>
<ds:KeyValue>
<ds:RSAKeyValue>
<ds:Modulus>tfJ29N0G1...</ds:Modulus>
<ds:Exponent>AQAB</ds:Exponent>
</ds:RSAKeyValue>
</ds:KeyValue>
</ds:KeyInfo>
Answering my own question - apparently, the <KeyInfo> format doesn't matter.
I got keycloak working with ADFS, while using <KeyValue> format only.
As I was told on keycloak-user mailing list, "ADFS should be able to determine the correct certificate for signature validation itself by iterating all
available certificates."
so I started building a website in MVC 4 with a template and everything was going fine. But, I felt that there were a lot of features already added into the template that I didn't understand in the slightest and therefore it was a challenge using some of those features properly. One such feature being the login system.
Now I managed to to setup and talk to my external database without to many hassles, but I was/am at a complete loss on how the template knows the users name and that he is logged in.
So I am trying to recreate/setup the same functionality, but from scratch so I can understand how it actually works. That being said... I am lost!
[AllowAnonymous]
public ActionResult Login(LoginModel model)
{
try
{
var canLogin = Services.Login(model.Username, model.Password);
var cas = Services.CheckAcountStatus(canLogin.Token);
if (cas.Payload.Items.Exists(m => !m.IsSynchronized)) RedirectToAction("VerifyPin", "Account", cas.Payload);
return RedirectToAction("Index", "MyPage");
}
catch (CustomException ase)
{
ModelState.AddModelError("", ErrorCodeToString(ase.Error));
}
return View(model);
}
This is what I have thus far.
<authentication mode="Forms">
<forms name="MyName" loginUrl="~/Account/Login" timeout="30" />
</authentication>
A lot of examples have explanations for setting up a database using EF and such, but im afraid that is the equivelant to my external database.
Is a database really needed to know if a user is logged in? or is it more just a cookie?
Beyond this I don't know where to go. If someone could at least point me in a good direction I would appreciate it.
In the end my only real goal is to have an easy way for communication between pages that a user is logged in.
if (Request.IsAuthenticated)
{
// Lets us know if the Request is authenticated
}
A simple answer to: "In the end my only real goal is to have an easy way for communication between pages that a user is logged in."
I would suggest reading about the configuration options for forms authentication in the web.config as well as researching the inner workings of the formsauthentication ticket. MVC also has the Authorize Attribute you can use.
http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute(v=vs.108).aspx
ASP.NET MVC 4 introduced a new membership provider called SimpleMemberhsip which is very flexible and easy to use. Here is an article that shows you how to customize SimpleMembership, which may be the best approach for you instead of trying to build a security framework from scratch that is compatible with ASP.NET forms authentication. Forms authentication relies on cookies to tell if a user is logged in across pages. I do not see anything in your code example that handle the cookies. If you look at the Login method that is generated by the Internet template you will see that the method WebSecurity.Login not only handles authenticating the user, it also handles generation of the cookie.
I like the new simplemembership feature in MVC 4 internet template with links to OAuth for external logins in VS 2012 RTM. For the most part authentication feature are working. However even after spending over 8 hours on this I am unable to implement roles based authorization to work on my controllers. SimpleMembership is turning out to be anything but simple.
I have searched stackoverflow, googled and have read the latest by John Galloway, tried many suggestions and still have not been able to resovle this issue. It all started with getting Sql connection error and could not figure out why when the connection string and everything else was good. It took many hours to figure out the it is Roles class that is causing problem.
The [Authorize] attribute on controllers works as before for basic authentication. But any time I try to use Roles it give sql connection error (because it reverts to the old DefaultRolesProvider which tries to connect to default SqlExpress aspnetdb file and fails). So something like:
[Authorize(Roles="admin")]
does not work. It will work if I go back to the old asp.net membership providers, but then I lose the simple database tables, token bases confirmation and recovery, more secure password hashing and more importantly external logins via OAuth.
The only thing that works inside code and razor views is
User.IsInRole("admin")
which is OK for menu items and such, but ver cumbersome to implement inside every single Action in controller (and I do not like that it only tests for single role at a time).
I will greatly appreciate any guidance to resovle this issue.
Found an answer here by Mehdi Golchin which seems to take care of:
[Authorize(Roles="admin,editor,publisher")]
If I also add this to the home controller:
[InitializeSimpleMembership]
Because this attribute is on the Accounts controller, SimpleMembership database gets initialize only after the first use of the accounts controller like login/register. Even when the current user gets logged in from the cookie, the database is not initialized and so it throws an error. One solution is to put this attribute on the home controller which gets called when I launch my Website. But, then it needs to be placed on every controller because I check roles and display different menu items based on role.
This is poor design as the database should be initialized on the App_Start and not when first used.
I did try to put
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
in the Global.asax Application_Start(), and it takes care of role checking in menu items using User.IsInRole("admin"), but then throw error in any controller with [Authorize(Roles="admin")] attribute, even with additional attribute [InitializeSimpleMembership] is applied.
So right now the solution is to put `[InitializeSimpleMembership] on all controllers as a user may initially land on any page using external links.
It still can't figure how to initialize the SimpleRolesProvider class to do more of the role management instead of just User.IsInRole().
These things do work better in the webmatrix webpages site and obviously the port ot MVC is not complete. It conflicts and gets confused with the default asp.net membership providers.
EDIT
OK I was not thinking [InitializeSimpleMembership] filter could be applied globally by putting this line in the FilterConfig.cs in the App_Start folder:
filters.Add(new InitializeSimpleMembershipAttribute());
That takes care of that problem. Now need a solution for SimpleRolesProvider initialization or else I will have to write my own roles provider.
UPDATE:
This post by Scott Allen has solved all my problems.
By including this in web.config:
<roleManager enabled="true" defaultProvider="simple">
<providers>
<clear/>
<add name="simple" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
</providers>
</roleManager>
<membership defaultProvider="simple">
<providers>
<clear/>
<add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData"/>
</providers>
</membership>
all the methods of Roles and Membership classes become available and can be initialized in code as follows:
var roles = (SimpleRoleProvider) Roles.Provider;
var membership = (SimpleMembershipProvider) Membership.Provider;
Had the same problem when I was moving my web app from VS2010/MVC3 to VS2012/MVC4.
And couldn´t get [InitializeSimpleMembership] to work.
Found out that adding this to your web.config does the trick:
<appSettings>
<add key="enableSimpleMembership" value="false" />
</appSettings>
And everything works fine as it did before.
I'm new to WCF and REST so please excuse any obvious questions.
I'm trying to create a RESTful API that will be used by clients. The API needs to be available only to authenticated users so I believe the best way to do this (from what I've read over the last couple of days) is using Basic Auth over SSL which is fine.
I have a basic WCF REST Service Application in VS2010 targeting .NET 3.5. - the bare bones of this have been directly taken from http://www.codeproject.com/KB/WCF/BasicAuthWCFRest.aspx
What I'm struggling to understand and to differentiate on is how to authenticate suers while also restricting the calls that clients can make based on who they are.
So the call that the clients will need to make will pass some basic information from their system to ours, each client will be able to make the same call however I don't want client A being able to post info into client B's area on our side and vice versa.
I was planning on having both clients POSTing something like the following url:-
api.mydomain.com/sale/
however, I wonder if it would make more sense to make it clearer to do this:-
api.mydomain.com/clientA/sale/
api.mydomain.com/clientB/sale/
...as you can see, I'm quite lost!
Also, the example code I have is using a custom MembershipProvider - I understand the basics of Membership but again, don't know if I should be using this in some way to restrict the clients posting data to eachothers areas?
Sorry for the waffling - sooo many questions :(
Regarding authorization (granting an authenticated use access to specific resources) there's a couple of ways.
You can restrict access to certain areas (directories / URL paths) via the <location> element in the web.config, and then using the <authorization> element only allow certain users or roles (groups) to access those locations. This is OK if the number of locations / users / roles is manageable and doesn't change too much. For example:
<location path="ProtectedPlaces/Foo">
<system.web>
<authorization>
<allow roles="FooGroup"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
Alternatively, under the covers you can use an API based approach that essentially does the same thing. There are a number of libraries out there that can help, including AzMan; an authorization library that's in the same 'family' as the role membership provider; there is also one in the Enterprise Libraries.
This article might be of some help (see: "Step 2: Limiting Functionality Based On the Currently Logged In User’s Roles").
Here is how I did this. I used a standard membership provider (but you can also do the same with a custom membership provider) to authenticate the user, but I do not let IIS do this. I authenticate the user myself (as part of the REST API) and generate a token for that user, which I store in the membership database and send back to the client.
For each request the client makes it needs to send a valid token as well. As the token is stored together with a user id, I can then determine if the token is valid and what user is making the request. Because of this I can then determine if the request is allowed based on my own security rules.
If a user is only allowed to do a certain request on it's own data, then you don't need to send any identifying information except for the token.
HTH.