I am using client application services to authenticate users for windows app. (SqlMembershipProvider) Login works fine and I can grab the user name by using the following code:
userName = System.Threading.Thread.CurrentPrincipal.Identity.Name.ToString();
I want to grab a bit more info about the user such as the email address. I have tried the following line to get the user.
MembershipUser mu = Membership.GetUser();
The above line gives me a "specified method is not supported" message. Same result if I pass in the userName as well.
Is there a way to get more detailed user info using client application services as you would in an asp.net app? If not, I wonder if I should just create my own Web Service wrapper instead?
I'm using the 4.0 Framework.
Update: A slice of the app.config file
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="http://PC-03/FAAppServices/Authentication_JSON_AppService.axd" credentialsProvider="BillingFormsApplication.LoginForm, BillingFormsApplication" savePasswordHashLocally="True" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="http://PC-03/FAAppServices/Role_JSON_AppService.axd" cacheTimeout="1209600" honorCookieExpiry="True" />
</providers>
</roleManager>
</system.web>
Update 2: Stack Trace
at System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider.GetUser(String username, Boolean userIsOnline)
at System.Web.Security.Membership.GetUser(String username, Boolean userIsOnline)
at BillingFormsApplication.MDIMain.MDIMain_Load(Object sender, EventArgs e) in C:\xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.cs:line 340
SimpleMembership, as the name implies, is very simple and does not implement all of the MembershipProvider methods; just those required for MVC basic authentication and authorization. If you try to use a method that is not implemented you will get that exception. You can either create your own MembershipProvider from scratch or you can inherit from SimpleMembership and implement the methods that are not implemented.
The exception is by design
The class ClientAuthenticationMembershipProvider does not use the method GetUser.
If your app.config is configured to use ClientAuthenticationMembershipProvider, and you call Membership.GetUser, then you will always get a NotSupportedException.
ref: https://learn.microsoft.com/en-us/dotnet/api/system.web.clientservices.providers.clientformsauthenticationmembershipprovider.getuser
Related
I am trying to set up an ASP.NET MVC site to use LDAP. I feel like I have everything set up right, but Membership.ValidateUser keeps returning false when I am expecting it to return true. I've read some documentation, like for example this one on AD membership, but one thing I want to make sure I completely understand as I am troubleshooting is this:
Is the defaultProvider attribute value something specific provided by Microsoft? Or is it just an arbitrary name, and we can call it anything?
This is my current web.config setup:
<connectionStrings>
<add name="ADConnectionString" connectionString="LDAP://dc1.dc2.dc3.dc4/DC=dc1,DC=dc2,DC=dc3,DC=dc4" /
</connectionStrings>
<membership defaultProvider="AspNetActiveDirectoryMembershipProvider">
<providers>
<clear />
<add name="AspNetActiveDirectoryMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider" connectionStringName="ADConnectionString" attributeMapUsername="sAMAccountName" />
</providers>
</membership>
We have recently started migrating to Castle Windsor and i'm having some issues getting our WCF service running. It is a regular windows service NOT HOSTED IN IIS where we serve up SSL material and use a custom X509CertificateValidator to verify the client's presented certificate.
Below is the code i'm using to create the WCF service. It is in a separate project to the WCF service which references it.
public IWindsorContainer RegisterService<T,K>(
IServiceBehavior customBehavior,
Action<ServiceHost> onCreate = null,
Action<ServiceHost> onOpen = null,
Action<ServiceHost> onClose = null,
Action<ServiceHost> onFault = null) where T : class where K : T
{
var facility = this.AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero);
var serviceModel = new DefaultServiceModel()
.OnCreated(onCreate)
.OnOpened(onOpen)
.OnClosed(onClose)
.OnFaulted(onFault);
var service = Component.For<T>()
.ImplementedBy<K>()
.AsWcfService<T>(serviceModel)
.LifestylePerWcfOperation<T>();
if (customBehavior != null)
facility.Register(Component.For<IServiceBehavior>().Instance(customBehavior));
facility.Register(service);
return facility;
}
The service starts as expected (i can navigate to the service using chrome with no issues) and the service is presenting and validating the SSL material (i.e. hits the custom validator) but after that, the client gets this in a FaultException:
Looks like you forgot to register the http module Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule
To fix this add
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />
to the <httpModules> section on your web.config.
If you plan running on IIS in Integrated Pipeline mode, you also need to add the module to the <modules> section under <system.webServer>.
Alternatively make sure you have Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 assembly in your GAC (it is installed by ASP.NET MVC3 or WebMatrix) and Windsor will be able to register the module automatically without having to add anything to the config file.
Below is a chunk of my App.Config, i have tried to place the module in all areas that were suggested through googles and through some guesswork:
...
<system.web>
<httpModules>
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />
</httpModules>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
<system.webServer>
<modules>
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />
</modules>
<handlers>
<add name="PerRequestLifestyle" verb="*" path="*.castle" preCondition="managedHandler" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Microkernel"/>
</handlers>
</system.webServer>
<system.serviceModel>
<extensions>
<endpointExtensions>
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />
</endpointExtensions>
<bindingExtensions>
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />
</bindingExtensions>
<behaviorExtensions>
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />
</behaviorExtensions>
<bindingElementExtensions>
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />
</bindingElementExtensions>
</extensions>
...
Im pretty much out of ideas. Does anyone know what could be the cause? If not, could anyone explain abit more about the error i'm getting?
Any help would be much appreciated!
Once again i'm answering my own question (the next day after posting, oh dear) :P
This error message is being thrown here (thank god for open source!):
https://github.com/castleproject/Windsor/blob/016730de012f15985410fb33e2eb907690fe5a28/src/Castle.Windsor/MicroKernel/Lifestyle/PerWebRequestLifestyleModule.cs
tldr - see below:
public class PerWebRequestLifestyleModule : IHttpModule
{
...
private static void EnsureInitialized()
{
if (initialized)
{
return;
}
var message = new StringBuilder();
message.AppendLine("Looks like you forgot to register the http module " + typeof(PerWebRequestLifestyleModule).FullName);
message.AppendLine("To fix this add");
message.AppendLine("<add name=\"PerRequestLifestyle\" type=\"Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor\" />");
message.AppendLine("to the <httpModules> section on your web.config.");
if (HttpRuntime.UsingIntegratedPipeline)
{
message.AppendLine(
"Windsor also detected you're running IIS in Integrated Pipeline mode. This means that you also need to add the module to the <modules> section under <system.webServer>.");
}
else
{
message.AppendLine(
"If you plan running on IIS in Integrated Pipeline mode, you also need to add the module to the <modules> section under <system.webServer>.");
}
#if !DOTNET35
message.AppendLine("Alternatively make sure you have " + PerWebRequestLifestyleModuleRegistration.MicrosoftWebInfrastructureDll +
" assembly in your GAC (it is installed by ASP.NET MVC3 or WebMatrix) and Windsor will be able to register the module automatically without having to add anything to the config file.");
#endif
throw new ComponentResolutionException(message.ToString());
}
...
}
From this I quickly gathered that the issue was that the PerWebRequestLifestyleModule was not being initialized, which was ok for me as i did not need it for this service!
Looking further into my own code, some of my repositories that were being loaded for this service were set to use LifestylePerWebRequest from when they were being used in our web console, bingo!
After adjusting them to something else (in this case 'LifestylePerWcfOperation`) all was working fine.
I've created an MVC 4 app and for the first time I am trying to use membership.
I have a sql database where I have created the membership tables and using "ASP.NET Configuration" I have selected my providers, added roles and a user.
When I try to login using the login page, I get the error;
To call this method, the "Membership.Provider" property must be an
instance of "ExtendedMembershipProvider".
I am not using azure nor am i using NuGet.
My config file looks like;
<membership defaultProvider="SqlMembershipProvider">
<providers>
<add connectionStringName="ApplicationServices" name="SqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="SqlRoleProvider">
<providers>
<add connectionStringName="ApplicationServices" name="SqlRoleProvider"
type="System.Web.Security.SqlRoleProvider" />
</providers>
</roleManager>
That's all that was added for me.
My account controller has the following attribute but removing it makes no difference.
[InitializeSimpleMembership]
and it fails on this line;
if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
What do I need to do to be able to log users in?
You set SqlMembershipProvider in config but trying to use SimpleMembershipProvider
Pick one and cofigure your app accordingly.
If you set up db against SimpleMembersip (most frequently one table with UserId, Username and other fields), then change your config as follows and make sure InitializeSimpleMembershipFilter looks for userId, username fields as they are set up in your table:
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear/>
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
<roleManager defaultProvider=“SimpleRoleProvider“>
<providers>
<add name=“SimpleRoleProvider“ type=“WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData“/>
</providers>
</roleManager>
Otherwise, to set up SqlMembershipProvider you may refer to the bottom of this page: http://msdn.microsoft.com/en-us/library/system.web.security.sqlmembershipprovider.aspx
I'm working on a C# Webservice that needs to provide authentication as well as roles and profile management. I need each profile to have a property of type List. The profile section in the web.config looks like this:
<profile defaultProvider="MyProfileProvider" enabled="true">
<providers>
<remove name="MyProfileProvider"/>
<add connectionStringName="MySqlServer"
applicationName="MyApp"
name="MyProfileProvider"
type="System.Web.Profile.SqlProfileProvider" />
</providers>
<properties>
<add name="Websites" type="System.Collections.Generic.List<String>" serializeAs="Binary"/>
</properties>
</profile>
However, when I start the webservice and try to access that property it returns the following error:
System.Configuration.ConfigurationErrorsException: Attempting to load this property's type resulted in the following error: Could not load type 'System.Collections.Generic.List<String>'. (C:\Projects\MyProject\web.config line 58) ---> System.Web.HttpException: Could not load type 'System.Collections.Generic.List<String>'.
Is there a way to use a generic collection for this purpose?
After more searching I finally managed to find the answer. The solution is to use the type name qualified by its namespace. This means that for my issue I used:
<add name="Websites" type="System.Collections.Generic.List`1[System.String]" serializeAs="Binary"/>
I also found out that it is also possible to specify classes defined in other assemblies. To use those you need the assembly-qualified name. For example, that would be "System.Collections.Generic.HashSet`1[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" for a Hashset of Strings.
So i am trying to get a simple system working where i have an asp.net mvc web app with the forms authentication already up and running with a user created. i can login with no problem using the mvc controller/view.
I then added a silverlight app to the solution, using the existing web app as the host. I created a silverlight-enabled web service and added an operation contract with the following code:
[OperationContract]
public bool Authenticate(string username, string password)
{
if (FormsAuthentication.Authenticate(username, password))
{
FormsAuthentication.SetAuthCookie(username, false);
return true;
}
return false;
}
In the silverlight app, i added two text boxes and a button, and a service reference to the WCF service. In the button click event, i have this code:
void login_Click(object sender, RoutedEventArgs e)
{
AuthenticationService.AuthenticationClient client = new AuthenticationClient();
client.AuthenticateCompleted += new EventHandler<AuthenticateCompletedEventArgs>(client_AuthenticateCompleted);
client.AuthenticateAsync(username.Text, password.Text);
}
void client_AuthenticateCompleted(object sender, AuthenticateCompletedEventArgs e)
{
if (e.Result)
{
MessageBox.Show("Success");
}
else
{
MessageBox.Show("Error");
}
}
So the problem is, when i enter my login info and click the button, all i get is the error box. I can't seem to get it to authenticate the user.
What am i missing?
UPDATE:
Here is the error i get in the async complete handler:
Line: 86
Error: Unhandled Error in Silverlight Application
Code: 4004
Category: ManagedRuntimeError
Message: System.NullReferenceException: Object reference not set to an instance of an object.
at UserPortal.MainPage.client_AuthenticateCompleted(Object sender, AuthenticateCompletedEventArgs e)
at UserPortal.AuthenticationService.AuthenticationClient.OnAuthenticateCompleted(Object state)
UPDATE 2:
So the error i posted above is because the e.Error property is null. So i am not getting any specific error from the authentication service. Is there something i need to change in the web.config to get this to work via silverlight?
<authentication mode="Forms">
<!-- forms loginUrl="~/Account/LogOn" timeout="2880"/ -->
</authentication>
<membership>
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/"/>
</providers>
</membership>
<profile>
<providers>
<clear/>
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ApplicationServices" applicationName="/"/>
</providers>
</profile>
<roleManager enabled="false">
<providers>
<clear/>
<add connectionStringName="ApplicationServices" applicationName="/" name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
<add applicationName="/" name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</providers>
</roleManager>
Ok, so i got it to work, kinda.
Following the content here i managed to get a service up and running that would allow me to successfully login. The problem is i had to change the RequireSSL to false. I could not get the service to work running on https.
Anyone know what i need to do to get it to work on SSL? i am using the ASP.NET development server right now, do i need to configure a real version of IIS on this box for that to work?
When using WCF and running on an development server, you need to have proper certificates installed. its not silverlight its the wcf client proxy that tries to verify your vertificate and fail I think. What happens when you try to hit it from asp or the browser?