Open Closed

Invalid Email Confirmation Token Always Occuring #5024


User avatar
0
balessi75 created

ABP Commercial 7.0.1 / Blazor Server / EF / Non tiered / Separate Host DB, Separate Tenant DBs / Lepton Theme

Hi, we are receiving the error "Volo.Abp.Identity:InvalidToken": "Invalid token.", whenever an email confirmation link is clicked.

The error doesn't occur in local development, it only occurs when the app is deployed (Azure App Service).

I've included logging from Azure below. The log indicates Volo.Abp.Account.Public.Web.Pages.Account.EmailConfirmationModel.OnGetAsync - ModelState is "Valid"

However, Model.InvalidToken appears to be true in EmailConfirmation.cshtml.cs

Also, in the database, the user gets flagged as having their email confirmed when clicking the confirmation link, even though they received the invalid token error.

Any ideas on what could be happening here? Any help is greatly appreciated...


30 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Hi, we are receiving the error "Volo.Abp.Identity:InvalidToken": "Invalid token.", whenever an email confirmation link is clicked.

    I can't see the error in the logs that you shared. Can you share these logs when you receive the error?

  • User Avatar
    0
    balessi75 created

    Hi,

    Sorry, I wasn't clear. There is no error in the logs and no exception occurs. The front-end UI simply shows the end user the message "Invalid Token"

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Can you set the log level to debug and re-get the logs?

        public async static Task<int> Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .Enrich.FromLogContext()
                .WriteTo.Async(c => c.File("Logs/logs.txt"))
                .WriteTo.Async(c => c.Console())
                .CreateLogger();
    
  • User Avatar
    0
    balessi75 created

    Hi @maliming ,

    The full log with debug info was sent to your email.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    [DBG] VerifyUserTokenAsync() failed with purpose: EmailConfirmation for user.

    Seems to be a problem with Data Protection, Please share the full log starting from the application startup.

    https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-7.0

    also share the code related to AddDataProtection

    Enable Information level logging of DataProtection to help diagnosis problem. The following appsettings.json file enables information logging of the DataProtection API:

    https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-7.0#logging-dataprotection

    Thanks

  • User Avatar
    0
    balessi75 created

    Thanks @maliming ,

    I emailed you a log from startup to the error occurring with the data protection logging turned on.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    What's this website?

    https://nvisionweb-dev.azurewebsites.net/

    Are you using angular?

    Which app is called the POST api/account/send-email-confirmation-token ?

    Please share a structure screenshot of your solution.

  • User Avatar
    0
    Leonardo.Willrich created

    I'm getting the same error, using version 7.2.1. It shows the page error 403 and then the message Invalid Token. Note, sometimes it works fine, sometimes I get stuck to this page. Clicking on the Go To Application button, it goes to the Swagger page instead to the login page. I'm using Blazor WASM application.

  • User Avatar
    0
    Leonardo.Willrich created

    Just sharing something that I've noticed. When creating a new user by the menu "Identity Management > Users", and you check the option "Send confirmation email", it will send the email. If you click on the link when still logged it will work fine. But, if you don't check that option, when if you log out and try to login using the new user, it will as to confirm the email, then, the link sent will show error 403.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Thanks @all

    I will check it asap.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    The error doesn't occur in local development, it only occurs when the app is deployed (Azure App Service).

    Can you reproduce it locally by setting the ASPNETCORE_ENVIRONMENT to production?

  • User Avatar
    0
    Leonardo.Willrich created

    @maliming changing the environment and profile to release to be able to send emails, it is working like a charm in my local machine, however, when it is deployed to a IIS server, I'm getting the error 403 Forbbiden and Invalid Token message.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    In this case, I must find a way to reproduce the problem. Do you have any ideas?

  • User Avatar
    0
    balessi75 created

    Hi @maliming ,

    I confirmed that when running locally with ASPNETCORE_ENVIRONMENT set to either Development or Production mode, everything works correctly. The problem only occurs once the application is deployed.

    Any ideas, why the user still ends up having their email flagged as confirmed even though they get the invalid token message?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    why the user still ends up having their email flagged as confirmed even though they get the invalid token message?

    This means that the URL has been accessed many times. The first time it succeeds, the token will be invalid after that.

  • User Avatar
    0
    balessi75 created

    Hi @maliming ,

    Ok, so something is accessing the token URL more than once when deployed, but not in local development?

    In an attempt to help you be able to replicate the problem, I created a new blazor server project at verison 7.0.1 using the abp cli. I figured this would eliminate any of our code/or overrides from being the issue.

    The only change I made was to allow the application to startup in an azure app service when abp is using openiddict (this was not a problem, or required when we used identityserver). The solution for using openiddict in an azure app servicce is documented here. https://codejack.com/2022/12/deploying-abp-io-to-an-azure-appservice/

    The only other change I made was to implement an email sender (sendgrid) so that we can receive the confirmation email. context.Services.Replace(ServiceDescriptor.Singleton<IEmailSender, SendGridEmailSender>());

    The newly created ABP starts up in azure app service and a confirmation email is successfully sent. When we click the confirmation link, however, we still receive the 'Invalid Token' error.

    I hope this helps, Please advise as we need a solution or workaround asap.

    Thanks

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi balessi75

    When we click the confirmation link, however, we still receive the 'Invalid Token' error.

    Is the email of the user confirmed?

    Can you share the full logs of this test process ?

    liming.ma@volosoft.com

  • User Avatar
    0
    balessi75 created

    Hi @maliming ,

    This may be helpful, but not sure. I'm analyzing the logs during the time a confirmation link is sent locally and comparing to when things are running in the Azure app service.

    I noticed that in local development (everything works fine), there is only one HTTP GET that references the confirmation token.

    HTTP/2 GET

    10:41.947 -04:00 [INF] Request starting HTTP/2 GET https://localhost:44373/Account/EmailConfirmation?userId=35fbd381-2ba7-f50e-198e-3a03a43dd59c&__tenant=&confirmationToken=CfDJ8GZOlvHBFm1MpqnR5b0ZIFns5BYvAqRh0WnxNpbHZStg0x3t%2Fuhhz9btfZHkv9NBCFJPBJK5nkuAxXQA6yyDUFA%2FtoRISlH1yqp8iy66DxnV7VHpb3qetIgtMtruAmPWt2AYg2XrWgHLdQDTqV3H%2FTgFYVFJCPDDQFEP21U%2F%2FrJSp%2BlXntX3bSueaD9YDqqkye%2F0KhnatWxLKuI%2FBoUmoig8%2BM%2FqPTtwbxFAvPl84VYoAf6PuTL372o4log4AJC2xQ%3D%3D - -
    

    But, when running in Azure there is both a HTTP HEAD and a HTTP GET that references the confirmation token

    HTTP/1.1 HEAD

    2023-05-10 02:42:38.836 +00:00 [INF] Request starting HTTP/1.1 HEAD https://nvisionweb-debug.azurewebsites.net/Account/EmailConfirmation?userId=35fbd381-2ba7-f50e-198e-3a03a43dd59c&__tenant=&confirmationToken=CfDJ8JOHPzwk2eBIkti1b63OgOlfmYda18CNZO8o6Wm7g%2FkDuoBuYZ2eUDK4mts8dFzJK3kRQ6LMDgUSYpPoJSCiCrHjidzQD0yeNwroUmDpBqEtdj7zHHOjmxL2nlWHWTZmgfsSHWeSwF3wIh4%2BLRFVAmR92P6ck4KWZF6IMTevWbfMqMEPJK04jcg%2FXdwTbZNKBuUMlFUeZ4CB5JctFq9rNwMSQt2ar3Nzv5Cvoq%2BsNNrlz%2BNW2Pk7v9LwM2jdALALkw%3D%3D - -
    

    HTTP/1.1 GET

    2023-05-10 02:42:39.278 +00:00 [INF] Request starting HTTP/1.1 GET https://nvisionweb-debug.azurewebsites.net/Account/EmailConfirmation?userId=35fbd381-2ba7-f50e-198e-3a03a43dd59c&__tenant=&confirmationToken=CfDJ8JOHPzwk2eBIkti1b63OgOlfmYda18CNZO8o6Wm7g%2FkDuoBuYZ2eUDK4mts8dFzJK3kRQ6LMDgUSYpPoJSCiCrHjidzQD0yeNwroUmDpBqEtdj7zHHOjmxL2nlWHWTZmgfsSHWeSwF3wIh4%2BLRFVAmR92P6ck4KWZF6IMTevWbfMqMEPJK04jcg%2FXdwTbZNKBuUMlFUeZ4CB5JctFq9rNwMSQt2ar3Nzv5Cvoq%2BsNNrlz%2BNW2Pk7v9LwM2jdALALkw%3D%3D - -
    

    Could this be what's causing the token to be invalidated?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Yes, this URL can only be requested once.

    Will it be requested by components like Azure or Firewall? You can write detailed http request header info in the log.

  • User Avatar
    0
    balessi75 created

    Will it be requested by components like Azure or Firewall?

    I'm not sure, I disabled our azure application gateway from the equation, so I know that isn't causing the problem,

    You can write detailed http request header info in the log.

    Can you assist me in how to do that?

  • User Avatar
    0
    Leonardo.Willrich created

    @maliming, I'm using IIS and I'm facing the same issue, therefore, I don't think Azure is the issue.

  • User Avatar
    0
    balessi75 created

    @maliming,

    Also, on previous versions of ABP I do not recall having this issue when publishing a basic newly templated application. Could there be something with ABP 7.0+ that is causing the issue?

    @Leonardo.Willrich are you using Blazor Server as well?

  • User Avatar
    0
    Leonardo.Willrich created

    @balessi75, I'm using Blazor WASM, but, the Host application should be the same as yours. That URL is from the Web API.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    You can write detailed http request header info in the log.

    
    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(AccountAppService), typeof(IAccountAppService))]
    public class MyAccountAppService : AccountAppService
    {
        public MyAccountAppService(IdentityUserManager userManager,
            IAccountEmailer accountEmailer,
            IAccountPhoneService phoneService,
            IIdentityRoleRepository roleRepository,
            IdentitySecurityLogManager identitySecurityLogManager,
            IBlobContainer<AccountProfilePictureContainer> accountProfilePictureContainer,
            ISettingManager settingManager,
            IOptions<IdentityOptions> identityOptions,
            IIdentitySecurityLogRepository securityLogRepository) :
            base(userManager, accountEmailer, phoneService, roleRepository, identitySecurityLogManager,
            accountProfilePictureContainer, settingManager, identityOptions, securityLogRepository)
        {
        }
    
        public async override Task ConfirmEmailAsync(ConfirmEmailInput input)
        {
            var httpContext = LazyServiceProvider.LazyGetRequiredService<IHttpContextAccessor>();
            if (httpContext.HttpContext == null)
            {
                var obj = new
                {
                    RemoteIpAddress = httpContext.HttpContext.Connection.RemoteIpAddress?.ToString(),
                    Headers = httpContext.HttpContext.Request.Headers
                        .Select(header => header.Key + " : " + header.Value)
                        .ToList()
                };
    
                var logger = LazyServiceProvider.LazyGetRequiredService<ILogger<MyAccountAppService>>();
                logger.LogError(JsonSerializer.Serialize(obj));
            }
    
            await base.ConfirmEmailAsync(input);
        }
    }
    
    

    Here is a temporary solution:

    [Dependency(ReplaceServices = true)]
    [ExposeServices(typeof(AccountAppService), typeof(IAccountAppService))]
    public class MyAccountAppService : AccountAppService
    {
        public MyAccountAppService(IdentityUserManager userManager,
            IAccountEmailer accountEmailer,
            IAccountPhoneService phoneService,
            IIdentityRoleRepository roleRepository,
            IdentitySecurityLogManager identitySecurityLogManager,
            IBlobContainer<AccountProfilePictureContainer> accountProfilePictureContainer,
            ISettingManager settingManager,
            IOptions<IdentityOptions> identityOptions,
            IIdentitySecurityLogRepository securityLogRepository) :
            base(userManager, accountEmailer, phoneService, roleRepository, identitySecurityLogManager,
            accountProfilePictureContainer, settingManager, identityOptions, securityLogRepository)
        {
        }
    
        public async override Task ConfirmEmailAsync(ConfirmEmailInput input)
        {
            var user = await UserManager.GetByIdAsync(input.UserId);
    
            if (user.EmailConfirmed)
            {
                return;
            }
    
            await base.ConfirmEmailAsync(input);
        }
    }
    
    
  • User Avatar
    0
    balessi75 created

    Hi @maliming

    Unfortunately the proposed temporary solution does not work. We implemented the above override to ConfirmEmailAsync(ConfirmEmailInput input) and redeployed to production.

    What we found is that ConfirmEmailAsync method executes during the HTTP HEAD request to https://nvisionweb-debug.azurewebsites.net/Account/EmailConfirmation, which sets the User as EmailConfirmed = true,

    But when the following HTTP GET to https://nvisionweb-debug.azurewebsites.net/Account/EmailConfirmation is requested, ConfirmEmailAsync(ConfirmEmailInput input) is never executed again, so the return statement you suggested if the user is already confirmed has no effect.

    See the the log from the deployed server (everything that is logged when the user clicks the confirm email link). Notice the debugging line that we put in with the asterisks (before and after await base.ConfirmEmailAsync(input); is executed. They indicate that ConfirmEmailAsync only fires during the HTTP HEAD request.

    2023-05-10 21:51:43.187 +00:00 [INF] Request starting HTTP/1.1 HEAD https://dev.nvisiononline.net/Account/EmailConfirmation?userId=35fbd381-2ba7-f50e-198e-3a03a43dd59c&__tenant=&confirmationToken=CfDJ8DbG1VUiUwVBrj99lyT7AP35Urc5Toikh6AIrddOdBw7VbfR4JYE6FFazHLbOwboWKA%2BKc1cuvbqIgWn%2FYvA8w8CfHDpROMliWwAT9oqDTHG553cRszN7Acl8HPQSCnOKTslulVfEMJgOn40LhXq9fUIi5FFVOvEXthVmy9nrm1RgKU%2Ff9orqAHLd2ikFxYhebkZ5lxuy2Zd0o2EXZ3KirdCzeE1iHhE9ALMqULkWgNNSwxltpIMfWAEd9Ydry8BNA%3D%3D&returnUrl=/ - -
    2023-05-10 21:51:43.190 +00:00 [INF] Executing endpoint '/Account/EmailConfirmation'
    2023-05-10 21:51:43.195 +00:00 [INF] Route matched with {page = "/Account/EmailConfirmation", area = "", action = "", controller = ""}. Executing page /Account/EmailConfirmation
    2023-05-10 21:51:43.195 +00:00 [INF] Skipping the execution of current filter as its not the most effective filter implementing the policy Microsoft.AspNetCore.Mvc.ViewFeatures.IAntiforgeryPolicy
    2023-05-10 21:51:43.207 +00:00 [INF] Executing handler method Volo.Abp.Account.Public.Web.Pages.Account.EmailConfirmationModel.OnGetAsync - ModelState is "Valid"
    2023-05-10 21:51:43.244 +00:00 [ERR] **************** before base.ConfirmEmailAsync - userid: 35fbd381-2ba7-f50e-198e-3a03a43dd59c, email confirmed: False*************
    2023-05-10 21:51:43.387 +00:00 [ERR] **************** after base.ConfirmEmailAsync - userid: 35fbd381-2ba7-f50e-198e-3a03a43dd59c, email confirmed: True*************
    2023-05-10 21:51:43.387 +00:00 [INF] Executed handler method OnGetAsync, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
    2023-05-10 21:51:43.401 +00:00 [INF] Executed page /Account/EmailConfirmation in 205.4595ms
    2023-05-10 21:51:43.401 +00:00 [INF] Executed endpoint '/Account/EmailConfirmation'
    2023-05-10 21:51:43.417 +00:00 [INF] Request finished HTTP/1.1 HEAD https://dev.nvisiononline.net/Account/EmailConfirmation?userId=35fbd381-2ba7-f50e-198e-3a03a43dd59c&__tenant=&confirmationToken=CfDJ8DbG1VUiUwVBrj99lyT7AP35Urc5Toikh6AIrddOdBw7VbfR4JYE6FFazHLbOwboWKA%2BKc1cuvbqIgWn%2FYvA8w8CfHDpROMliWwAT9oqDTHG553cRszN7Acl8HPQSCnOKTslulVfEMJgOn40LhXq9fUIi5FFVOvEXthVmy9nrm1RgKU%2Ff9orqAHLd2ikFxYhebkZ5lxuy2Zd0o2EXZ3KirdCzeE1iHhE9ALMqULkWgNNSwxltpIMfWAEd9Ydry8BNA%3D%3D&returnUrl=/ - - - 200 - text/html;+charset=utf-8 230.1402ms
    2023-05-10 21:51:43.938 +00:00 [INF] Request starting HTTP/1.1 GET https://dev.nvisiononline.net/Account/EmailConfirmation?userId=35fbd381-2ba7-f50e-198e-3a03a43dd59c&__tenant=&confirmationToken=CfDJ8DbG1VUiUwVBrj99lyT7AP35Urc5Toikh6AIrddOdBw7VbfR4JYE6FFazHLbOwboWKA%2BKc1cuvbqIgWn%2FYvA8w8CfHDpROMliWwAT9oqDTHG553cRszN7Acl8HPQSCnOKTslulVfEMJgOn40LhXq9fUIi5FFVOvEXthVmy9nrm1RgKU%2Ff9orqAHLd2ikFxYhebkZ5lxuy2Zd0o2EXZ3KirdCzeE1iHhE9ALMqULkWgNNSwxltpIMfWAEd9Ydry8BNA%3D%3D&returnUrl=/ - -
    2023-05-10 21:51:43.940 +00:00 [INF] Executing endpoint '/Account/EmailConfirmation'
    2023-05-10 21:51:43.941 +00:00 [INF] Route matched with {page = "/Account/EmailConfirmation", area = "", action = "", controller = ""}. Executing page /Account/EmailConfirmation
    2023-05-10 21:51:43.941 +00:00 [INF] Skipping the execution of current filter as its not the most effective filter implementing the policy Microsoft.AspNetCore.Mvc.ViewFeatures.IAntiforgeryPolicy
    2023-05-10 21:51:43.950 +00:00 [INF] Executing handler method Volo.Abp.Account.Public.Web.Pages.Account.EmailConfirmationModel.OnGetAsync - ModelState is "Valid"
    2023-05-10 21:51:44.019 +00:00 [INF] Executed handler method OnGetAsync, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
    2023-05-10 21:51:44.026 +00:00 [INF] Executed page /Account/EmailConfirmation in 85.4659ms
    2023-05-10 21:51:44.026 +00:00 [INF] Executed endpoint '/Account/EmailConfirmation'
    2023-05-10 21:51:44.027 +00:00 [INF] Request finished HTTP/1.1 GET https://dev.nvisiononline.net/Account/EmailConfirmation?userId=35fbd381-2ba7-f50e-198e-3a03a43dd59c&__tenant=&confirmationToken=CfDJ8DbG1VUiUwVBrj99lyT7AP35Urc5Toikh6AIrddOdBw7VbfR4JYE6FFazHLbOwboWKA%2BKc1cuvbqIgWn%2FYvA8w8CfHDpROMliWwAT9oqDTHG553cRszN7Acl8HPQSCnOKTslulVfEMJgOn40LhXq9fUIi5FFVOvEXthVmy9nrm1RgKU%2Ff9orqAHLd2ikFxYhebkZ5lxuy2Zd0o2EXZ3KirdCzeE1iHhE9ALMqULkWgNNSwxltpIMfWAEd9Ydry8BNA%3D%3D&returnUrl=/ - - - 200 - text/html;+charset=utf-8 88.9392ms
    2023-05-10 21:51:44.222 +00:00 [INF] Request starting HTTP/1.1 GET https://dev.nvisiononline.net/__bundles/Lepton.Global.A731103D4094CB227220AB3AA128D798.css?_v=638193521556340646 - -
    2023-05-10 21:51:44.225 +00:00 [INF] Sending file. Request path: '/__bundles/Lepton.Global.A731103D4094CB227220AB3AA128D798.css'. Physical path: 'N/A'
    2023-05-10 21:51:44.233 +00:00 [INF] Request finished HTTP/1.1 GET https://dev.nvisiononline.net/__bundles/Lepton.Global.A731103D4094CB227220AB3AA128D798.css?_v=638193521556340646 - - - 200 508363 text/css 10.8158ms
    2023-05-10 21:51:44.254 +00:00 [INF] Request starting HTTP/1.1 GET https://dev.nvisiononline.net/__bundles/Lepton.Global.BEB0EC95992206E635C10616FB097244.js?_v=638193521562893246 - -
    2023-05-10 21:51:44.255 +00:00 [INF] Request starting HTTP/1.1 GET https://dev.nvisiononline.net/libs/timeago/locales/jquery.timeago.en.js?_v=637792859015910000 - -
    2023-05-10 21:51:44.256 +00:00 [INF] The file /libs/timeago/locales/jquery.timeago.en.js was not modified
    2023-05-10 21:51:44.256 +00:00 [INF] Request finished HTTP/1.1 GET https://dev.nvisiononline.net/libs/timeago/locales/jquery.timeago.en.js?_v=637792859015910000 - - - 304 - application/javascript 0.7395ms
    

    Any other ideas on a work around or resolution?

Made with ❤️ on ABP v9.1.0-preview. Updated on December 05, 2024, 12:19