-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Open
Labels
area-identityIncludes: Identity and providersIncludes: Identity and providers
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
When we host the IdentityApi in a non-public environment and we call an api-method for sending the conformation.
The conformationlink has the host address of the api application.
async Task SendConfirmationEmailAsync(TUser user, UserManager<TUser> userManager, HttpContext context, string email, bool isChange = false) |
Expected Behavior
That an Event is called/raised with the parameters to be processed. (user, userid, code)
For example
public interface IIdentityCoreHandler<TUser> where TUser : class
{
Task LoggedIn(string email);
Task LoggedInFailure(string email, string errorMessage);
Task EmailConfirmed(TUser user);
Task SendConfirmationEmailAsync(TUser user, string? userId, string email, string code, bool isChange = false);
Task SendPasswordResetCodeAsync(TUser user, string email, string resetCode);
}
with implementation
public class IdentityCoreHandler<TUser> : IIdentityCoreHandler<TUser>
where TUser : class
{
/*private readonly IPublisher _eventPublisher;*/
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IEmailSender<TUser> _emailSender;
private readonly LinkGenerator _linkGenerator;
public IdentityCoreHandler(/*IPublisher eventPublisher,*/ IHttpContextAccessor httpContextAccessor, IEmailSender<TUser> emailSender, LinkGenerator linkGenerator)
{
/*_eventPublisher = eventPublisher;*/
_httpContextAccessor = httpContextAccessor;
_emailSender = emailSender;
_linkGenerator = linkGenerator;
}
public Task EmailConfirmed(TUser user)
=> Task.CompletedTask;
// we could do extra checks for success login
// Maybe first login from 'unknown' location? Than we could notify the user
public Task LoggedIn(string email)
=> Task.CompletedTask;
public Task LoggedInFailure(string email, string errorMessage)
=> Task.CompletedTask;
public async Task SendConfirmationEmailAsync(TUser user, string? userId, string code, string email, bool isChange = false)
{
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var routeValues = new RouteValueDictionary()
{
["userId"] = userId,
["code"] = code,
};
if (isChange)
{
// This is validated by the /confirmEmail endpoint on change.
routeValues.Add("changedEmail", email);
}
var confirmEmailUrl = _linkGenerator.GetUriByName(_httpContextAccessor.HttpContext!, ConfirmEmailEndpointStore.ConfirmEmailEndpointName, routeValues)
?? throw new NotSupportedException($"Could not find endpoint named '{ConfirmEmailEndpointStore.ConfirmEmailEndpointName}'.");
// When developer/usecase wants to create his own IIdentityHandler, he can inject IConfiguration
// and set a different host for the confirmEmailUrl by a appsettings.json key/value
await _emailSender.SendConfirmationLinkAsync(user, email, HtmlEncoder.Default.Encode(confirmEmailUrl));
}
public async Task SendPasswordResetCodeAsync(TUser user, string email, string resetCode)
{
//we could publish an event with mediatr, and let the domain solve that to do with it..
//var @event = new Domain.Model.Identity.Events.SendPasswordResetCodeEvent<TUser>(user, email, resetCode);
//await _eventPublisher.Publish(@event);
await Task.CompletedTask;
}
}
than we can change the SendConfirmationEmailAsync in the IdentityApiEndpointRouteBuilderExtensions to
async Task SendConfirmationEmailAsync(TUser user, UserManager<TUser> userManager, HttpContext context, string email, bool isChange = false)
{
var code = isChange
? await userManager.GenerateChangeEmailTokenAsync(user, email)
: await userManager.GenerateEmailConfirmationTokenAsync(user);
var userId = await userManager.GetUserIdAsync(user);
await identityCoreHandler.SendConfirmationEmailAsync(user, userId, code, email, isChange: isChange);
}
change line 47
var emailSender = endpoints.ServiceProvider.GetRequiredService<IEmailSender>();
into
var identityCoreHandler = endpoints.ServiceProvider.GetRequiredService<IIdentityCoreHandler>();
Now we have full controll what we want to do in every scanario
Steps To Reproduce
Host the IdentityApi in a non-public environment.
Exceptions (if any)
No response
.NET Version
No response
Anything else?
No response
Metadata
Metadata
Assignees
Labels
area-identityIncludes: Identity and providersIncludes: Identity and providers