Ticket T234465
Visible to All Users

WebForms - How to skip authentication and automatically redirect a user to the New Password dialog by a link from email

created 10 years ago

I have a requirement in the product, to implement confirmation of password reset.
So, the scenario is next:
Once user get's to the ForgotPassword detail view, enters valid email. We send out email to the one he entered, with a confirmation link. When that confirmation click, I need to show 2 fieds, New Password and Confirm New Password, to allow password to be changed.

From the code perspective, I'll be generating URL to login.aspx with a parameter. Something like:
~\Login .aspx?id=123456789

So in the application, if that's the URL which was requested, instead of showing usual username and password fields on that page, I need to show 2 fields, I've mentoned above ( New password and Confirmation ) .

How can I achieve the behavior I've described?

Thank you in advance

Answers approved by DevExpress Support

created 10 years ago (modified 2 years ago)

Hello Dmitry,

You can implement this functionality using a custom authentication. In the authentication's AskLogonParametersViaUI property, check if the Web request contains the user name to determine whether or not the logon window should be shown. In the Authenticate method, authenticate the user whose name was specified. Here is an example:

C#
using DevExpress.Data.Filtering; using DevExpress.ExpressApp; using DevExpress.ExpressApp.Security; using DevExpress.Persistent.Base.Security; using System; using System.Linq; using System.Web; namespace SkipAuthenticationWeb.Web { public class CustomAuthentication : AuthenticationStandard { private bool IsUserExist() { if(string.IsNullOrEmpty(UserName)) { return false; } var provider = Application.GetObjectSpaceProvider(UserType); INonsecuredObjectSpaceProvider nonsecuredObjectSpaceProvider = (INonsecuredObjectSpaceProvider)provider; var objectSpace = nonsecuredObjectSpaceProvider.CreateNonsecuredObjectSpace(); return FindUser(objectSpace) != null; } private IAuthenticationStandardUser FindUser(IObjectSpace objectSpace) { if(string.IsNullOrEmpty(UserName)) { return null; } return (IAuthenticationStandardUser)objectSpace.FindObject(UserType, new BinaryOperator("UserName", UserName)); } private string UserName { get { return HttpContext.Current.Request.Params["id"]; } } public override bool AskLogonParametersViaUI { get { if(IsUserExist()) { return false; } return base.AskLogonParametersViaUI; } } public override object Authenticate(IObjectSpace objectSpace) { IAuthenticationStandardUser user = FindUser(objectSpace); if(user != null) { user.ChangePasswordOnFirstLogon = true; objectSpace.CommitChanges(); return user; } return base.Authenticate(objectSpace); } public XafApplication Application { get; set; } } }

Then, replace the default authentication (AuthenticationStandard) with a custom one and assign the CustomAuthentication.Application property:

C#
namespace SkipAuthenticationWeb.Web { // For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Web.WebApplication public partial class SkipAuthenticationWebAspNetApplication : WebApplication { private CustomAuthentication customAuthentication; public SkipAuthenticationWebAspNetApplication() { InitializeComponent(); this.customAuthentication.Application = this; } private void InitializeComponent() { this.customAuthentication = new CustomAuthentication(); this.securityStrategyComplex1.Authentication = this.customAuthentication; this.customAuthentication.LogonParametersType = typeof(DevExpress.ExpressApp.Security.AuthenticationStandardLogonParameters); this.customAuthentication.UserLoginInfoType = typeof(SkipAuthenticationWeb.Module.BusinessObjects.ApplicationUserLoginInfo); } }

I have attached a sample project demonstrating this solution. Refer to the How to: Use Custom Logon Parameters and Authentication topic for additional information.

You may also find the following ticket useful: How to skip the logon page and automatically authenticate a user in code (e.g. from an external link)

If you want to show a password change page without logging in the corresponding user, it is better to accomplish this task using a custom page. The Login.aspx page is not appropriate for this task, since it is difficult to change its content dynamically based on the request parameters. So, I recommend that you create a custom page (e.g. ChangePassword.aspx) in your application, add the required text edit controls and the OK button in it. Here is an example of how to change password when this button is clicked:

C#
string userName = HttpContext.Current.Request.Params["id"]; if (!String.IsNullOrEmpty(userName)) { IObjectSpace objectSpace = WebApplication.Instance.CreateObjectSpace(); IAuthenticationStandardUser user = (IAuthenticationStandardUser)objectSpace.FindObject(WebApplication.Instance.Security.UserType, new BinaryOperator("UserName", userName)); if (user != null) { user.SetPassword(password); objectSpace.CommitChanges(); WebApplication.Redirect("Default.aspx"); } }

In addition, allow access to this page to non-authenticated users in Web.config:

XML
<location path="ChangePassword.aspx"> <system.web> <authorization> <allow users="?"/> </authorization> </system.web> </location>

To learn how to accomplish this task in XAF Blazor, refer to the following thread: T964789 - Bypass the login Page in Blazor XAF - using parameter passed in URL.

