Authentication Parent Site Integration for CS2.0

This post has 3 Replies | 2 Followers

Top 500 Contributor
Posts 76
Points 795
JoelDKraft Posted: Mon, Feb 20 2006 6:25 PM
This is the CS2.0 version of my instructions to integrate CS into a site with existing forms-based authentication!

I have been able to get the following configuration to work:
  • Existing root site with ASP.NET forms authentication (How the user is actually authenticated is not important.  Ours is actually using our campus Central Authentication Service on another server.)
  • The existing forms authentication stores the username in the authentication ticket. This is the default behavior if you are using FormsAuthentication.RedirectFromLoginPage() or FormsAuthentication.GetRedirectUrl() to build the cookie.
  • Community Server 2.0 installed as an application subdirectory (this means that you cannot scatter the CS controls on other parts of your site)
In this solution, all all authentication is handled in the root application.  The root application also performs the work to automatically create or validate a CS user.

Step 1 - Specify Forms Authentication Keys
By default, ASP.NET is configured so that applications automatically generate a unique validationKey and decryption key which is used to secure things like cookies and viewstate. You will need to generate and specify the keys in the web.config of your root application. (I also have this in my CS application web.config file, but this may not be necessary because of settings inheritance.) This is outlined in an MSDN article. There is a knowledge article about how to generate the keys, and also a website that will do it, though I cannot find my bookmark for it right now.
<machineKey validationKey="XXXXX" decryptionKey="YYYYY" validation="SHA1" />
Step 2 - Update siteurls.config to Find Login Page
First, add a new location "auth" into the locations tag. The paths in these tags are relative to the root of the CS application, so notice that the path contains ".." to reach the root site. Then modify the "login", "login_clean" and "logout" entries in the urls section to refer to your specific login and logout page names. Notice that I also added "?ReturnURL=/CS/" to the end of the login_clean entry, so that a user will be redirected back to the CS application if no specific page was given.
<locations>
  <location name="auth" path="/../auth/" />
</locations>
<urls>
  <url name="login" location="auth"
       path="login.aspx?ReturnUrl={0}" />
  <url name="login_clean" location="auth"
       path="login.aspx?ReturnUrl=/CS/" />
  <url name="logout" location="auth" path="logout.aspx" />
</urls>
Step 3 - Modify login.aspx to Automatically Create CS Users
We created a custom stored procedure that we call to create a new CS user on every login. We didn't use the default behaviors so that we could set additional properties such as the names.  If the user already exists, this procedure also activates them as a visitor.
CREATE
PROCEDURE dbo.cs_Auto_Create_User
@UserID nvarchar(256),
@Email nvarchar(128),
@CommonName nvarchar(128)
AS
BEGIN
DECLARE @retval int
DECLARE @timezoneadj int
SET @timezoneadj = DATEDIFF(hh,GETUTCDATE(),GETDATE())

EXECUTE @retval = aspnet_Membership_GetUserByName
@ApplicationName = 'CS',
@UserName = @UserID,
@TimeZoneAdjustment = @timezoneadj,
@UpdateLastActivity = 1

IF (@retval = -1) BEGIN
DECLARE @newuserid uniqueidentifier
DECLARE @guid uniqueidentifier
DECLARE @csuserid int
SET @guid = NEWID()

EXECUTE @retval = aspnet_Membership_CreateUser
@ApplicationName = 'CS',
@UserName = @UserID,
@Password = @guid,
@PasswordSalt = 'XYZZY',
@Email = @Email,
@PasswordQuestion = NULL,
@PasswordAnswer = NULL,
@IsApproved = 1,
@TimeZoneAdjustment = @timezoneadj,
@UniqueEmail = 1,
@PasswordFormat = 0,
@UserId = @newuserid OUTPUT

EXECUTE @retval = aspnet_UsersInRoles_AddUsersToRoles
@ApplicationName = 'CS',
@UserNames = @UserID,
@RoleNames = 'Everyone,Registered Users',
@TimeZoneAdjustment = @timezoneadj

EXECUTE @retval = cs_user_CreateUpdateDelete
@cs_UserID = @csuserid OUTPUT,
@UserID = @newuserid,
@Action = 0, -- CREATE
@SettingsID = 1000, -- CS
@TimeZone = -5.0, -- EST
@ModerationLevel = 1, -- Not Moderated
@EnableThreadTracking = 1,
@EnableDisplayUnreadThreadsOnly = 1
END

EXECUTE aspnet_Profile_GetProperties
@ApplicationName = 'CS',
@UserName = @UserID,
@TimeZoneAdjustment = @timezoneadj

