My companion organization already had ADFS setup. My purpose was to have the partner organization authenticate the user after which have DNN automatically recognize the user, not obtaining to enter any far more credentials. From there we wanted to manage the groups and permissions by way of the standard DNN portal.
I was initially beneath the misconception that I couldn't make use of the present DNNMembershipProvider and I'd have to generate a whole new Authentication Provider and gather the credentials and pass them to my partner organization.

What I have figured out is that you can use the existing DNNMembership provider, but you've got to make the user ahead of the request gets towards the DNNMembership provider making use of the info offered by ADFS.

Note: This approach is really a straight pass-through from ADFS to DNN. No measures are taken to authenticate the user or to check any from the inputs from ADFS.

As an aside, this method performs not just with ADFS but in addition any other external 3rd-party Authentication approach that sends user info in headers or cookies. Change the context_AuthenticateRequest approach to suit your requirements.

Right here are the pre-conditions to this article. I expect:

  • Your partner organization has ADFS up and running
  • You have your ADFS proxy up and running and it talks to the partner organization.
  • ADFS Web Agent is installed on the server you are running.

Let’s get begin.

HTTPModule

What you've to complete is produce an HTTPModule that will intercept the AuthorizeRequest events ahead of DNN does. An over-simplified definition of an HTTPModule is, it is a piece of code that runs ahead of any web page gets hit. You can listen for a large amount of distinct events. For much more data, click right here.

To make the HTTPModule you'll need to:

  • Open Visual Studio and produce a brand new class library.
  • Generate a brand new class and copy the code attached to this blog.
  • Add References to the following DLLs
    • DotNetNuke
    • System.Web
    • System.Web.Security.SingleSignOn
    • System.Web.Security.SingleSignOn.ClaimsTransform
    • System.Web.Security.SingleSignOn.Permissions
  • Compile the solution
  • The DLL that is created will need to be placed in the bin directory of your website.
  • Make changes to your web.config (explained in a later section).

I will walk through a bit of the code. Here is the first snippet of code. We start listening for the AuthenticateRequest event. All other events pass through untouched.

public void Init(HttpApplication context)
{
//Start listening for each authentication request
context.AuthenticateRequest += new EventHandler(context_AuthenticateRequest);
}

Now, what do we do when this event is fired off? To shorten the namespace I added the statement

using SSO = System.Web.Security.SingleSignOn;

First off, we need to get the information that ADFS has sent us by casting the User.Identity into the ADFS object SingleSignOnIdentity.

public void context_AuthenticateRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
//By the time the request gets to here, it should have been authenticated
//against ADFS.
SSO.SingleSignOnIdentity id = (SSO.SingleSignOnIdentity)app.User.Identity;

At this point you will have access to the user’s Identity and any claims coming from the ADFS server. You can access them through id.SecurityPropertyCollection. You can use them to populate the new user account. You can iterate through the claims with the following code

foreach(SecurityProperty sp in id.SecurityPropertyCollection)
{
    Console.WriteLine(sp.Name);
    Console.WriteLine(sp.Value);
}

Subsequent, we check to determine in the event the use currently exists within the database by utilizing the DNN API function GetUserByName. If it doesn’t, then the user is created by the common DNN API function CreateUser and logged in. If the user does exist currently then we log them in automatically. The user will automatically be added to the Registered Users and Subscribers security groups.

