Idenity.Core GenerateEmailConfirmationTokenAsync 来自 Angular 10 WebApp 的无效令牌
Idenity.Core GenerateEmailConfirmationTokenAsync Invalid Token coming from Angular 10 WebApp
我有一个使用 Identity Core 生成电子邮件确认令牌的 DotNet Core WebApi。当我生成令牌并使用 WebApi URL 将其发送到我的电子邮件地址时,它工作正常。当我使用 Angular Web 应用程序将 ur?token=token 发送到我的电子邮件以从该应用程序进行 AJAX 调用时,我收到“无效令牌”错误。来自 Angular 服务的 GET 调用获取 QueryString 并对 API ->“无效令牌”进行 AJAX 调用。
WebApi 代码:
//I tried
//var confirmationLink = Url.Content($"{this.Request.Scheme}://{siteUrl}{this.Request.PathBase}/Confirm?token={token}&email={appUser.Email}");
// And
var confirmationLink = Url.Content($"{this.Request.Scheme}://{siteUrl}{this.Request.PathBase}/Confirm?token={HttpUtility.UrlEncode(token)}&email={appUser.Email}");
SendEmail($"{model.FirstName} {model.LastName}", "Confirm your account", model.Email,
$"Please confirm your account by clicking {callback}");
Angular 查看
this.route.queryParams.subscribe(params => {
this.email = params[emailKey];
this.token = params[tokenKey];
});
this.authenticationService.confirmEmail(this.email, this.token).subscribe(
(result) => {
this.emailMsg = 'Thank you for confirming your email. Please procced to login page.';
},
(err) => {
this.emailMsg = 'Email confirmation link has expired or is invalid.';
}
);
Angular 服务
return this.http.get<boolean>(`${environment.apiUrl}/authenticate/VerifyEmail?email=${email}&token=${token}`)
.pipe(
map((data: boolean) => {
return data;
}), catchError((error: HttpErrorResponse) => {
return throwError(error);
})
);
在电子邮件确认端点中,我尝试了一些不同的东西并且 none 工作。
var user = await _userManager.FindByEmailAsync(email);
if (user == null) {
throw new InvalidOperationException();
}
var fix = token.Replace(' ', '+');
var emailConfirmationResultescapefix = await _userManager.ConfirmEmailAsync(user, Uri.EscapeDataString(fix));
var emailConfirmationResulttest = await _userManager.ConfirmEmailAsync(user, Uri.EscapeDataString(token));
var code = HttpUtility.UrlDecode(token);
var emailConfirmationResult = await _userManager.ConfirmEmailAsync(user, Uri.EscapeDataString(code));
var urisescape = Uri.EscapeDataString(token);
var emailConfirmationResultescape = await _userManager.ConfirmEmailAsync(user, Uri.EscapeDataString(urisescape));
var webUtil = WebUtility.UrlDecode(token);
var emailConfirmationResultweb = await _userManager.ConfirmEmailAsync(user, Uri.EscapeDataString(webUtil));
我尝试验证令牌的所有不同方法都失败了。他们都有一个无效的令牌。我尝试使用代码比较来检查令牌是否确实不同并且不是第一种方法。令牌匹配,但我仍然得到无效令牌。
据我了解,您仅在 WebApi 中对令牌进行编码,但我建议在从 Angular 服务传递令牌时使用 encodeURIComponent()
对其进行编码。所以你的代码应该像下面这样。
Angular 服务:
return this.http.get<boolean>(`${environment.apiUrl}/authenticate/VerifyEmail?email=${email}&token=${encodeURIComponent(token)}`)
.pipe(
map((data: boolean) => {
return data;
}), catchError((error: HttpErrorResponse) => {
return throwError(error);
})
);
这听起来很愚蠢,但出于某种原因,在执行以下操作后:
token = token.Replace(' ', '+');
现在电子邮件验证有效。
不保证 ASP.NET 身份生成的令牌是 URL 安全的。
如果您使用 Identity.UI 包,那么它会为您处理 URL-自版本 3.x.
以来的安全性
我通常在代码中使用 Base64UrlEncoder.Encode(token)
和 Base64UrlEncoder.Decode(token)
来解决这个问题。它摆脱了所有可能在 URL-s.
中引起问题的符号
Base64UrlEncoder
来自命名空间 Microsoft.IdentityModel.Tokens
.
我有一个使用 Identity Core 生成电子邮件确认令牌的 DotNet Core WebApi。当我生成令牌并使用 WebApi URL 将其发送到我的电子邮件地址时,它工作正常。当我使用 Angular Web 应用程序将 ur?token=token 发送到我的电子邮件以从该应用程序进行 AJAX 调用时,我收到“无效令牌”错误。来自 Angular 服务的 GET 调用获取 QueryString 并对 API ->“无效令牌”进行 AJAX 调用。
WebApi 代码:
//I tried
//var confirmationLink = Url.Content($"{this.Request.Scheme}://{siteUrl}{this.Request.PathBase}/Confirm?token={token}&email={appUser.Email}");
// And
var confirmationLink = Url.Content($"{this.Request.Scheme}://{siteUrl}{this.Request.PathBase}/Confirm?token={HttpUtility.UrlEncode(token)}&email={appUser.Email}");
SendEmail($"{model.FirstName} {model.LastName}", "Confirm your account", model.Email,
$"Please confirm your account by clicking {callback}");
Angular 查看
this.route.queryParams.subscribe(params => {
this.email = params[emailKey];
this.token = params[tokenKey];
});
this.authenticationService.confirmEmail(this.email, this.token).subscribe(
(result) => {
this.emailMsg = 'Thank you for confirming your email. Please procced to login page.';
},
(err) => {
this.emailMsg = 'Email confirmation link has expired or is invalid.';
}
);
Angular 服务
return this.http.get<boolean>(`${environment.apiUrl}/authenticate/VerifyEmail?email=${email}&token=${token}`)
.pipe(
map((data: boolean) => {
return data;
}), catchError((error: HttpErrorResponse) => {
return throwError(error);
})
);
在电子邮件确认端点中,我尝试了一些不同的东西并且 none 工作。
var user = await _userManager.FindByEmailAsync(email);
if (user == null) {
throw new InvalidOperationException();
}
var fix = token.Replace(' ', '+');
var emailConfirmationResultescapefix = await _userManager.ConfirmEmailAsync(user, Uri.EscapeDataString(fix));
var emailConfirmationResulttest = await _userManager.ConfirmEmailAsync(user, Uri.EscapeDataString(token));
var code = HttpUtility.UrlDecode(token);
var emailConfirmationResult = await _userManager.ConfirmEmailAsync(user, Uri.EscapeDataString(code));
var urisescape = Uri.EscapeDataString(token);
var emailConfirmationResultescape = await _userManager.ConfirmEmailAsync(user, Uri.EscapeDataString(urisescape));
var webUtil = WebUtility.UrlDecode(token);
var emailConfirmationResultweb = await _userManager.ConfirmEmailAsync(user, Uri.EscapeDataString(webUtil));
我尝试验证令牌的所有不同方法都失败了。他们都有一个无效的令牌。我尝试使用代码比较来检查令牌是否确实不同并且不是第一种方法。令牌匹配,但我仍然得到无效令牌。
据我了解,您仅在 WebApi 中对令牌进行编码,但我建议在从 Angular 服务传递令牌时使用 encodeURIComponent()
对其进行编码。所以你的代码应该像下面这样。
Angular 服务:
return this.http.get<boolean>(`${environment.apiUrl}/authenticate/VerifyEmail?email=${email}&token=${encodeURIComponent(token)}`)
.pipe(
map((data: boolean) => {
return data;
}), catchError((error: HttpErrorResponse) => {
return throwError(error);
})
);
这听起来很愚蠢,但出于某种原因,在执行以下操作后:
token = token.Replace(' ', '+');
现在电子邮件验证有效。
不保证 ASP.NET 身份生成的令牌是 URL 安全的。
如果您使用 Identity.UI 包,那么它会为您处理 URL-自版本 3.x.
以来的安全性我通常在代码中使用 Base64UrlEncoder.Encode(token)
和 Base64UrlEncoder.Decode(token)
来解决这个问题。它摆脱了所有可能在 URL-s.
Base64UrlEncoder
来自命名空间 Microsoft.IdentityModel.Tokens
.