Membership for external users in Sitecore 8 - asp.net-mvc-5

I want to build a user registration store for Sitecore 8 website. The users will go in an external database.
Sitecore.NET 8.0 (rev. 150223)
.NET Framework 4.0.30319.18052
Razor Version=3.0.0.0
MVC 5.2.3.0
Asp.net MVC comes with the membership built in (AccountController, views, etc). I wanted to port this to my Sitecore project. The problem is Sitecore also uses membership internally. I know there is a way for getting membership working for the Sitecore 6.x versions through the switching providers described at Sitecore authenticate users against external membership database.
Is it still the same process for Sitecore 8?

This still applies to Sitecore 8 and the core asp.net membership features and the switching membership provider can still be used. The mongo db side of Sitecore 8 is for xDb, but you still use membership systems to authenticate.
I won't provide any further detail as the post you referenced seems to cover it all. Just in case there's another good post here:
https://himadritechblog.wordpress.com/2014/11/24/sitecore-custom-membership-provider/
Make sure you declare a new domain for you membership system in your domains.config.

I ended up not using the SimpleMembership and just going with Membership. I could not get the adapter that the thecodeking link mentions to work.
This method is not properly documented. I just had to change the config files. I did not have to create a custom class that inherits from MembershipProvider.
Web.config:
In membership section,
change realProviderName to "switcher"
copy "sql" node and change name and connectionStringName to "external"
In switchingProviders section,
add "external" node with domains "external"
web.config:
<membership defaultProvider="sitecore" hashAlgorithmType="SHA1">
<providers>
<clear />
<!-- change realProviderName to "switcher" -->
<add name="sitecore"
type="Sitecore.Security.SitecoreMembershipProvider, Sitecore.Kernel"
realProviderName="switcher"
providerWildcard="%"
raiseEvents="true"
/>
<add name="sql"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="core"
applicationName="sitecore"
minRequiredPasswordLength="1"
minRequiredNonalphanumericCharacters="0"
requiresQuestionAndAnswer="false"
requiresUniqueEmail="false"
maxInvalidPasswordAttempts="256"
/>
<add name="switcher"
type="Sitecore.Security.SwitchingMembershipProvider, Sitecore.Kernel"
applicationName="sitecore"
mappings="switchingProviders/membership"
/>
<!-- copy "sql" node and change name and connectionStringName to "external" -->
<add name="external"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="external"
applicationName="sitecore"
minRequiredPasswordLength="1"
minRequiredNonalphanumericCharacters="0"
requiresQuestionAndAnswer="false"
requiresUniqueEmail="false"
maxInvalidPasswordAttempts="256"
/>
</providers>
</membership>
<switchingProviders>
<membership>
<provider providerName="sql" storeFullNames="true" wildcard="%" domains="*" />
<!-- add "external" node with domains "external" -->
<provider providerName="external" storeFullNames="true" wildcard="%" domains="external" />
</membership>
</switchingProviders>
ConnectionStrings.config:
add connection "external"
config:
<add name="external" connectionString="..." providerName="System.Data.SqlClient"/>
Domains.config:
add domain "external"
config:
<domain name="external" ensureAnonymousUser="false" />
Then use the "external" provider directly which saves user to external db. This is the key point.
// uses "external" provider directly
Membership.Providers["external"].CreateUser(...)
Instead of this which saves to core db.
// uses default provider
Membership.CreateUser(...)

I personally like to keep the membership logic very simple and away from custom providers. Sitecore has a concept of Virtual User that you can instantiate once you authenticate on the external DB. You can set any custom properties on this virtual user and let sitecore record it in xDB.
Here is a good example.

Related

IIS Authorization Rule Issue for AD Group

I want to configure the IIS to accept only the request from users who belong to a particular AD Group. This configuration is required at Default Website level. So on Default Website I enabled Windows Authentication, went to Authorization rules option,choose Add Allow Rule and put the AD group in "Specified roles or user groups:".
This does not work with any AD group (for which I am a member). This work well when I put the AD user in the next option "Sepcified User" https://i.stack.imgur.com/hbqhK.png .
Can some one please help on what I am missing. As stated above I want to do it at Default Website level on IIS so there is no Web.config invovled.
Cheers.
Real old thread, but in case anyone Googling this issues comes across the same problem:
I could only get this to work with AD groups that are have their Group Type set to "Global" in AD. Ones set to "Security" wouldn't work for me.
In IIS this is specified under the "Roles" section on the IIS Authorization rules.
I have only Windows Authentication selected as an authentication method. Strange IIS bug?
Here is the web.config for reference
<configuration>
<system.webServer>
<security>
<authorization>
<remove users="*" roles="" verbs="" />
<add accessType="Allow" users="" roles="DOMAIN\TestGroup" />
</authorization>
</security>
</system.webServer>
</configuration>