IF (@@ROWCOUNT = 0) BEGIN
DECLARE @pn varchar(1000), @pvs varchar(1000)
SET @pvs = '-5'+@CommonName
SET @pn = 'timezone:S:0:2:commonName:S:2:' + CAST(LEN(@CommonName) AS varchar(5))

EXECUTE aspnet_Profile_SetProperties
@ApplicationName = 'CS',
@PropertyNames = @pn,
@PropertyValuesString = @pvs,
@PropertyValuesBinary = '',
@UserName = @UserID,
@IsUserAnonymous = 0,
@TimeZoneAdjustment = @timezoneadj
END
END
Step 4 - Modify Skins
The last step is to modify the skins to remove options that you might not want displayed to your end users.  (I have not yet done this for CS2, but it shoudln't be a big deal!)  The things that you would want to delete are the option for a user to change their password.  We also take this opportunity to set fields (such as name and private email) that we don't want changed to read-only.  Finally, it would probably be a good idea to delete the /cs/login.aspx and /cs/login.aspx.

That should be it!
Joel

PS. If you build your own FormsAuthenticationTicket, you can still get this to work. If you only add optional userdata to the ticket, CS2.0 seems to still work okay.  (In 1.1, this didn't seem to work for me.) If you do something more drastic, then you can provide your own /cs/global.asax file and define FormsAuthentication_OnAuthenticate() to get what you need out of the ticket.
  • | Post Points: 35
Top 25 Contributor
Male
Posts 1,496
Points 102,955
CS Developers
rhoward replied on Tue, Feb 21 2006 6:37 AM

We’ve got an ASP.NET Forms authentication single sign-on module that enables this -- but only requires an entry in the communityserver.config file J

 


From: JoelDKraft [mailtoBig Smile [:D]iscussion@communityserver.org]
Sent: Monday, February 20, 2006 6:25 PM
To: Rob Howard
Subject: [CS.Discussions] Authentication Parent Site Integration for CS2.0

 

This is the CS2.0 version of my instructions to integrate CS into a site with existing forms-based authentication!

I have been able to get the following configuration to work:

  • Existing root site with ASP.NET forms authentication (How the user is actually authenticated is not important.  Ours is actually using our campus Central Authentication Service on another server.)
  • The existing forms authentication stores the username in the authentication ticket. This is the default behavior if you are using FormsAuthentication.RedirectFromLoginPage() or FormsAuthentication.GetRedirectUrl() to build the cookie.
  • Community Server 2.0 installed as an application subdirectory (this means that you cannot scatter the CS controls on other parts of your site)

In this solution, all all authentication is handled in the root application.  The root application also performs the work to automatically create or validate a CS user.

Step 1 - Specify Forms Authentication Keys
By default, ASP.NET is configured so that applications automatically generate a unique validationKey and decryption key which is used to secure things like cookies and viewstate. You will need to generate and specify the keys in the web.config of your root application. (I also have this in my CS application web.config file, but this may not be necessary because of settings inheritance.) This is outlined in an MSDN article. There is a knowledge article about how to generate the keys, and also a website that will do it, though I cannot find my bookmark for it right now.

<machineKey validationKey="XXXXX" decryptionKey="YYYYY" validation="SHA1" />

Step 2 - Update siteurls.config to Find Login Page
First, add a new location "auth" into the locations tag. The paths in these tags are relative to the root of the CS application, so notice that the path contains ".." to reach the root site. Then modify the "login", "login_clean" and "logout" entries in the urls section to refer to your specific login and logout page names. Notice that I also added "?ReturnURL=/CS/" to the end of the login_clean entry, so that a user will be redirected back to the CS application if no specific page was given.

<locations>
  <location name="auth" path="/../auth/" />
</locations>
<urls>
  <url name="login" location="auth"
       path="login.aspx?ReturnUrl={0}" />
  <url name="login_clean" location="auth"
       path="login.aspx?ReturnUrl=/CS/" />
  <url name="logout" location="auth" path="logout.aspx" />
</urls>

Step 3 - Modify login.aspx to Automatically Create CS Users
We created a custom stored procedure that we call to create a new CS user on every login. We didn't use the default behaviors so that we could set additional properties such as the names.  If the user already exists, this procedure also activates them as a visitor.

CREATE
PROCEDURE   dbo.cs_Auto_Create_User
    @UserID     nvarchar(256),
    @Email      nvarchar(128),
    @CommonName nvarchar(128)
AS
BEGIN
    DECLARE @retval int
    DECLARE @timezoneadj int
    SET @timezoneadj = DATEDIFF(hh,GETUTCDATE(),GETDATE())

    EXECUTE @retval = aspnet_Membership_GetUserByName
        @ApplicationName    = 'CS',
        @UserName           = @UserID,
        @TimeZoneAdjustment = @timezoneadj,
        @UpdateLastActivity = 1

    IF (@retval = -1) BEGIN
        DECLARE @newuserid uniqueidentifier
        DECLARE @guid uniqueidentifier
        DECLARE @csuserid int
        SET @guid = NEWID()

        EXECUTE @retval = aspnet_Membership_CreateUser
            @ApplicationName    = 'CS',
            @UserName           = @UserID,
            @Password           = @guid,
            @PasswordSalt       = 'XYZZY',
            @Email              = @Email,
            @PasswordQuestion   = NULL,
            @PasswordAnswer     = NULL,
            @IsApproved         = 1,
            @TimeZoneAdjustment = @timezoneadj,
            @UniqueEmail        = 1,
            @PasswordFormat     = 0,
            @UserId             = @newuserid OUTPUT

        EXECUTE @retval = aspnet_UsersInRoles_AddUsersToRoles
            @ApplicationName    = 'CS',
            @UserNames          = @UserID,
            @RoleNames          = 'Everyone,Registered Users',
            @TimeZoneAdjustment = @timezoneadj

        EXECUTE @retval = cs_user_CreateUpdateDelete
            @cs_UserID                          = @csuserid OUTPUT,
            @UserID                             = @newuserid,
            @Action                             = 0,        -- CREATE
            @SettingsID                         = 1000,     -- CS
            @TimeZone                           = -5.0,     -- EST
            @ModerationLevel                    = 1,        -- Not Moderated
            @EnableThreadTracking               = 1,
            @EnableDisplayUnreadThreadsOnly     = 1
    END

    EXECUTE aspnet_Profile_GetProperties
        @ApplicationName        = 'CS',
        @UserName               = @UserID,
        @TimeZoneAdjustment     = @timezoneadj

    IF  (@@ROWCOUNT = 0) BEGIN
        DECLARE @pn varchar(1000), @pvs varchar(1000)
        SET @pvs = '-5'+@CommonName
        SET @pn = 'timezone:S:0:2:commonName:S:2:' + CAST(LEN(@CommonName) AS varchar(5))

        EXECUTE aspnet_Profile_SetProperties
            @ApplicationName        = 'CS',
            @PropertyNames          = @pn,
            @PropertyValuesString   = @pvs,
            @PropertyValuesBinary   = '',
            @UserName               = @UserID,
            @IsUserAnonymous        = 0,
            @TimeZoneAdjustment     = @timezoneadj
    END
END

Step 4 - Modify Skins
The last step is to modify the skins to remove options that you might not want displayed to your end users.  (I have not yet done this for CS2, but it shoudln't be a big deal!)  The things that you would want to delete are the option for a user to change their password.  We also take this opportunity to set fields (such as name and private email) that we don't want changed to read-only.  Finally, it would probably be a good idea to delete the /cs/login.aspx and /cs/login.aspx.

That should be it!
Joel

PS. If you build your own FormsAuthenticationTicket, you can still get this to work. If you only add optional userdata to the ticket, CS2.0 seems to still work okay.  (In 1.1, this didn't seem to work for me.) If you do something more drastic, then you can provide your own /cs/global.asax file and define FormsAuthentication_OnAuthenticate() to get what you need out of the ticket.


Thanks, Rob
  • | Post Points: 20
Top 500 Contributor
Posts 76
Points 795
rhoward:

We’ve got an ASP.NET Forms authentication single sign-on module that enables this -- but only requires an entry in the communityserver.config file J



Yeah, well some of us are still trying to scrimp up enough money for the standard edition before the price goes up!!  Smile [:)]

Does the module really do everything there?  I would assume you'd still have to do the web.config stuff at least!
  • | Post Points: 5
Top 500 Contributor
Posts 97
Points 280
runboy27 replied on Sat, May 20 2006 8:06 PM

Hi JoelDKraft

I have a site that is mostly written in ASP3.0 where users are loging in to get access. I would like to create the users in the CS database when they are created in the ASP3.0 system.

It looks to me like I can just call your SP (Maybe slightly modified so I pass the password also) from within ASP3.0 in order to create the users or am I missing something?

What are you passing in the @CommonName variable?

  • | Post Points: 5
Page 1 of 1 (4 items) | RSS
Powered by Community Server (Commercial Edition), by Telligent Systems

Copyright© 2008 Telligent Systems Inc. All rights reserved
CommunityServer.com  •  Telligent.com