//'See if user exists in DNN Portal user DB
UserInfo objUserInfo = UserController.GetUserByName(currentPortal.PortalId, id.Name);
//' user does exist - try to create on the fly
if (objUserInfo == null)
{
    objUserInfo = new UserInfo();
    objUserInfo.DisplayName = id.Name;
    objUserInfo.FirstName = id.Name;
    objUserInfo.LastName = id.Name;
    objUserInfo.Username = id.Name;
    objUserInfo.Membership.Password = "AReallyStrongPassword";
    objUserInfo.PortalID = currentPortal.PortalId;
    objUserInfo.Email = id.Name;
    UserCreateStatus objUserCreateStatus = UserController.CreateUser(ref objUserInfo);
    //See if the user was added successfully
    if (objUserCreateStatus == UserCreateStatus.Success)
    {
        //We have created them successfully, so let them into the site
        LetsLogUserIn(objUserInfo);
    }
    else
    {
        //This will send the error to the error log, but the user will experience an infinite loop
        throw new Exception("User not created successfully: " + objUserInfo.Username + "- " +         objUserCreateStatus.ToString());
}

Here is the LetsLogUserIn function:

private void LetsLogUserIn(UserInfo objUserInfo)
{
    try
    {
    //Get the current portal
    PortalSettings currentPortal = PortalController.GetCurrentPortalSettings();
    //set the language to the default language of the portal
    Localization.SetLanguage(currentPortal.DefaultLanguage);
    //Log the user in
        UserController.UserLogin(currentPortal.PortalId,
            objUserInfo,
            currentPortal.PortalName,
            HttpContext.Current.Request.UserHostAddress,
            false);
    }
    catch(Exception ex)
    {
        Exceptions.LogException(ex);
    }
}

Web.Config

We need to make several changes to the web.config. First we need to make the changes necessary for ADFS and then we need to make changes for our HTTPModule.

The ADFS changes are the standard web.config changes you would do for any ADFS claims-aware site. You first need to add the section groups to your web.config.

<sectionGroup name="system.web">
    <section name="websso" type="System.Web.Security.SingleSignOn.WebSsoConfigurationHandler,                                  System.Web.Security.SingleSignOn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null" />
</sectionGroup>

Then you need to add the actual section. The <returnurl> needs to be EXACTLY what is put into ADFS. Remember, this URL needs to have a / at the end to prevent ADFS from posting to a directory listing. The <fs> element needs to be changed to reflect the name of your server.

<system.web>

    <websso>
        <authenticationrequired />
        <auditlevel>55</auditlevel>
        <urls>
            <returnurl>https://your_application/</returnurl>
        </urls>
        <fs>https://fs-server/adfs/fs/federationserverservice.asmx</fs>
    </websso>

</system.web>

If you would like to have logging (and who doesn’t like loggingJ) you will need to add the following section at the end of your web.config

<configuration>

<system.diagnostics>
     <switches>
       <!-- enables full debug logging -->
       <add name="WebSsoDebugLevel" value="255" />
     </switches>
     <trace autoflush="true" indentsize="3">
       <listeners>
         <!-- either create a c:\logs directory and grant Network Service permission to write to it, or remove this listener -->
         <add name="MyListener"
              type="System.Web.Security.SingleSignOn.BoundedSizeLogFileTraceListener, System.Web.Security.SingleSignOn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null"
              initializeData="c:\logs\webagent.log" />
       </listeners>
     </trace>
   </system.diagnostics>
</configuration>

Ultimately, you need to add the HTTPModules for ADFS and our HTTPModule. Order matters a good deal for the HTTPModules. We require the ADFS Web Agent to become listed first, to ensure that any request will likely be redirected to our partner’s logon screen. Right away following the Web Agent should be our HTTPModule. This will make sure that we'll automatically log them on just before DNN even see it.

<system.web>
<httpModules>
    <add name="Identity Federation Services Application Authentication Module"                       type="System.Web.Security.SingleSignOn.WebSsoAuthenticationModule, System.Web.Security.SingleSignOn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null" />
 
    <add name="HTTP_Module_Test" type="HTTP_Module_Test.SSO_Module, HTTP_Module_Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>

There you have it Hope it helps someone.

Best DotNetNuke Hosting Recommendation

ASPHostPortal.com provides its customers with Plesk Panel, one of the most popular and stable control panels for Windows hosting, as free. You could also see the latest .NET framework, a crazy amount of functionality as well as Large disk space, bandwidth, MSSQL databases and more. All those give people the convenience to build up a powerful site in Windows server. ASPHostPortal.com offers DotNetNuke hosting starts from $5/month only. We also guarantees 30 days money back and guarantee 99.9% uptime. If you need a reliable affordable DotNetNuke Hosting, we should be your best choice.

Save