I'm wondering if anyone knows how you can "login" a user after you register them with Identity Server 4?

In my current setup I have a registration wizard on my website (localhost:44300). During the wizard a user will enter a Username, Email and Password which I send to my IS4 server (localhost:44310) using an http post call. On the IS4 server I create the user and then calling _signManager.SignInAsync. I have also tried calling HttpContext.SignInAsync. Upon returning to my website the user will complete the registration wizard and then be sent to our dashboard. The problem is when the user is sent to the dashboard they are asked to log in. I assume this has to do with the fact that the client is not receiving any tokens/cookies.

So does anyone know how I might accomplish this? Note the closest question I found was this one but it has not been answered: Identity Server 4 Auto Login After Registration

Please let me know if something is quite clear on what I am trying to accomplish.

Thank you for your time.

Client Startup

services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
    options.SignInScheme = "Cookies";
    options.Authority = "https://localhost:44310/";
    options.ClientId = "Id";
    options.ClientSecret = "Secret";
    options.RequireHttpsMetadata = true;
    options.ResponseType = "code id_token";
    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = false;
    options.SignedOutRedirectUri = "https://localhost:44300/";
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("Identity");
});

Client Register

var disco = await Client.GetDiscoveryDocumentAsync("https://localhost:44310/");
if (disco.IsError)
{
    throw new Exception(disco.Error);
}

var tokenResponse = await Client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
    Address = disco.TokenEndpoint,

    ClientId = "Id",
    ClientSecret = "Secret",
    Scope = "Identity"
});

if (tokenResponse.IsError)
{
    throw new Exception(tokenResponse.Error);
}

var token = tokenResponse.AccessToken;
Client.SetBearerToken(tokenResponse.AccessToken);

var myContent = JsonConvert.SerializeObject(new {
    model.Username,
    model.Email,
    model.Password,
    Claims = new List<string> {"User"},
});
var response = await Client.PostAsync("Account/register", new StringContent(myContent, Encoding.UTF8, "application/json"));

return await response.Content.ReadAsAsync<Models.RegistrationResponse>();

IS4 Register

[Authorize]
[HttpPost]
public async Task<IActionResult> Register([FromBody]RegistrationRequest model)
{ 
    user = new IdentityUser()
    {
        UserName = model.Username,
        Email = model.Email,
    };
    var result = await _userManager.CreateAsync(user, model.Password);

    if (result.Succeeded)
    {
        var cliams = new List<Claim>();

        foreach (var claim in model.Claims)
        {
            cliams.Add(new Claim(claim, ""));
        }
        await _userManager.AddClaimsAsync(user, cliams);

        await _signManager.SignInAsync(user, true);//I was originally just doing this

        //I tried copying what Account/Login does, which is the following lines
        await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName));

        await HttpContext.SignInAsync(user.Id, user.UserName);
        ////////////////////////////

        return Ok(new RegistrationResponse()
        {
            Successful = true,
            UserId = user.Id,
        });
    }
}

0 Answers