Impersonate settings in config for multiple databases

I have a console application which connects to two different SQL databases. I'm using the "impersonate" tag within the config file to force the application to login as "APP_USER". The APP_USER account utilizes windows authentication & has been granted permissions in both databases.
The first DB connection works fine, but the second one fails as it is trying to log in as my account which does not have access.
System.Data.SqlClient.SqlException: Login failed for user 'DOMAIN\CURRENT_USER'.
What do I need to change in my config to make the application login to both databases as another user?
<configuration>
<connectionStrings>
<add name="Connection1" connectionString="metadata=res://*/Models.Model1.csdl|res://*/Models.Model1.ssdl|res://*/Models.Model1.msl;provider=System.Data.SqlClient;provider connection string="data source=DB1;initial catalog=DBcat1;integrated security=True;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
<add name="Connection2" connectionString="metadata=res://*/Models.Model2.csdl|res://*/Models.Model2.ssdl|res://*/Models.Model2.msl;provider=System.Data.SqlClient;provider connection string="data source=DB2;initial catalog=DBcat2;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
<system.web>
<identity impersonate="true" userName="DOMAIN\APP_USER" password="password"/>
</system.web>
</configuration>
Apparently the config-setting route can only be used in asp.net projects. In order to accomplish this within a console application, you have to write code that utilizes LogonUser within the advapi32.dll library.
Similar question: StackOverflow: Windows Impersonation from C#
I based my final code off of the following project: Code Project: A small C# Class for impersonating a User
Everything seems to be working fine now.

Azure WCF Service + Sharepoint 2010 Sandbox Visual Web Part = error

I have problem to call Azure WCF Service from sandbox Visual Web Part Sharepoint 2010. All installed al local computer Windows 7 64 Ultimate -
Sharepoint Foundation 2010 to develop web parts and Visual Studio 2010 with Azure SDK. Web Service starting in local Azure Emulator, web part in local computer.
When i use standart master "Add Service Reference" to web part, that generate app.config, then throw error:
ServiceReference1.Service1Client serv = new ServiceReference1.Service1Client();
Label1.Text = serv.GetData(9);
Could not find default endpoint element that references contract 'ServiceReference1.IService1' in the ServiceModel client configuration section.
This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.
When i create connection programmatically -
EndpointAddress adr = new EndpointAddress(new Uri("http://127.0.0.1:81/Service1.svc"));
BasicHttpBinding basic = new BasicHttpBinding();
ChannelFactory<ServiceReference1.IService1Channel> fact = new ChannelFactory<ServiceReference1.IService1Channel>(basic, adr);
Label1.Text = fact.CreateChannel().GetData(8);
throw error:
Request for the permission of type "System.Net.WebPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089".
app.config webpart:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://127.0.0.1:81/Service1.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
name="BasicHttpBinding_IService1" />
</client>
</system.serviceModel>
</configuration>
web.config Azure WCF Service:
<?xml version="1.0"?>
<configuration>
<configSections>
</configSections>
<!-- To collect diagnostic traces, uncomment the section below or merge with existing system.diagnostics section.
To persist the traces to storage, update the DiagnosticsConnectionString setting with your storage credentials.
To avoid performance degradation, remember to disable tracing on production deployments.
<system.diagnostics>
<sharedListeners>
<add name="AzureLocalStorage" type="WCFServiceWebRole1.AzureLocalStorageTraceListener, WCFServiceWebRole1"/>
</sharedListeners>
<sources>
<source name="System.ServiceModel" switchValue="Verbose, ActivityTracing">
<listeners>
<add name="AzureLocalStorage"/>
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging" switchValue="Verbose">
<listeners>
<add name="AzureLocalStorage"/>
</listeners>
</source>
</sources>
</system.diagnostics> -->
<system.diagnostics>
<trace>
<listeners>
<add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
name="AzureDiagnostics">
<filter type="" />
</add>
</listeners>
</trace>
</system.diagnostics>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
P.S. When all moved to work deployment - Azure и Sharepoint Online - errors again. I create connection programmatically, because read, that in sandbox
solutions app.config not deployed with web part, we must duplicate his code in web.config Sharepoint 2010 - but in Sharepoint Online this file is closed from developers!
I have verified first that you sure can use SharePoint Designer 2010 to create an external content type that consumes and writes data to SQL Server, a Windows Communication Foundation (WCF) Service or a .NET type.
Next SharePoint BCS supports both SOAP and OData however WCF Data Services supports OData services, so to consume a WCF Data Service, you need OData base connectivity. Data view web parts can issue GET requests which works for OData feeds.
SharePoint Online Office 365 supports sandbox solutions which means .Net/C# code and solution deployed web parts are possible however I am not sure if connecting SP Web Parts is possible in the way that you describe because sandbox solutions don't support making outbound web calls.
Have you verified the last part?
You receive correct error from the SharePoint
Request for the permission of type "System.Net.WebPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089".
This is because Sandbox restrictions. You can see all permissions which are denied to the sandbox code from this MSDN article. And WebPermission along with SocketPermission which are dinied for code in sandbox solution.
If you want to access external services, does not matter using the TCP or HTTP protocol you should move to the full trust solutions.