    Show previous comments (4)
    Anatol (DevExpress) 10 years ago

      Thank you for the clarification. Actions specified in this method are executed only when a user is logged in. If you need to implement this functionality without logging in a user, it is better to use a custom page. I have added a description of this solution to my initial answer. Does it meet your needs?

        So you are saying, there is no other way, other than creating separate ASPX page for the scenario I've described?
        Is the ASPX page, what you are referring to, when you say separate page?
        Can it use the same template, as the original login page?
        Thanks

        Anatol (DevExpress) 10 years ago

          This is the easiest and most reliable way. There are other ways to accomplish this task, but they are a bit tricky, and we would prefer to avoid recommending them.

          >> Is the ASPX page, what you are referring to, when you say separate page?
          Yes, I mean a general ASPX page.

          >> Can it use the same template, as the original login page?
          To apply the same visual style to this page, it is sufficient to use DevExpress controls with the same theme.

          Other Answers

          created 10 years ago (modified 10 years ago)

          Posting a solution, which worked for me. Hopefully, it would be helpful for others.
          Much better option, than separate page, because all the styles and markup for other pages, won't get duplicated.
          And it's less code of course.

          In the code below, I'm redirecting to ResetPassword view, but I'm quite sure, it can be redirected to any other view in the same way.
          Redirect is needed, since otherwise page errors.

          If you can suggest a better way to avoid error, and get to the new view - please, share.

          C#
          /// <summary> /// Redirects page to itself after view get's changed to ResetPassword. /// </summary> public class RedirectController : ObjectViewController<DetailView , XpandLogonParameters> { #region Constants /// <summary> /// ResetPassword action key. /// </summary> private const string RESETPASSWORDACTIONKEY = "action"; /// <summary> /// ResetPassword action value. /// </summary> private const string RESETPASSWORDACTIONVALUE = "rp"; #endregion #region Methods /// <summary> /// Redirects page to itself in the case when action is set to ResetPassword. /// </summary> protected override void EndUpdate() { base.EndUpdate(); if ( IsRedirectRequired() ) { HttpContext.Current.Response.Redirect( HttpContext.Current.Request.Url.LocalPath , true ); } } /// <summary> /// Changes view to ResetPassword if that action is specified in the url. /// </summary> protected override void OnViewControlsCreated() { base.OnViewControlsCreated(); if ( IsRedirectRequired() ) { Frame.GetController<Security.Extensions.ManageUsersOnLogonController>().RestorePasswordAction.DoExecute(); } } /// <summary> /// Checks if ResetPassword redirect requested. /// </summary> /// <returns>True, when redirect requried. False otherwise.</returns> private bool IsRedirectRequired() { string action; action = HttpContext.Current.Request.Params[ RESETPASSWORDACTIONKEY ]; return !String.IsNullOrEmpty( action ) && action.Equals( RESETPASSWORDACTIONVALUE , StringComparison.InvariantCultureIgnoreCase ); } #endregion }
            Comments (2)
            Anatol (DevExpress) 10 years ago

              Thank you for posting your solution, Dmitry. I am happy to know that you have successfully implemented this functionality. Please do not hesitate to contact us if you need further assistance.

              OS OS
              Oleksiy Shtefchuk 9 years ago

                Dmitry Lazariev, thanks a lot for this your solution. I searched for it few days and you save me lot of time. Have a nice time and great projects! :)

                Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

                Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.