I googled and found following article that described how to solve the same issue for CRM 4.0 that was written by MVP fellow Dylan Haskins (thanks a lot, I owe you a beer). Here are steps to replace LiveId authentication with Forms authentication (I assume that you’ve already configured Customer Portal):
1. Open web.config file and find following text:
<authentication mode="None"/>
<authentication mode="Forms"> <forms name=".ASPXAUTH" loginUrl="login" defaultUrl="default.aspx" protection="All" timeout="30" path="/" requireSSL="false" slidingExpiration="true" cookieless="UseDeviceProfile" domain="" enableCrossAppRedirects="false"> </forms> </authentication>
<%@ Page Language="C#" MasterPageFile="~/MasterPages/Default.master" AutoEventWireup="True" CodeBehind="Login.aspx.cs" Inherits="Site.Pages.Login" %> <asp:Content ID="Content1" ContentPlaceHolderID="ContentBottom" runat="server"> <asp:Login ID="Login1" runat="server" onauthenticate="Login1_Authenticate"> </asp:Login> </asp:Content>
using System; using System.Web.Security; using Xrm; using System.Linq; using Microsoft.Xrm.Portal; using Microsoft.Xrm.Portal.Configuration; using Microsoft.Xrm.Portal.Access; using Microsoft.Xrm.Portal.Cms; using Microsoft.Xrm.Portal.Core; namespace Site.Pages { public partial class Login : PortalPage { private Contact _loginContact; protected Contact LoginContact { get { if (_loginContact != null) { return _loginContact; } _loginContact = XrmContext.ContactSet .FirstOrDefault(c => c.Adx_username == Login1.UserName && (c.Adx_password == Login1.Password)); XrmContext.Detach(_loginContact); return _loginContact; } } protected void Page_Load(object sender, EventArgs e) { if ((User != null && User.Identity != null) && User.Identity.IsAuthenticated) { var redirectUrl = !string.IsNullOrEmpty(Request.QueryString["ReturnUrl"]) ? Request["ReturnUrl"] : !string.IsNullOrEmpty(Request.QueryString["URL"]) ? Request["URL"] : "/"; Response.Redirect(redirectUrl); } } protected void Login1_Authenticate(object sender, System.Web.UI.WebControls.AuthenticateEventArgs e) { if (LoginContact == null) { e.Authenticated = false; } else { if (LoginContact.Adx_username == Login1.UserName) { if (LoginContact.Adx_changepasswordatnextlogon.Value) { var portal = PortalCrmConfigurationManager.CreatePortalContext(); var website = (Adx_website)portal.Website; var page = (Adx_webpage)portal.ServiceContext.GetPageBySiteMarkerName(portal.Website, "ChangePassword"); string redirectURL = page.Adx_PartialUrl + "?UserName=" + Server.UrlEncode(Login1.UserName) + "&Password=" + Server.UrlEncode(Login1.Password); Response.Redirect(redirectURL); } else { LoginContact.Adx_LastSuccessfulLogon = DateTime.Now; XrmContext.Attach(LoginContact); XrmContext.UpdateObject(LoginContact); XrmContext.SaveChanges(); XrmContext.Detach(LoginContact); e.Authenticated = true; FormsAuthentication.RedirectFromLoginPage(Login1.UserName, true); } } else { e.Authenticated = false; } } } } }
using System; using System.Linq; using Microsoft.Xrm.Portal.Access; using Microsoft.Xrm.Portal.Cms; using Microsoft.Xrm.Portal.Core; using Microsoft.Xrm.Portal.Web; using Xrm; using System.Web.UI.WebControls; using Site.Library; using System.Web.Security; using Microsoft.Xrm.Portal.Configuration; namespace Site.Pages { public partial class Logout : PortalPage { protected void Page_Load(object sender, EventArgs e) { FormsAuthentication.SignOut(); var portal = PortalCrmConfigurationManager.CreatePortalContext(); var website = (Adx_website)portal.Website; var page = (Adx_webpage)portal.ServiceContext.GetPageBySiteMarkerName(portal.Website, "Home"); Response.Redirect(page.Adx_PartialUrl); } } }
<asp:LinkButton ID="LogoutLink" runat="server" Text='<%$ Snippet: links/logout, Logout %>' OnClick="LogoutLink_Click"/>
<asp:HyperLink ID="LogoutLink" runat="server" Text='<%$ Snippet: links/logout, Logout %>' NavigateUrl="/Pages/logout.aspx"/>
7. For test purposes create a contact in CRM:
8. Open Customer Portal and try to log in:
That’s it and in case you are too lazy to do provided steps you can find source code of a project here:
Честно говоря, недолюбливаю Customer Portal с момента его появления, возможно, что сейчас его сильно переписали.
ReplyDeleteХочу несколько дополнить приведённое решение.
Возможно, что вместо
var redirectUrl = !string.IsNullOrEmpty(Request.QueryString["ReturnUrl"])
? Request["ReturnUrl"]
: !string.IsNullOrEmpty(Request.QueryString["URL"])
? Request["URL"]
: "/";
можно использовать:
string targetPath = FormsAuthentication.GetRedirectUrl(String.Empty, false);
можно также использовать такой метод для редиректа на ReturnUrl (не понадобиться даже отдельно извлекать ReturnUrl):
FormsAuthentication.RedirectFromLoginPage(UserName, false);
Не очень хорошо передавать логин и пароль в открытом виде в URL'е. Это делается тут:
string redirectURL = page.Adx_PartialUrl + "?UserName=" + Server.UrlEncode(Login1.UserName) +
"&Password=" + Server.UrlEncode(Login1.Password);
Response.Redirect(redirectURL);
Тогда уж надо всё взаимодействие с сервером пускать по TLS-каналу.
Также является плохим тоном хранение пароля в открытом виде. Как минимум его надо хэшировать (ещё лучше вместе с каким-то другим секретным значением, например, так: http://crrm.ru/articles/2010/03/secure-pass-storing-in-mscrm).
В идеале, я бы порекомендовал написать собственный Membership-провайдер (а если требуется, то и Role-провайдер). Это не очень сложно, но позволяет использовать всю мощь провайдеров в ASP.NET (быстрое встраивание, встроенный механизм восстановления паролей).
Переписать можно всё ;) Вопрос в необходимости и в том заплатят за это или нет. Насчёт хранения пароля в открытом виде не спорю, безспорно лучше использовать хеш вместо самого пароля, но на это опять таки необходимо время и переработка кода и не мне вам объяснять то, что донести новые сроки и стоимость до бизнеса зачастую является тяжёлой, кропотливой, а зачастую и напрасной задачей.
DeleteHI,
ReplyDeleteI have followed your blog and deployed the customer portal. While giving user name and password in the login page it is again redirecting to the same page and unable to access other pages. But it successfully authenticated and I can see last logon time in the CRM contact page.
But it is not redirecting to other pages. Please help us to get the solution in this issue.
Hello,
DeleteNot sure what's wrong. Portal works fine for my customer.
Thank you very much for sharing this post
ReplyDeleteHello,
DeleteWelcome!
Hi ,
DeleteAs per blog i'm followed all the points , now the portal is working fine . i have some doubts
1.I need to replace contoso logo .
2.when i'm clicking on some links it shows the messages "like You do not have sufficient permissions to view this page"
3.i can't able to create a invition code in crm
cheers
Dhamodharan
Hi ,
Deletei got the solution for logo replacement .
Cheers
Dhamodharan
Hello,
DeleteGlad that you've solved your issue!
Kind regards,
Andrii.
Hi,I have followed your instructions and successfully deployed the customer portal.
ReplyDeleteBut I've the problem, that there is no password field in my contact entity (http://4.bp.blogspot.com/-5zZo7gBHWT4/UPmZ5_NuriI/AAAAAAAABp0/xdy7KdUWRXw/s1600/1.png).
Have you any suggestion for me, to solve this problem?
This comment has been removed by the author.
DeleteHi, i managed now to add the missing field, but I still not able to Login.
DeleteThe webpage gives out this message:
[NullReferenceException: Object reference not set to an instance of an object.]
Site.Pages.Login.Login1_Authenticate(Object sender, AuthenticateEventArgs e) in D:\Alle\CustomerPortal\Web\Pages\Login.aspx.cs:65
System.Web.UI.WebControls.Login.AttemptLogin() +159
System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e) +90
System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +51
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3553
Can you help me? :(
Hello Hendrik,
DeleteThe best way as for me is to attach with VS to your customer portal put breakpoint and get an answer why solution doesn't work.
Kind regards,
Andrii.
Hello Andrii,
Deleteunfortunately VS displays no error or something else.
I used the portal files from your ZIP-archive, but when trying to log in, I get the error.
I hope you can help me - I'm pretty frustrated because I did not find the error :(
Kind regards,
Hendrik
Hello Hendrik,
ReplyDeleteVS can detect compile-time errors but not run-time. To solve your issue you will have to using VS attach to IIS process (w3wp.exe) and put breakpoint to method Login1_Authenticate. Then you should try to authenticate and breakpoint should be reached. Then you will have to go line by line with debugger to find the reason of error you are getting.
Kind regards,
Andrii.
Hi !
ReplyDeleteI'm trying to install my first Dynamics install but i've got a ridiculous problem : How to build the custom package to impot it into Dynamics ?
Thanks for your help
Hello,
DeleteNot sure what do you want to do... Can you please explain what do you want to achieve?
Kind regards,
Andrii.
Hi !
DeleteThanks for your help.
I'm a rookie in Dynamics CRM 2011 and just use the system as simple as possible, on-premise version (we use Action Pack licences).
I try to install the Customer Portal but i need that the authentication to use the "contacts" instead of on Windows LiveID or AD.
i import the Customer Portal solution in my Dynamics Organisation and modifiy the web files with your instructions.
Now i try to activate this web site by use the "websitecopy" application, the copy is ok but i don't know how to access the website...
I think i've got this problems:
- i think the installation of the Customer Portal solution in Dynamis must be made AFTER rebuild the package with your modifications, but i don't know how
- i don't now what i must do to deploy correctly the customer portal website
- i really need your help :)
I hope that my problems are clearly explain...
Thanks in advance.
Hello, I got your issue.
DeleteYou should activate your portal using websitecopy - this will create required records in CRM.
After you will have to deploy to your IIS website files. Check following thread - http://social.microsoft.com/Forums/en-US/crmlabs/thread/43836cf2-8ab1-459c-a2f9-e753a674d0eb
Kind regards,
Andrii.
Thanks for your help ! You've got it !
ReplyDeleteThe wesite correctly appear in Internet Explorer but now; i got a login problem :
Server Error in '/' Application.
--------------------------------------------------------------------------------
Value cannot be null.
Parameter name: entity
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentNullException: Value cannot be null.
Parameter name: entity
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[ArgumentNullException: Value cannot be null.
Parameter name: entity]
Microsoft.Xrm.Sdk.Client.OrganizationServiceContext.Detach(Entity entity) +91
Site.Pages.Login.get_LoginContact() in C:\Projects\Poltev Sergey\CustomerPortal\Web\Pages\Login.aspx.cs:30
Site.Pages.Login.Login1_Authenticate(Object sender, AuthenticateEventArgs e) in C:\Projects\Poltev Sergey\CustomerPortal\Web\Pages\Login.aspx.cs:51
System.Web.UI.WebControls.Login.AttemptLogin() +166
System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e) +93
System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +52
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3707
A last idea for this last problem ? :)
Thank you very much
Regards
Sorry, don't take care about my last post, i use the wrong sources for the website.
ReplyDeletei'm trying with the good ones...
Best Regards
It seems that you've found error in the code ;) I'm not ideal and I already fixed that issue on the customer's portal. I will update portal and provide updated version.
ReplyDeleteKind regards,
Andrii.
OK... you know what ?... i've got a problem yet...hum... sorry.
ReplyDeleteWhen i try to access the login page, i've got this message :
Server Error in '/' Application.
--------------------------------------------------------------------------------
Compilation Error
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS1061: '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?)
Source Error:
Line 2:
Line 3:
Line 4:
Line 6:
Source File: c:\Web\Pages\Login.aspx Line: 4
Any Idea ?
Thanks a lot
Best Regards