Single Sign On with WCF and Asp.NET Custom Membership Provider


I recently was involved in designing enterprise software which contained several ASP.NET web sites and desktop applications. Since same users would use this software system a single-sign-on feature was necessary. Thus I took advantage of Microsoft Identity Foundation which is based on Claim Based Authentication. Also as the applications would be used by internal users, I used Active Directory Federation for authenticating users against an existing Active Directory.

Later I though what would be the solution if Claim Based Authentication did not fit in the solution? So I decided to design and implement a simple single-sign-on (SSO) authentication with WCF. This SSO has the following specifications:

  • Only performs Authentication. It does not contain any role management capability. The reason is that roles and access rights are defined in the scope of each application (or sub-system) so it is left to be done by applications.
  • It is based on Web Services so it can be consumed any technology that understands Web Services (e.g. Java apps.)
  • It can support many kind of user storage, such as Active Directory, ASP.NET Application Services (ASPNETDB) , Custom Authentication etc.
  • It can be used by Web, Desktop and Mobile applications.

Figure 1, Components of SSO

As seen in figure 1, user information can be retrieved from Active Directory, ASP.NET Application Services, Custom Database or 3rd Party Web Services. Components that encapsulate the details of each user storage or services are called Federations. This term is used by Microsoft in Windows Identity Foundation so we keep using that!

The Single Sign-On Service relies on Federation Services. Each federation service is simply a .NET Class Library that contains a class which implements an interface which is common between itself and SSO service. A federation module is plugged into SSO service via a configuration file. The Visual Studio solution that is downloadable at the bottom of this post includes a custom federation module that uses SQL Server to store the user information.

Client applications can consume the Web Service directly to perform sign-in, sign-out, authentication and other related operations. However, this solution includes a custom ASP.NET membership provider which allows ASP.NET applications consume SSO with no hassle. It also enables the existing ASP.NET applications to use this SSO service with a small configuration change.

Figure 2, Package diagram of SSO

Classes and Interfaces

The key classes and interfaces are as below:

  • ISSOFederation Interface: is implemented by Federation classes.
  • AuthenticatedUser: Is used by the federation classes and SSO service to represent a user. This type is also emitted by the service to the clients.

Figure 3, Key types of Common package

  • CustomFederation: Implements ISSOFederation and encapsulates the details of authentication and user storage.
  • SSOFederationHelper (SignInServices package): Provides a service to load the nominated federation service. Only one instance of the federation object exists (Singleton) so to plug another federation module the service must be restarted (e.g. restart the ISS web site).

Figure 4, SSOFederationHelper class

A federation object is plugged to the service using reflection. To do so, first the Fully Qualified Name of the federation type is placed in the Web.Config file:

<appSettings>

<add
key=federationType
value=SignInServices.CustomFederation.SSOCustomFederation,SignInServices.CustomFederation/>

</appSettings>

 

 

This type is instanciated by reflection and provided to the consumers by SSOFederationHelper.FederationObject property. For example:

 

public
List<AuthenticatedUser>
FindUsersByEmail(string
EmailAddress)

{


return
SSOFederationHelper.FederationObject
.FindUsersByEmail(EmailAddress).ToList();

}

 

  • SSOMembershipProvider (SSOClientServices package) is also a custom Asp.net membership provider. This class enables the ASP.NET applications take advantage of the SSOService without being dependent on it. The key point here is that all the ASP.NET applications that take advantage of SSO service must give a same name to the Asp.net membership cookie. Example:

<authentication
mode=Forms >

<forms
loginUrl=~/Account/Login.aspx
timeout=2880” name=.SSOV1Auth />

</authentication>

<authorization>

 

The custom membership provider has a proprietary app.config file. This configuration file includes the WCF client configuration (e.g. binding configuration). However, the URI of the service is configured in the Web.config file of the ASP.NET client. For example, an ASP.NET client configures the membership providers as below:

<membership
defaultProvider=SSOMembershipProvider>

<providers>

<clear/>

<add
name=SSOMembershipProvider
type=SSOClientServices.SSOMembershipProvider,SSOClientServices


endPointUri=http://localhost/SSO/service/sso.svc


enablePasswordRetrieval=false
enablePasswordReset=true
requiresQuestionAndAnswer=false
requiresUniqueEmail=false

/>

</providers>

</membership>

 

