TL;DR
Question: how to implement social login (OAuth2 authorization flow) with an existing SPA/Web API application that is based on identity, user/password, bearer token authentication?
I have an existing application that has:
Backend: .Net Core 2 Web API with Identity and OpenIddict services configured, with a working authentication process based on user/password challenge for bearer token.
Users are stored with Identity (AspNetUsers).
Part of the Startup.cs code
// Register the OpenIddict services.
services.AddOpenIddict()
.AddCore(options =>
{
options.UseEntityFrameworkCore().UseDbContext<ApplicationDbContext>();
})
.AddServer(options =>
{
options.UseMvc();
options.EnableTokenEndpoint("/connect/token");
options.AllowPasswordFlow();
options.AllowRefreshTokenFlow();
options.AcceptAnonymousClients();
options.RegisterScopes(
OpenIdConnectConstants.Scopes.OpenId,
OpenIdConnectConstants.Scopes.Email,
OpenIdConnectConstants.Scopes.Phone,
OpenIdConnectConstants.Scopes.Profile,
OpenIdConnectConstants.Scopes.OfflineAccess,
OpenIddictConstants.Scopes.Roles);
})
.AddValidation();
.
Frontend: SPA Angular 7 app that consumes this backend API and token authorization
So basically the current setup is, user inputs user/password to the SPA that invokes the backend /connect/token endpoint that validates the credentials and generates the token for the client.
And now I need to integrate Social Login (OAuth2 Authorization flow) so that
- user chooses login with provider,
- gets redirected to providers authorization page,
- gets redirected back to my application that
- needs to create the Identity user and save the Identity UserLoginInfo data and
- provide my application token so that the user can login.
I understand the OAuth2 authorization flow that needs to Request an Authorization Code and then Exchange Authorization Code for an Access Token for that provider. I also know that this flow must use backend, once it uses sensitive information like client_secret that can't be stored in client side.
But at some point user needs to interact with frontend, so connecting these parts seems very difficult considering that these are wide used technologies. All practical examples I found on Google were using .Net Core MVC application. I also found this article ASP.NET Core 3.0 Preview 4 - Authentication and authorization for SPAs that seems promising but is still in Preview 4.
I already created the social providers apps and I have client_id, client_secret. Also registered my redirects url's.
What I tried with no success was:
- In frontend user chooses login with social provider,
- User gets redirected to provider authorization page, authenticates himself and
- gets redirected from the provider to my frontend URL (
redirect_uri) with the provider's code then - my frontend calls my backend
/connect/tokenexisting endpoint passing the selected provider and the received code, the endpoint was programmed to receive the provider and code also, then - my backend calls provider's get AccessToken url posting
"grant_type", "authorization_code""code", code"redirect_uri", "https://same_frontend_host/same/path""client_id", providerClientId"client_secret", providerSecretand receives aStatusCode: 401, ReasonPhrase: 'Unauthorized'response
What am I doing wrong? It's been a real hard time to get this to work.
What worked but it's not what I need
An implicit 2 step authorization flow using frontend for provider authentication calls and a backend call to get my bearer token and create Identity user. With this setup user made a successful login using a social provider, unfortunately it's not what I need
EDIT:
Made a diagram of what is implemented, it is failing at step 5/6 with StatusCode: 401, ReasonPhrase: 'Unauthorized' and further steps are not completed.
