How to implement account linking in Blazor Web App?

44 views Asked by At

I want to get the user for example to be able to register with Steam and be able to link his Discord account.

So far I have managed to get a user to register with Steam (or any provider like Google) but I have not found any documentation on how to link accounts (Google => Discord). So far i have this:

Program.cs

builder.Services.AddAuthentication(opt =>
    {
        opt.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        opt.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        opt.DefaultChallengeScheme = DiscordAuthenticationDefaults.AuthenticationScheme;
    })
    .AddCookie(opt =>
    {
        opt.LoginPath = "/signin";
        opt.LogoutPath = "/signout";
    }
    )
    .AddDiscord(x =>
    {
        x.ClientId = builder.Configuration.GetSection("Keys")["ClientID"];
        x.ClientSecret = builder.Configuration.GetSection("Keys")["SecretID"];

        x.SaveTokens = true;
    })
    .AddSteam(x =>
    {
        x.ApplicationKey = builder.Configuration.GetSection("Keys")["SteamID"];
        
        x.SaveTokens = true;
    });

AuthController.cs

[HttpPost("~/signin")]
public async Task<IActionResult> SignIn([FromForm] string provider)
{
    if (string.IsNullOrWhiteSpace(provider))
    {
        return BadRequest();
    }

    if (!await HttpContext.IsProviderSupportedAsync(provider))
    {
        return BadRequest();
    }

    // Instruct the middleware corresponding to the requested external identity
    // provider to redirect the user agent to its own authorization endpoint.
    // Note: the authenticationScheme parameter must match the value configured in Startup.cs
    return Challenge(new AuthenticationProperties { RedirectUri = "/" }, provider);
}

[HttpGet("~/signout")]
[HttpPost("~/signout")]
public IActionResult SignOutCurrentUser()
{
    // Instruct the cookies middleware to delete the local cookie created
    // when the user agent is redirected from the external identity provider
    // after a successful authentication flow (e.g Google or Facebook).
    return SignOut(new AuthenticationProperties { RedirectUri = "/" },
        CookieAuthenticationDefaults.AuthenticationScheme);
}

HttpContextExtensions.cs The functions present in this class is to determine what provider want to use the user and if supported.

public static class HttpContextExtensions
{
    public static async Task<AuthenticationScheme[]> GetExternalProvidersAsync(this HttpContext context)
    {
        ArgumentNullException.ThrowIfNull(context);

        var schemes = context.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>();

        return (from scheme in await schemes.GetAllSchemesAsync()
                where !string.IsNullOrEmpty(scheme.DisplayName)
                select scheme).ToArray();
    }

    public static async Task<bool> IsProviderSupportedAsync(this HttpContext context, string provider)
    {
        ArgumentNullException.ThrowIfNull(context);

        return (from scheme in await context.GetExternalProvidersAsync()
                where string.Equals(scheme.Name, provider, StringComparison.OrdinalIgnoreCase)
                select scheme).Any();
    }
}

Finally, for auth i'm using AspNet.Security.OAuth.Discord and AspNet.Security.OpenId.Steam mostly of the code that I show can be found in the sample folder of the github.

0

There are 0 answers