The value of endPointUri entry will be used to configure the service proxy.

 

The Visual Studio solution

The source code provided here has been developed using Visual Studio 2010 and requires the following components be installed:

  1. Visual Studio 2010 Express Edition
  2. Entity Framework 4.0
  3. WCF
  4. C# 4.0
  5. IIS 7
  6. SQL Server 2008 or 2008 Express

The following Visual Studio (C#) projects are included:

  1. SignInServices.Common: Includes common types
  2. SignInServices.CustomFederation: Is a sample Federation provider
  3. SignInServices: The Single Sign On WCF Service
  4. SSOClientServices: Includes a custom ASP.NET membership provider
  5. TestWebSite: An ASP.NET web site to test the SSO

How to download the source code?

The source code has been uploaded to CodePlex. Please go to http://wcfsso.codeplex.com and download the latest change set.

 

How to deploy?

In order to deploy the solution take the following actions:

  1. Restore the SQL Server 2008 Database in a SQL Server 2008 Server under the name of Framework
  2. Create a Windows login in SQL Server 2008 and grant access to the restored database (e.g. Domain\SSOUser).
  3. Launch IIS
  4. Create an application pool that works with .NET 4 and uses “Integrated” mode. Name this Application Pool as SSO.
  5. Set the identity account of the newly created application pool. This account must be equal to the Windows account that you added to SQL Server (e.g. Domain\SSOUser). This is required because the existing custom federation project is using Windows Authentication to access database.
  6. Open the solution file in Visual Studio 2010
  7. Publish SignInServices application to a folder
  8. Go to the folder
  9. Open web.config file and configure the following entries:
    1. Under <appSettings> set SessionTimeOutMinutes. This value indicates that how long a sign-in ticket is valid.
    2. Under <appSettings> set federationType to any other federation type that you may want to use. If you want to use the custom federation type shipped with this sample, leave the current value as is.
    3. Under <connectionStrings> update the connection strings either if you have restored the database under any name other than “Framework” or you want to use SQL Server authentication rather Windows authentication.
  10. Build SignInService.CustomFederation project and copy the .DLL file to the \BIN folder of SignInService
  11. Build SSOClientServices project and copy the .DLL file to the \BIN folder of SignInService
  12. Go back to IIS
  13. Under IIS create a new Web Application that uses SSO as its Application Pool and points to the folder to which you published the SignInService application.
  14. Publish TestWebSite to IIS or simply run it in VS 2010.

 

Configuring the custom federation

The custom federation uses SMTP to send a new password to users once a password is requested to reset. The configuration of SMTP server is in Web.Config file of the WCF application (SignInSerivice). You must configure SMTP in order to reset passwords.

<system.net>

<mailSettings>

<smtp
deliveryMethod=Network
from=name@domain.com>

<network
host=smtp.mail.com
userName=name@domain.com
password=password of sender
port=25 />

</smtp>

</mailSettings>

</system.net>

 

Important notice: The solution file uses a custom database to store the user information. To add new users, simply install the SignInService under IIS and then navigate to http://service-url/Admin/ManageUsers.aspx for example if the SSO WCF service is deployed to http://127.0.0.1 /SSO/SSO.SVC, you may access the user management page via http://127.0.0.1/SSO/SSO.SVC/Admin/ManageUsers.aspx

(the admin page must be completed as I focused on developing the SSO service rather than implementing the admin web site)

Important notice: None of the applications or the WCF service is protected for simplicity purposes. If you deploy this solution to a production environment, you must protect them using ASP.NET authentication or WCF security practices.

Important notice: Once you launch the TestWebSite, you’ll see a login screen. Enter the following default credential to enter:

User: aref.karimi

Password: 123

 

 

Advertisements

38 thoughts on “Single Sign On with WCF and Asp.NET Custom Membership Provider

    • Aref Karimi says:

      Hi Elham
      Please wait for a short time until the CodePlex project is activated (source code is hosted by codeplex.com)

    • Aref Karimi says:

      sorry for the late reply. to use with Active directory you can write a Federation class and authenticate uses against active directory. Active Directory functionality is encapsulated in System.NET.

  1. Aref says:

    Hi Gopal
    I believe that roles are defined within the scope of one system/application. That’s why I did not include it in this article. However if you look at the documentation of Claim Based Authentication, it will help you to implement access right management.

  2. Diego says:

    You say that all the ASP.NET applications that take advantage of SSO service must give a same name to the Asp.net membership cookie. I want to know if they must also be in the same domain?

    • Aref says:

      Seems that I have not expressed myself properly. I said if you give same cookine name to your ASP.NET applications (as well as same application name), they will use same ticket for authentication so you will have a kind of SSO! It’s not a robust way but is very simple to implement.
      If you use the approach that I’ve mentioned, and also use a provider such as the one that I’ve provided, the applications will all use the same web service so they will work in a SSO fashion

  3. Venkata says:

    I can not restore Framework.bak on to SQL Server 2008 R2 edition.

    I am getting the following error.

    TITLE: Microsoft SQL Server Management Studio
    ———————————————————

    An exception occurred while executing a Transact-SQL statement or batch. (Microsoft.SqlServer.ConnectionInfo)

    ——————————
    ADDITIONAL INFORMATION:

    The media family on device ‘D:\Framework.bak’ is incorrectly formed. SQL Server cannot process this media family.
    RESTORE HEADERONLY is terminating abnormally. (Microsoft SQL Server, Error: 3241)

  4. Venkata says:

    Thanks for the nice work. I got the database, since I am getting an error to restore from .bak file included, I generated from model to db and able to run the code successfully.

  5. shekhar parate says:

    Good article. I have some confusion about installting steps 7,8 and 13,14. It will be helpful if you explain or give more details steps for above steps.

  6. Rex says:

    Correct me if I’m wrong, but isn’t federation defined as the ability to authenticate over multiple indentity providers *at the same time*? I don’t see how your solution does that.

    • Aref says:

      It’s not hard to implement. We can configure a list of provides in the app.config (or web.config) and go through them. The first one that accepts the credentials will be the token issuer.

  7. Just a query. Isn’t it the service that is responsible for identifying which membership provider to use for authenticating the user/client . And the providers in this case would be Active Directory , Federation services etc.

    Thanks

  8. Shibin says:

    Thanks for the great sample..
    I am getting an error when running test application.

    Value cannot be null.
    Parameter name: type

    Type loadedType = Type.GetType(typeName);

    loadedType is null

  9. Good post. I learn something totally new and challenging on blogs I stumbleupon every day.
    It will always be helpful to read through content from other authors and use something from
    other websites.

  10. Hello, Neat post. There is an issue together with your website in internet explorer, would test this?
    IE still is the marketplace chief and a large part of folks will omit
    your wonderful writing due to this problem.

  11. VD says:

    Hi,
    You said that an existing ASP.Net application can directly consume the service withouth any membership provider with small config change. Can you please explain how can that be acheived?

  12. Ranjit says:

    Hi,
    I like your example, I am planning to create Claim Aware WCF Service to use ADFS2.0. Could you please suggest how to implement using the example above?

  13. Amit says:

    Nice work, thanks. But there are a concerns that I have with your solution:

    1) The SSO is working inside same browser tabs. If I open two separate Internet Explorer windows the SSO fails to identify the logged in user.

    As per SSO participating sites should recognize the logged in user in same browser no matter how it is open (i.e. same window or multiple windows)

    2) In your solution, how are the sites identifying which user is logged in. I am unable to locate that code. I mean to say suppose I have logged in to Site A with X user, how is Site B able to recognize the X user?

  14. I’ve learn several good stuff here. Certainly value bookmarking for revisiting.

    I wonder how a lot attempt you put to create
    the sort of fantastic informative web site.

  15. По данным официальной статистической отчетности заработок основной массы наших сограждан близок к минимальному или все они вовсе работают без оформления. Отсутствие записей в трудовой книжке – это выслуга лет, какой не будет учитываться при назначении пенсии. В таких обстоятельствах претендовать на занятие оптимально оплачиваемой должности либо приобретения стандартного заработка по окончании трудовой активности нереально.
    Оформление потребительского или автокредита возможно при существовании справки 2-НДФЛ. Официальный заработок, вписанный в бумаге, его откровенно будет мало для получения займа. Работодатель не будет подвергать себя риску и не укажет в действительности выплачиваемый доход. Обозначенные повыше проблемы имеют приемлемое разрешение, и состоит оно в приобретении требуемых документов, оформленных в соответствии с действующим законодательством.

    купить трудовую книжку

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s