What is the best way to set up username and password authentication in a Silverlight-Enabled WCF web service?
The best way for me has been forms authenication...using ASP.NET application services.
Basically you expose 3 *.svc files in your WCF service that handle authenication, roles, and profiles. There is no code behind because it's built into the .net assemblies. You will have to do some configuration in the .config (see link) to enable them.
Details here: http://blogs.msdn.com/brada/archive/2008/05/03/accessing-the-asp-net-authentication-profile-and-role-service-in-silverlight.aspx
Side Note on ASPNETDB.MDF
Normally all the user accounts and profiles will be in ASPNETDB.MDF which is located on a local file in the APP_Data folder but I find this clumsy especially with permissions so I kept it in my primary WCF database but you can choose another if you have the connection string. To initialize it I ran "C:\Windows\Microsoft.NET\Framework\v2.0.50727\a
spnet_regsql -C *Data Source=localhost;Initial Catalog=MYDB;Persist Security Info=True;User ID=**;Password=****;" * -A all" to include the ASP.NET membership tables and sprocs into the db of my choice. If you do you this..ensure you override the default LocalSQLServer connectionstring or it won't find the db like this in web.config of your asp.net website
<connectionStrings>
<clear/>
<add name="LocalSQLServer" connectionString="Data Source=localhost;Initial Catalog=MYDB;Persist Security Info=True;User ID=**;Password=****;" providerName="System.Data.SqlClient" />
To actually add user accounts and roles
1) from Visual Studio
2) Click on your ASP.NET website
3) There should be a menu above called Website that shows up...select ASP.NET Configuration and your browser will start with the configuration website that will edit your config and update the configured database with accounts and roles
I hope this helps
Related
I used the standard VS 2012 MVC 4 Internet template in a .NET Framework 4 project. I was mainly using External Logins (Google, Microsoft, Facebook, Yahoo, Twitter) to access the parts of my application which are decorated with the [Authorize] attribute.
[One thing I noticed is that the default web.config created by VS does not contain any sections on membership or role providers, unlike those I see in an ASP.NET web form application.]
I deployed the project to an azurewebsites.net site. Things worked fine initially, but after some use, the app will throw an exception because it tried to use the server's machine config file to access SqlMembershipProvider using a connection string called LocalSqlServer.
Q1: How does SqlMembershipProvider relate to the SimpleMembership provider?
Anyway, I created an <membership> section in web.config and added <clear/>. This solved the that problem but created another problem, as now it tried to access SqlRoleProvider in machine.config using the connection string LocalSqlServer, again! I tried to add a <roleManager> section with a <clear/> to my web.config, but I was not as successful. It insists on a defaultProvider to be included. What should I put?
Q2. What is the assembly to use for the SimpleMembership role provider in .NET Framework 4.0 MVC 4 application?
I tried:
System.Web.Security.SqlRoleProvider, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
but it created another problem, that it Could not find stored procedure 'dbo.aspnet_CheckSchemaVersion'. Before I run aspnet_regsql.exe I would like to ask:
Q3: Why does the standard app work fine for some time and then start looking for SqlMembershipProvider and SqlRoleProvider?
Is there someone playing around with the settings on the server?
Here is what your web.config settings should look like when using SimpleMembership.
<roleManager enabled="true" defaultProvider="SimpleRoleProvider">
<providers>
<clear/>
<add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
</providers>
</roleManager>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear/>
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData"/>
</providers>
</membership>
The assembly that contains the SimpleMembership role provider is WebMatrix.WebData.
SqlMembershipProvider is not related to SimpleMembership except that they are both membership providers. My guess is that if SimpleMembership is not configured correctly it is defaulting to a SqlMembershipProvider.
Somewhere in your application you need to initialize the database for SimpleMembership by calling WebSecurity.InitializeDatabaseConnection. The first parameter in this method indicates what connection string to use. If the application was created using the MVC4 Internet template this method is called in the filter InitializeSimpleMembershipAttribute which is decorated on the Account Controller. If you need to add a call to the InitializeDatabaseConnection method yourself I would just put it in the Gloaba.asax Application_Start method.
Situation:
I have a .NET asmx web service deployed on my web server. This service calls a service on another server (our SharePoint server, if that's relevant). I want to impersonate/delegate the call to the SharePoint service from my web service by using the credentials of the client.
Problem:
I'm getting a 401 response back from the SharePoint service when I call MY Web Service and it calls SharePoint.
Setup:
My web server is running IIS 7. The app pool is running under "Network Service"
On my Windows Server 2003 domain controller the web server has "Trusted for Delegation (Kerberos Only)" enabled.
In ISS my app has Anonymous Authentication Disabled, Impersonation Enabled, and Windows Authentication Enabled with all three providers enabled (Negotiate:Kerberos, Negotiate, and NTLM)
The SharePoint server is set up with Anonymous Enabled, Impersonation enabled and Windows Authentication Enabled with ONLY provider NTLM enabled.
I can see on the SharePoint logs that when I run locally in Visual Studio a username is getting passed through (and the service works correctly) but when I run it on the web server NO username is on the log file and I get a 401 error
What an I setting up wrong to make the Kerberos delegation work?
Ideas? Thanks!
Platform:
Using IIS7 this is what I did on BOTH servers. The first server and the second that we want the Kerberos authentication to "hop" to.
Step 1:
For the IIS site that has the services in it that you are calling (on each server) go into IIS manager, click on the site on the left under Connections and open up the "Authentication" section under IIS. Set "ASP.NET Impersonation" to Enabled and 'Windows Authentication" to Enabled. All other options under Authentication (Ananymous, Forms, etc.) should be be set to Disabled.
Under "Windows Authentication" right click and select "Providers". Set the only provider to be "Negotiate:Kerberos" (This forces Kerberos. If you want, after you get Kerberos working you can use both the "Negotiate" and "NTLM" providers and remove "Negotiate:Kerberos" so that clients unable to do Kerberos can connect. Note: I currently have mine set to "Negotiate" and "NTLM" and it seems to work)
Under "Windows Authentication" right click and select "Advanced Settings". Uncheck the "Enable Kernal-mode" box. (My Extended Protection option was set to off, didn't try anything else)
Step 2:
For each server you have to set up SPNs. The SPNs would be the following (either A OR B):
A:
If your app pool is running under an IDENTITIY that is a DOMAIN ACCOUNT add the following SPNs to THAT DOMAIN ACCOUNT on the domain controller
http/COMPUTER_NETBIOS_NAME
http/COMPUTER_NETBIOS_NAME.FULLY_QUALIFIED_DOMAIN_NAME
http://COMPUTER_NETBIOS_NAME.FULLY_QUALIFIED_DOMAIN_NAME
(if your not running on the default port, also add an additional 3 entries with the port name attached: http/COMPUTER_NETBIOS_NAME:PORT etc.)
B:
If your app pool is running under the IDENTITY "NetworkService" then add the same SPNs as above except replace "http" with "HOST" BUT ADD THEN TO COMPUTER_NETBIOS_NAME on your domain controller.
I'm still working to implement this in production, but this is what works for me in my Test environment. I'll keep this updated as I find out more.
Note:
This works if you are using the COMPUTER_NETBIOS_NAME directly in the url when you connect. If you are using a alias (www.mysite.mydomain.com) or the IP address directly this will not work. I believe, although I have not fully tested it, that you would have to folle the steps above but replace COMPUTER_NETBIOS_NAME with the alias or IP address when adding the SPNs. (or add it with both the netbios and the alias/ip, not really sure)
Also, if you get an error about a setting not being valid for integrated... after you turn on the "ASP.NET Impersonation" then you might need to add
<validation validateIntegratedModeConfiguration="false" />
to your web.config in the system.webServer section
Try this:
Move Negotiate to the top of the Providers' list. And, in the applicationHost.config file usually under C:\Windows\System32\inetsrv\config, add useKernelMode="true" useAppPoolCredentials="true" to the <windowsAuthentication> tag under the <location> tag for your application, like below:
<location path="YOUR_APPLICATION_PATH">
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="false" />
<windowsAuthentication enabled="true" useKernelMode="true" useAppPoolCredentials="true">
<providers>
<clear />
<add value="Negotiate" />
<add value="NTLM" />
</providers>
</windowsAuthentication>
</authentication>
</security>
</system.webServer>
</location>
Delegation requires Kerberos. You'll have to make the SharePoint server support authentication with Kerberos.
This is my connection string, which the web service (hosted in IIS, running under ApplicationPoolIdentity) uses to connect to database
<add name="AdventureWorksEntities"connectionString="metadata=.\AdventureWorks.csdl|.\AdventureWorks.ssdl|.\AdventureWorks.msl;
provider=System.Data.SqlClient;provider connection string='Data Source=TestMachine;Initial Catalog=AdventureWorks;
Integrated Security=True;Connection Timeout=60;multipleactiveresultsets=true'" providerName="System.Data.EntityClient" />
When I try to access the site I am getting an exception: Login Failed for user MyDomain\TestMachine$.
Why is IIS trying to use TestMachine to connect and not my user account (e.g MyDomain\TestUser) ?
The reason I believe could be because its hosted under ApplicationPoolIdentity which uses machine creds.
How do I specify it to use the context of the user that made the request without having to run the application under custom identity (i.e I want it to continue running under ApplicationPoolIdentity)?
If I set <identity impersonate = true/>' in my web.config file then I am able to access the site locally from IIS server machine and access to database works but then accessing the site remotely fails. My Webservice is using Windows Authentication. Any thoughts on this ?
You need to enable Windows Authentication and ASP.NET Impersonation in IIS
Then in your web.config
<system.web>
<authentication mode="Windows" />
<identity impersonate="true" />
</system.web>
This VS 2012 extension is meant to allow me to add a local Development STS to my MVC application http://visualstudiogallery.msdn.microsoft.com/e21bf653-dfe1-4d81-b3d3-795cb104066e
I follow the very simple instructions e.g. Right Click the project name and select Identity and Access in the menu. Select your Identity Provider and the OK to apply the settings to your web.config.
I run my MVC 4 application and it redirects immediately to login.aspx
I'm guessing there are special instructions for MVC 4.
What are they?
Where do I find them?
EDIT
To be clear I have created a ASP.MVC 4 Internet application in visual studio 2012. Then I am using the Identity & Access Tool to add a local development STS to Test my application.
I am running the site on a local IIS Express
When I debug the application I am redirected to
localhost:11378/login.aspx?ReturnUrl=%2f
This occurs even if I remove forms authentication as suggested in advice already given.
In my case I added this
<system.web>
...
<httpModules>
...
<remove name="FormsAuthentication" />
</httpModules>
</system.web>
and this
<system.webServer>
...
<modules>
...
<remove name="FormsAuthentication" />
</modules>
</system.webServer>
EDIT
The next problem you might get is this
A claim of type
'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier'
or
'http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider'
was not present on the provided ClaimsIdentity. To enable anti-forgery
token support with claims-based authentication, please verify that the
configured claims provider is providing both of these claims on the
ClaimsIdentity instances it generates. If the configured claims
provider instead uses a different claim type as a unique identifier,
it can be configured by setting the static property
AntiForgeryConfig.UniqueClaimTypeIdentifier.
add these 2 claims to the Development STS in the Identity and Access Tool
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier
http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider
and add this line to your Global.asax
AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
This article helped me
Removing FormsAuthentication module worked for me.
<httpModules>
...
<remove name="FormsAuthentication" />
</httpModules>
I had a similar problem with my MVC4 application on local IIS Express.
It turned out that Windows Authentication was enabled for the project. Disabling Windows Authentication (in project properties pane -- press F4) fixed the problem.
I am learning and designing a WCF service. I have picked to use Windows credential as the authentication method, and I have configured it correctly, hopefully, because I can see the authentication audit log from event log viewer when I am testing my service hosted in the local machine.
But now I come up with this weird question: what users will not be authenticated under such configuration? Does my service authenticate all Windows user within the same Windows domain, or can I specify what specific users within my domain will/will not get authenticated?
Or, does it mean that I can only control what users (in my domain) can perform what operations my service is providing through authorization(that I know how to do)?
It sounds simple but all the material I found only tell you how to perform authentication, doesn't say how to deny authentication request.
Update:
After reading #syneptody answer, I still have two questions:
I must say my confusion between authentication and authorization is still there. The authentication means to identify the user. But if I want to tell a user belonging to the same domain as the service host(it's IIS, by the way), who just makes a request to my service, "you are not authenticated", what I really should say is "I do authenticate you, but you are not authorized (to perform your request)", is it right? There is not a state of "Unauthenticated" for a user in my domain? And what if a user not belonging to my domain makes a request? My service will tell him "You are not authenticated" or "You are not authorized"? As long as this user has an identity, the service will authenticate it, and continue to investigate whether it should be authorized?
#syneptody mentioned This "authorization" element. It belongs to ASP.NET, and it specifies which roles can/can't access the resource (whether it is the website or an application hosted in the website, depending on which Web.config file it is in). Is it right? But what if I don't use ASP.NET or don't host the WCF in ASP.NET Compatibility Mode, will it still work like that? Actually the requirement for us is to only provide the service, so I didn't think of using ASP.NET because in my opinion it is more like a web client consuming my service.
By the way, my usage scenario is this service will be hosted and consumed within intranet. So I choose Windows credential for authentication and Windows Groups for role-based authorization because it requires minimum work in my opinion.
Take a look at this article:
http://msdn.microsoft.com/en-us/library/aa702682.aspx
It does a pretty good job explaining the connection between WCF and ASP.NET. If you are able to run your services in ASP.NET compatibility mode you can use the ASP.NET authorization rules. In a domain environment where you can leverage Integrated Authentication there is no easier way to provide authorization to your services.
Your service implementation:
[AspNetCompatibilityRequirements(RequirementsMode AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior]
public class Foo { ... }
Then in your configuration:
<system.web>
<authorization>
<allow users="?" />
<allow roles="DOMAIN_SECURITY_GROUP" />
<deny users="*" />
</authorization>
<authentication mode="Windows" />
<identity impersonate="false" />
</system.web>