Tuesday, October 2, 2012

How to change the customer / partner portal V2 to authenticate against the MSCRM only.


How to change the customer / partner portal V2 to authenticate against the MSCRM only.

There is a new portal and the changes are Little bit different than it was in the previous version
Customer portal V1 changes can be found here

Walkthrough:

In order to do it you'll need to download the portal and follow the installation steps, avoid all the stuff regarding the LiveID.
After you've imported the solution and the website data we are ready to go.
1)      Open the website in visual studio.
2)      Edit he web.config.
a.                 Remove
                a.1)
 <add name="Live" connectionString="Application Id=0000000000000000; Secret=00000000000000000000000000000000"/>

 a.2)
 <add key="FederationMetadataLocation" value="https://contoso.accesscontrol.windows.net/FederationMetadata/2007-06/FederationMetadata.xml"/>

                        a.3)
 <membership defaultProvider="CrmMembershipProvider">
                                        <providers>
                                                        <add name="CrmMembershipProvider" type="Microsoft.Xrm.Portal.Web.Security.LiveIdMembershipProvider, Microsoft.Xrm.Portal" liveIdConnectionStringName="Live"/>
                                        </providers>
                                        </membership>

                        a.4) 
<httpRuntime maxRequestLength="102400" requestValidationMode="2.0" requestValidationType="Microsoft.Xrm.Portal.IdentityModel.Web.FederationRequestValidator, Microsoft.Xrm.Portal"/>

                        a.5)
 <add name="LiveId" verb="*" path="LiveID.axd" preCondition="integratedMode" type="Microsoft.Xrm.Portal.IdentityModel.Web.Handlers.LiveIdAccountTransferHandler, Microsoft.Xrm.Portal"/>
                                        <add name="Federation" verb="*" path="Federation.axd" preCondition="integratedMode" type="Microsoft.Xrm.Portal.IdentityModel.Web.Handlers.FederationAuthenticationHandler, Microsoft.Xrm.Portal"/>


a.6) 
<microsoft.identityModel>
<service>
                                        <audienceUris>
                                                        <add value="http://contoso.cloudapp.net/"/>
                                        </audienceUris>
                                        <federatedAuthentication>
                                                        <wsFederation passiveRedirectEnabled="false" issuer="https://contoso.accesscontrol.windows.net/v2/wsfederation" realm="http://contoso.cloudapp.net/" requireHttps="false"/>
                                                        <cookieHandler requireSsl="false"/>
                                        </federatedAuthentication>
                                        <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
                                                        <trustedIssuers>
                                                                        <add thumbprint="0000000000000000000000000000000000000000" name="https://contoso.accesscontrol.windows.net/"/>
                                                        </trustedIssuers>
                                        </issuerNameRegistry>
                        </service>
        </microsoft.identityModel>
        <microsoft.xrm.portal.identityModel>
                        <registration enabled="true" registrationPath="~/confirm-invite" profilePath="~/profile" accountTransferPath="~/login" requiresInvitation="true"
                                        requiresChallengeAnswer="false" requiresConfirmation="false" invitationCodeDuration="01:00:00"/>
        </microsoft.xrm.portal.identityModel>

b.         Replace the Authentication tag to as follow
<authentication mode="Forms">
<forms loginUrl="/login" timeout="525600"     defaultUrl="/"  />
 </authentication>

3)      Edit \Pages\Login.aspx
a.         Remove                
a.1)
<%@ Register TagPrefix="adx" TagName="AzureAcs" Src="~/Controls/AzureAcs.ascx" %>

a.2)
<adx:AzureAcs runat="server" />

a.3)
<crm:Snippet runat="server" SnippetName="Login/ACS/AccountTransfer/Heading" DefaultText="Live ID Account Transfer" />

a.4)
<p>Already registered with a Windows Live ID account? Sign in to transfer the account to an AppFabric ACS account:</p>

b.         Replace
<crm:LiveIdLoginStatus ID="TransferLiveIdLink" runat="server" LoginImageUrl="https://www.passportimages.com/1033/signin.gif"
LogoutImageUrl="https://www.passportimages.com/1033/signout.gif" />
With
  <asp:Login ID="Login1" runat="server" OnAuthenticate="Login1_Authenticate"></asp:Login>

5)   Edit \Pages\Login.aspx.cs
a.                Add to using
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Crm.Sdk;
using Microsoft.Xrm.Client.Services;
using Microsoft.Xrm.Client;
using Xrm;
using System.Web.Security;

b.                Replace Page_Load
protected void Page_Load(object sender, EventArgs e)
        {
            if ((User != null) && User.Identity.IsAuthenticated)
            {
                var redirectUrl = !string.IsNullOrEmpty(Request.QueryString["ReturnUrl"]) ? Request["ReturnUrl"]: !string.IsNullOrEmpty(Request.QueryString["URL"])? Request["URL"]: "/";
                Response.Redirect(redirectUrl);
            }
        }
