📄 src/Api/YouTubeAuth/YouTubeAuthExtensions.cs
using Google.Apis.Auth.AspNetCore3;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Slopper.Infrastructure.YouTube;

namespace Slopper.Api.YouTubeAuth;

public static class YouTubeAuthExtensions
{
    extension(AuthenticationBuilder auth)
    {
        public AuthenticationBuilder AddYouTube()
        {
            auth.AddGoogleOpenIdConnect(
                GoogleOpenIdConnectDefaults.AuthenticationScheme,
                options =>
                {
                    options.CallbackPath = "/admin/redirect/youtube";
                    options.ResponseMode = OpenIdConnectResponseMode.Query;
                }
            );

            auth.Services.AddOptions<OpenIdConnectOptions>(GoogleOpenIdConnectDefaults.AuthenticationScheme)
                .BindConfiguration("YouTube");

            auth.Services.AddTransient<IAuthorizationHandler, YouTubeScopeAuthorizationHandler>();

            auth.Services.AddTransient<IYouTubeCredentialsProvider, YouTubeCredentialsProvider>();

            return auth;
        }
    }

    extension(AuthorizationBuilder auth)
    {
        public AuthorizationBuilder AddYouTubePolicy() =>
            auth.AddPolicy(
                "YouTube",
                policy =>
                    policy
                        .AddAuthenticationSchemes(GoogleOpenIdConnectDefaults.AuthenticationScheme)
                        .RequireAuthenticatedUser()
                        .AddRequirements(new YouTubeScopeRequirement("https://www.googleapis.com/auth/youtube.upload"))
            );
    }
}