What you can do with this library?

On backend you could verify AuthCode (passed from your SPA) and get user information from oAuth provider

If you're using IdentityServer, you could plug-in an extension grant that will allow you to issue your own JWT tokens in exchange for AuthCode (and optionally create new users).

Goal

The project goal is to allow easy integration of external OAuth providers (e.g. Google, Facebook, etc.) into your SPA applications (React, Angular, plain-old-js, whatever), with the minimum amount of needed code.
This is a backend library, that integrates with Asp.Net Core 2.2+.
The library is kept minimal, as we reuse all official and non-official authentication providers (i.e. library doesn't need to be updated when those external providers change).

How to

Just install nuget to add the library to your project.

dotnet add package IdentityOAuthSpaExtensions

You could also take a look at IdentityOAuthSpaExtensions.Example for example usage (keep in mind, that there are hardcoded ClientId/ClientSecret for FB and Google within Example app. They are for demo purposes and everyone can use them, so beware).

Backend

That's it. Just .AddAuthentication.AddGoogle() or .AddFacebook() to make it work. Follow instructions on how to set up applications on OAuth provider side. You should specify https://YOUR_BACKEND/external-auth/callback-{providerName} as a return URL (https://YOUR_BACKEND/external-auth/callback-google, https://YOUR_BACKEND/external-auth/callback-facebook, etc.)

After that you will be able to request AuthCode from SPA (instructions below), and manually verify AuthCode on backend:
this.HttpContext.RequestServices.GetService<ExternalAuthService>().GetExternalUserId(providerName, authCode)
or
this.HttpContext.RequestServices.GetService<ExternalAuthService>().GetExternalUserInfo(providerName, authCode)

to obtain access_token, that you could later use in Authorization header.

Identity Server integration

Adding external grant (validate Auth Code and issue own JWT)

Typical scenario is that you use oAuth for authentication only, and then create the user in your local DB (via e.g. IdentityServer) and issue your own JWT with custom claims for later authorization.
This library perfectly supports this scenario in combination with IdentityServer using extension grants (https://docs.identityserver.io/en/latest/topics/grant_types.html#extension-grants).
To integrate with IdentityServer all you need to do is call
services.AddIdentityServer().AddExtensionGrantValidator<ExternalAuthenticationGrantValidator<IdentityUser, string>>().
That will register an extension grant named external and you could authenticate from JS as described above

Configuration

By default, ExternalAuthenticationGrantValidator is configured to create new users automatically, when they successfully authenticate via oAuth. You could change that behavior by setting:
services.ConfigureExternalAuth(Configuration, options => { options.CreateUserIfNotFound = false; });.

Customization

You could inherit from ExternalAuthenticationGrantValidator<IdentityUser, string> and provide your custom logic for any of the following methods:

CreateNewUser - fill-in the fields of new User based on your business requirements and/or information received from oAuth provider

CreateResultForLocallyNotFoundUser - here you could write your own business logic, regarding what to do when the user is logging in for the first time. You could write custom logic for user creation, or deny some users (based on email/id) from logging in.

GetUserName - most useful if you don't override CreateNewUser. You could provide Username for newly created users based on oAuth provider info

External user storage

We use standard Asp.Net Identity mechanism to store external logins (namely, AspNetUserLogins table). To find a user by external OAuth id you need to use _userManager.FindByLoginAsync(providerName, externalUserId)