Oauth2 login to Google api with ASP .net core MVC

2020-03-24 05:14发布

问题:

I have been following Web applications (ASP.NET MVC) Attempting to connect to one of the Google APIs.

using System;
using System.Web.Mvc;

using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Mvc;
using Google.Apis.Drive.v2;
using Google.Apis.Util.Store;

namespace Google.Apis.Sample.MVC4
{
    public class AppFlowMetadata : FlowMetadata
    {
        private static readonly IAuthorizationCodeFlow flow =
            new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = new ClientSecrets
                    {
                        ClientId = "PUT_CLIENT_ID_HERE",
                        ClientSecret = "PUT_CLIENT_SECRET_HERE"
                    },
                    Scopes = new[] { DriveService.Scope.Drive },
                    DataStore = new FileDataStore("Drive.Api.Auth.Store")
                });

        public override string GetUserId(Controller controller)
        {
            // In this sample we use the session to store the user identifiers.
            // That's not the best practice, because you should have a logic to identify
            // a user. You might want to use "OpenID Connect".
            // You can read more about the protocol in the following link:
            // https://developers.google.com/accounts/docs/OAuth2Login.
            var user = controller.Session["user"];
            if (user == null)
            {
                user = Guid.NewGuid();
                controller.Session["user"] = user;
            }
            return user.ToString();

        }

        public override IAuthorizationCodeFlow Flow
        {
            get { return flow; }
        }
    }
}

The sample doesn't appear to work with .net core as it cant find FlowMetadata

回答1:

The problem is that the above sample was not designed for .net core.

clientinfo.cs

/// <summary>
    /// Client auth information, loaded from a Google user credential json file.
    /// Set the TEST_CLIENT_SECRET_FILENAME environment variable to point to the credential file.
    /// </summary>
    public class ClientInfo
    {
        public static ClientInfo Load()
        {
            const string ClientSecretFilenameVariable = "TEST_CLIENT_SECRET_FILENAME";
            string clientSecretFilename = Environment.GetEnvironmentVariable(ClientSecretFilenameVariable);
            if (string.IsNullOrEmpty(clientSecretFilename))
            {
                throw new InvalidOperationException($"Please set the {ClientSecretFilenameVariable} environment variable before running tests.");
            }
            var secrets = JObject.Parse(Encoding.UTF8.GetString(File.ReadAllBytes(clientSecretFilename)))["web"];
            var projectId = secrets["project_id"].Value<string>();
            var clientId = secrets["client_id"].Value<string>();
            var clientSecret = secrets["client_secret"].Value<string>();
            return new ClientInfo(projectId, clientId, clientSecret);
        }

        private ClientInfo()
        {
            Load();
        }


        private ClientInfo(string projectId, string clientId, string clientSecret)
        {
            ProjectId = projectId;
            ClientId = clientId;
            ClientSecret = clientSecret;
        }

        public string ProjectId { get; }
        public string ClientId { get; }
        public string ClientSecret { get; }
    }

Program.cs

 public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args)
        {
            var clientInfo = ClientInfo.Load();

            return WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .ConfigureServices(services =>
                {
                    services.AddSingleton(clientInfo);
                })
                .Build();
        }
    }

startup.cs configure services

 services.AddAuthentication(options =>
                {
                    options.DefaultScheme = "Cookies";
                    options.DefaultChallengeScheme = "Google";
                })
                .AddCookie("Cookies")
                .AddGoogleOpenIdConnect("Google", options =>
                {
                    var clientInfo = (ClientInfo)services.First(x => x.ServiceType == typeof(ClientInfo)).ImplementationInstance;
                    options.ClientId = clientInfo.ClientId;
                    options.ClientSecret = clientInfo.ClientSecret;
                    options.Scope.Add("profile");   

                });

        }

add the following to configure as well app.UseAuthentication();

controler

[GoogleScopedAuthorize("https://www.googleapis.com/auth/analytics.readonly")]
        public async Task<IActionResult> GoogleAnalyticsReport([FromServices] IGoogleAuthProvider auth, [FromServices] ClientInfo clientInfo, long ViewId)
        {
            var cred = await auth.GetCredentialAsync();
            var service = new AnalyticsReportingService(new BaseClientService.Initializer
            {
                HttpClientInitializer = cred
            });

LogOut

 public async Task<IActionResult> Logout()
    {
        await HttpContext.SignOutAsync();
        return RedirectToAction("Index");
    }

Its now logging my user in and i can request data.