In the last part of the series, we discuss the way we can define OAuth2Clients, create classes to read data from appsettings.json, and the way we can register and use OAuth2MultiClientIntegrator.

1-AddOAuth2MultiClientIntegratorClients

public static class ConfigureOAuth2MultiClientIntegratorClients
{
  public static IServiceCollection AddOAuth2MultiClientIntegratorClients
    (this IServiceCollection services, ConfigurationManager configuration)
  {
    services.Configure<OAuth2IntegrationsOptions>
      (options => configuration.GetSection
      ("OAuth2Integrations").Bind(options));

    var options = services.BuildServiceProvider()
      .GetRequiredService<IOptions<OAuth2IntegrationsOptions>>();

    services.AddOAuth2MultiClientIntegratorClient(
      new OAuth2Client
      (
        new ClientCredentialOptions
        {
          ClientName = "ARegularClient",
          ClientId = options.Value.ARegularClientSettings.ClientSettings.ClientId,
          ClientSecret = options.Value.ARegularClientSettings.ClientSettings.ClientSecret
        },
        new AuthenticationCodeOptions
        {
          BaseAuthenticationUri = "BaseAuthenticationUri",
          TargetUri = options.Value.ARegularClientSettings.ClientSettings.TargetUri,
          Scope = "Scope",
          NonestandardSettings = new List<KeyValuePair<string, string>>
          {
            new KeyValuePair<string, string>("account_type","service")
          },
          StaticExpirationValue = 600,
        },
        new AccessTokenOptions
        {
          BaseAccessTokenUri = "BaseAccessTokenUri"
        }
      )
    );
    services.AddOAuth2MultiClientIntegratorClient(
      new OAuth2Client
      (
        new ClientCredentialOptions
        {
          ClientName = "GoogleClient",
          ClientId = options.Value.FacebookSettings.ClientSettings.ClientId,
          ClientSecret = options.Value.FacebookSettings.ClientSettings.ClientSecret
        },
        new AuthenticationCodeOptions
        {
          BaseAuthenticationUri = "https://accounts.google.com/o/oauth2/v2/auth",
          TargetUri = options.Value.FacebookSettings.ClientSettings.TargetUri,
          Scope = "https://www.googleapis.com/auth/business.manage",
          StaticExpirationValue = 60
        },
        new AccessTokenOptions
        {
          BaseAccessTokenUri = "https://oauth2.googleapis.com/token"
        }
      )
    );
    services.AddOAuth2MultiClientIntegratorClient(
      new OAuth2Client
      (
        new ClientCredentialOptions
        {
          ClientName = "FacebookClient",
          ClientId = options.Value.GoogleSettings.ClientSettings.ClientId,
          ClientSecret = options.Value.GoogleSettings.ClientSettings.ClientSecret
        },
        new AuthenticationCodeOptions
        {
          BaseAuthenticationUri = "https://www.facebook.com/v18.0/dialog/oauth",
          TargetUri = options.Value.GoogleSettings.ClientSettings.TargetUri,
          Scope = "public_profile,email",
          StaticExpirationValue = 60,
          NonestandardSettings = new List<KeyValuePair<string, string>>
          {
            new KeyValuePair<string, string>("config_id","SomeValue")
          }
        },
        new AccessTokenOptions
        {
          BaseAccessTokenUri = "https://graph.facebook.com/v18.0/oauth/access_token",
          StaticExpirationValue = 5184000,
          CanRenewAfterExpiration = false
        },
        new RefreshTokenOptions
        {
          GrantType = "fb_exchange_token",
          StaticExpirationValue = 5184000,
          CanRenewAfterExpiration = false,
          StandardAlternativeNamePairs = new List<Tuple<string, string>>
          {
            new Tuple<string, string>( "refresh_token","fb_exchange_token")
          },
          NonestandardSettings = new List<KeyValuePair<string, string>>
          {
            new KeyValuePair<string, string>("set_token_expires_in_60_days","true")
          }
        }
      )
    );

    return services;
  }
}

In the above code, we see the registration of three different OAuth2Clients. The settings for the one named ARegularClient are for the client that completely complies with OAuth 2.0 specification. After that, As we said earlier, Facebook and Google settings have slight deviations from the accepted standard. You should replace your credentials and other information with what has been written. You can add your non-standard settings for Facebook and Google with the NonestandardSettings option. Additionally, for clients such as Facebook and Google, settings come with different names. In this situation, you can use StandardAlternativeNamePairs to introduce the alternative names. Some clients have a specified value for the expiration of the authentication code, we can set this value by using the StaticExpirationValue property.

2-Option Classes

public class OAuth2IntegrationsOptions
{
  public const string OAuth2Integrations = "OAuth2Integrations";
  public ARegularClientSettings ARegularClientSettings { get; set; }
  public FacebookSettings FacebookSettings { get; set; }
  public GoogleSettings GoogleSettings { get; set; }
}

public class ARegularClientSettings
{
  public ClientSettings ClientSettings { get; set; }
}
public class FacebookSettings
{
  public ClientSettings ClientSettings { get; set; }
}
public class GoogleSettings
{
  public ClientSettings ClientSettings { get; set; }
}
public class ClientSettings
{
  public string ClientId { get; set; }
  public string ClientSecret { get; set; }
  public string TargetUri { get; set; }
}

The above classes are the ones we can use to read data from appsettings.json

3-Content of appsettings.json

 "OAuth2Integrations": {
  "ARegularClientSettings": {
   "ClientSettings": {
    "ClientId": "ClientId",
    "ClientSecret": "ClientSecret",
    "TargetUri": "/"
   }
  },
  "FacebookSettings": {
   "ClientSettings": {
    "ClientId": "ClientId",
    "ClientSecret": "ClientSecret",
    "TargetUri": "/"
   }
  },
  "GoogleSettings": {
   "ClientSettings": {
    "ClientId": "ClientId",
    "ClientSecret": "ClientSecret",
    "TargetUri": "/"
   }
  }
 }

The above JSON data should be placed in appsettings.json. Whenever you need a new client, you can easily add a new settings section.

4-Add DI configurations to program.cs

public class Program
{
	public static void Main(string[] args)
    {
      var builder = WebApplication.CreateBuilder(args);

.
.

      builder.Services.AddHttpContextAccessor();
      builder.Services.AddHttpClient();

      builder.Services.AddOAuth2MultiClientIntegratorServices(builder.Configuration);
      builder.Services.AddOAuth2MultiClientIntegratorClients(builder.Configuration);

      var app = builder.Build();

.
.

      app.UseOAuth2MultiClientIntegrator();

      app.Run();
    }
}

Finally, to use the package, the only thing you need is to add what has been added to the above program class. For the sake of simplicity, we have removed pre-existing service registrations.