IIS 7.5 What am I doing wrong?

In IIS 7.5 under Windows 7 Utilmate, I have an application which is configured for authentication as follows:
Anonymous & Windows
In the ASP.NET Website, I have turned Forms authentication and identity impersonate = true
I also deny any anonymous users.
<authentication mode="Forms">
</authentication>
<identity impersonate="true"/>
<authorization>
<deny user="?">
</authorization>
IIS complains. What am I doing wrong...
What I want to achieve :I want the windows Logged On User so I can build a FormsAuthentication ticket and pass it to a Passive STS.
So in IIS I have anonymous and windows...If have only windows ticked, I cannot go onto the Login.aspx page as I have an extra parameter to be passed from there.
So now in webconfig, I then disable anonymous users by saying deny user="?" , so it leaves me with the authenticated windows user but using Forms Authentication.You know what I mean??
http://msdn.microsoft.com/en-us/library/ff649264.aspx
If you see Table 4 IIS Integrated Windows for IIS then Web.config setting 3rd row, accordingly WindowsIdentity is Domian\Username .It works on IIS 6.0 win2003/IIS 5.1 under XP
If this is an application that leverages claims based identity, then the responsibility of authenticating users is in the STS itself, not in the app.
If you are configuring your (web) application to trust an external STS, then your authentication mode would be "None" and you'd have a whole section in the config file for "Microsoft.identityModel". You would then configure the STS address there (the issuer attribute). Something like this:
<microsoft.identityModel>
<service>
<audienceUris>
<add value="https://aexpense-dev.adatum.com/" />
</audienceUris>
<federatedAuthentication>
<wsFederation passiveRedirectEnabled="true" issuer="https://localhost/Adatum.SimulatedIssuer/" realm="https://aexpense-dev.adatum.com/" requireHttps="true" />
<cookieHandler requireSsl="false" />
</federatedAuthentication>
<serviceCertificate>
<certificateReference x509FindType="FindBySubjectDistinguishedName" findValue="CN=localhost"/>
</serviceCertificate>
<certificateValidation certificateValidationMode="None"/>
<applicationService>
<claimTypeRequired>
<claimType type="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" optional="true" />
</claimTypeRequired>
</applicationService>
<issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<trustedIssuers>
<add thumbprint="f260042d59e14937984c6183fbc6bfc71baf5462" name="https://localhost/Adatum.SimulatedIssuer/" />
</trustedIssuers>
</issuerNameRegistry>
</service>
The STS itself might use Forms authentication or something else, depending on the implementation.

SharePoint form-based authentication with custom database

I have SharePoint site and I want to use form-based authentication, not Windows how it is by default.
For this I read that I have to modify the web.config from Central Administration and web.config from my site with the membership and roleManager tags configured properly.
But if I use this:
<membership>
<providers>
<add name="MyProvider"
type="System.Web.Security.SqlMembershipProvider,
System.Web, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
.../>
</providers>
</membership>
System.Web.Security.SqlMembershipProvider requires a database generated with ASP.NET SQL Server Setup Wizard (aspnet_regsql.exe), and this is my problem!
I want to use another database with cunstom table 'Users' from where to take the username and password for authentication.
How can I do this?
Thank you in advance
If you have a custom database structure, then you will need to write a custom MembershipProvider. I suggest starting here on MSDN.

Resources