We have existing ASP.NET Core 5 WebAPI project that is not using Identity. When a user sends login credentials we issue JWT token and return it as response body. It works well.
Now we should add an ability to login using OIDC (for example Google).
I managed to send user to Identity provider and redirect them back to our backend. Here I have all information needed about that user. I would use that data to check if user is already registred in our database and if not, I would create new user. Next step would be creation of our JWT and returning it to frontend.
This part I don't know how to solve. I think I need some info from frontend to know where to send new token. Any sugestions on how to return new token to frontend app?
Controller
/// <summary>
/// The controller for handling external user related request.
/// </summary>
/// <seealso cref="Microsoft.AspNetCore.Mvc.ControllerBase" />
[ApiController]
[Route("[controller]")]
public class ExternalUserController : ControllerBase
{
private readonly IUserService _userService;
/// <summary>
/// Initializes a new instance of the <see cref="ExternalUserController"/> class.
/// </summary>
/// <param name="userService">The user service.</param>
public ExternalUserController(IUserService userService)
{
_userService = userService;
}
[HttpGet]
public async Task Login(string returnUrl = "/ExternalUser/token")
{
await HttpContext.ChallengeAsync("oidc", new AuthenticationProperties
{
RedirectUri = returnUrl
});
}
[Authorize(AuthenticationSchemes= "oidc")]
[HttpGet("token")]
public async Task<ActionResult> GetToken()
{
if (User.Identity.IsAuthenticated)
{
var nameIdentifier = User.FindFirst(ClaimTypes.NameIdentifier);
var name = User.FindFirst(ClaimTypes.Name);
var givenName = User.FindFirst(ClaimTypes.GivenName);
var surname = User.FindFirst(ClaimTypes.Surname);
var email = User.FindFirst(ClaimTypes.Email);
var mobilePhone = User.FindFirst(ClaimTypes.MobilePhone);
var authenticationMethod = User.FindFirst(ClaimTypes.AuthenticationMethod);
var emails = User.FindFirst("emails");
// Register user if not present and issue new JWT.
// How to return this to specific frontend URL?
return Ok("NEW JWT");
}
return Ok();
}
}
In ConfigureServices
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority = "https://accounts.google.com";
options.RequireHttpsMetadata = false;
options.ClientId = "MY CLIENT ID";
options.ClientSecret = "MY SECRET";
options.ResponseType = $"{OpenIdConnectParameterNames.Code} {OpenIdConnectParameterNames.IdToken}";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Events = new OpenIdConnectEvents()
{
OnTokenValidated = async y =>
{
await Task.FromResult(0);
}
};
})
.AddCookie();