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)
-
0
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?
-
0
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"
-
0
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();
-
0
Hi @maliming ,
The full log with debug info was sent to your email.
-
0
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
-
0
Thanks @maliming ,
I emailed you a log from startup to the error occurring with the data protection logging turned on.
-
0
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.
-
0
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.
-
0
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.
-
0
Thanks @all
I will check it asap.
-
0
-
0
@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.
-
0
hi
In this case, I must find a way to reproduce the problem. Do you have any ideas?
-
0
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?
-
0
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.
-
0
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
-
0
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
-
0
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?
-
0
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.
-
0
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?
-
0
@maliming, I'm using IIS and I'm facing the same issue, therefore, I don't think Azure is the issue.
-
0
@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?
-
0
@balessi75, I'm using Blazor WASM, but, the Host application should be the same as yours. That URL is from the Web API.
-
0
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); } }
-
0
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 tohttps://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 thatConfirmEmailAsync
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?