c.                 Add
        private Contact _loginContact;

        protected Contact LoginContact
        {
            get
            {
                return _loginContact ?? (_loginContact = XrmContext.ContactSet.FirstOrDefault(c => c.Adx_username == Login1.UserName && c.Adx_LogonEnabled != null && c.Adx_LogonEnabled.Value));
            }
        }

        protected void Login1_Authenticate(object sender, System.Web.UI.WebControls.AuthenticateEventArgs e)
        {
            if (LoginContact == null)
            {
                e.Authenticated = false;
            }
            else
            {
                if (LoginContact.Adx_password == Login1.Password)
                {
                if (LoginContact.Adx_changepasswordatnextlogon != null && LoginContact.Adx_changepasswordatnextlogon.Value)
                    {
                        //var page = ServiceContext.GetPageBySiteMarkerName(Website, "ChangePassword");
                        //string redirectURL = ServiceContext.GetUrl(page) + "?UserName=" + Server.UrlEncode(Login1.UserName) + "&Password=" + Server.UrlEncode(Login1.Password);
                        //Response.Redirect(redirectURL);
                    }
                    else
                    {
                        LoginContact.Adx_LastSuccessfulLogon = DateTime.Now.Date;
                        XrmContext.UpdateObject(LoginContact);
                        XrmContext.SaveChanges();
                        e.Authenticated = true;
                        // Response.Redirect("/");
                        FormsAuthentication.RedirectFromLoginPage(Login1.UserName, true);
                    }
                }
                else
                {
                    e.Authenticated = false;
                }
            }
        }

Compile, Debug and Publish to the IIS.

Download changed portal:

17 comments:

  1. Hi,

    Your code is very helpful! Thanks for posting it. I have installed the portal and followed the steps in your blog. However, I am stuck on one thing. I have two errors in my solution after following the steps above. Both errors read the same so I will just post once:

    'ASP.pages_login_aspx' does not contain a definition for 'Login1_Authenticate' and no extension method 'Login1_Authenticate' accepting a first argument of type 'ASP.pages_login_aspx' could be found (are you missing a using directive or an assembly reference?) C:\CRM 2011 Websites\PartnerPortal\Pages\Login.aspx 6

    Do you have any idea how I could fix this error?

    Thank you so much!
    Holly Myers
    hmyers@moog.com

    ReplyDelete
  2. Thanks you,
    I think you are missing step 5c, because the error is about not having the function Login1_Authenticate.

    Hope it helps.

    ReplyDelete
    Replies
    1. One of my co-workers figured out that I should be opening the project as a project/solution in Visual Studio. I was opening it as a web site. This error is now gone. Thank you for your help!

      Delete
  3. Hi yairrose. What configurations i have to make in contacts to login? i already fill login name, logon enable and system user and still can´t log in.

    thanks !

    ReplyDelete
    Replies
    1. Hi,
      Besides setting Login, Password, Logon enable and system user, the contact should have Web Roles to the website, Customer/Partner.

      Delete
    2. Hi,

      thanks, some fields aren´t in form.

      Delete
    3. i am also having this issue, there is no password field.

      Any help would be thankful
      Regards Jarrad
      jarrad@virtualtech.net.au

      Delete
    4. ok i rolled back to a older portal solution and the missing password field came up, but i am still unable to log in.

      Delete
    5. use the newest portal solution, but edit the form and add the password field. then fill in the password field and it should work

      Delete
  4. Has anyone managed to get the portal to work with the latest available portal download and the latest SDK. it appears to have changed, or i'm missing something as even with the changed portal download above there are many errors.

    ReplyDelete
  5. Hi,
    i've the same problem like Holly.
    But i've done the step 5c and also tried to open the project in visual studio and i still have the error:
    ASP.pages_login_aspx' does not contain a definition for 'Login1_Authenticate' and no extension method 'Login1_Authenticate' accepting a first argument of type 'ASP.pages_login_aspx' could be found (are you missing a using directive or an assembly reference?) C:\CRM 2011 Websites\PartnerPortal\Pages\Login.aspx 6

    ReplyDelete
    Replies
    1. I solved my problem above, but now I've a new problem.
      I have no password field in the "web authentication" entity.

      Delete
    2. Hi,

      Were you able to resolve the 'no password field'?

      Delete
  6. login works fine. but doesn't log me out! what am i missed here!?

    ReplyDelete
  7. it doesn't seem to work - var fam = new CrmFederationAuthenticationModule(Context);
    fam.SignOut(false);

    Response.Redirect(Request.RawUrl);

    ReplyDelete
  8. ID4281: Cannot create a WindowsClaimsIdentity from an anonymous WindowsIdentity. (IIS server us throwing this error)

    also logoff function is not working.

    ReplyDelete