dotnet / dotnet/aspnetcore

Identity Endpoints API - Optional "CallbackUrl"

Open
#50,904 6 comments 2 reactions 0 assignees View on GitHub
api-suggestion area-identity enhancement feature-identity-apis
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 10h
Merged PRs (30d)
281

Description

## Background and Motivation

I'd like an optional `string? CallbackUrl` since I'll likely have **multiple** frontends on different (sub)domains, consuming the same Auth API.
Passing that (sub)domain URL all the way through, would enable that.

For example, https://www.leashr.com & https://www.belgiandoggos.be use the same API for authentication & authorization.
Setting either one in my `appSettings.json` won't cut it.

So, I prefer you just make the parameters available so we can form our own URLs and decide whether it goes to a frontend or backend. Then, I can also choose to use route parameters rather than query string parameters on my Blazor frontends.

Feel free to watch my implementation of RC1: https://youtu.be/yGYpN1hFPAg?si=zlLykBIas_WBjXWN

## Proposed API

```csharp

Task SendConfirmationEmailAsync(TUser user, string email, string code, string confirmationLink, string? callbackUrl) where TUser : class
{
return SendEmailAsync(email, code, confirmationLink, callbackUrl);
}

// Merged ResetCode & ResetLink into one.
Task SendPasswordResetEmailAsync(TUser user, string email, string resetCode, string resetLink, string? callbackUrl) where TUser : class
{
return SendEmailAsync(email, resetCode, resetLink, callbackUrl);
}

```

```csharp

public sealed class NoOpEmailSender : IEmailSender
{
public Task SendEmailAsync(string email, string code, string link, string? callbackUrl) => Task.CompletedTask;
}

```

#### DTO

You'll need to add the `string? CallbackUrl` property to your request & response DTO's as well to pass the value all the way down and back to the consumer.

## Usage Examples

```csharp

public async Task SendConfirmationEmailAsync(TUser user, string email, string code, string confirmationLink, string? callbackUrl) where TUser : class
{
var frontendConfirmationLink = $"clicking here";

await SendEmailAsync(email, $"{user.Name}, confirm your email", $"Please confirm message (in my native language) {frontendConfirmationLink}.");
}

// Merged ResetCode & ResetLink into one.
public async Task SendPasswordResetEmailAsync(TUser user, string email, string resetCode, string resetLink, string? callbackUrl) where TUser : class
{
var frontendResetLink = $"clicking here";

await SendEmailAsync(email, $"{user.Name}, reset your password", $"Reset password message (in my native language): {frontendResetLink}");
}

```

## Alternative Designs

The formed links are fine as an example but a pain to extract from & reformat.
The subject & message are likely to be translated or changed, so mainly serve as an example as well.
I don't think you need either of the above but feel free to leave those in.

## Risks

Will need good documentation to prevent confusion about being able to use the provided link but also to use the parameters to form your own link.

Contributor guide

Open the contributing guide

Research direction

Start with the Identity endpoints API, IEmailSender/NoOpEmailSender, the confirmation and password-reset methods, and the related request and response DTOs mentioned in the issue. Trace how these values move through the authentication flow and check existing tests or documentation before deciding the API shape. Done means an optional CallbackUrl can reach the email sender and consumers without breaking existing callers.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
api, authentication, backend-api-design
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.