通过 asp .net core 连接到 Google api 导致无休止的授权循环 [英] Connect to Google api via asp .net core causes endless authorization loop

查看:31
本文介绍了通过 asp .net core 连接到 Google api 导致无休止的授权循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试设置一个 Asp .net core 3 Web 项目,以便在用户登录后连接到 Google 日历并请求用户数据.

I am currently trying to set up an Asp .net core 3 web project to connect to Google calendar and request user data after the user has logged in.

用户登录,应用程序请求访问其数据的权限.问题从那之后开始.

The user logs in and the application requests permission to access their data. The problems start after that.

   // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlite(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();
        services.AddControllersWithViews();
        services.AddRazorPages();

        services
            .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie()
            .AddGoogleOpenIdConnect(options =>
            {
                IConfigurationSection googleAuthSection = Configuration.GetSection("Authentication:Google");
                options.ClientId = googleAuthSection["ClientId"];
                options.ClientSecret = googleAuthSection["ClientSecret"];
                options.Scope.Add(Google.Apis.Calendar.v3.CalendarService.Scope.Calendar);
            });
    }

控制器

public class CalController : Controller
{
    private readonly ILogger<CalController> _logger;

    public CalController(ILogger<CalController> logger)
    {
        _logger = logger;
    }

    [Authorize]
    public async Task<IActionResult> Index([FromServices] IGoogleAuthProvider auth)
    {
        var cred = await auth.GetCredentialAsync();
        var service = new CalendarService(new BaseClientService.Initializer
        {
            HttpClientInitializer = cred
        });
        var calendar = await service.Calendars.Get("primary").ExecuteAsync();

        return View();
    }
   
}

问题

目前系统在我身上循环.当我导航到日历控制器时出现以下错误.

Issue

Currently the system is looping on me. When i navigate to the calendar controller It comes with the following error.

所以我用以下操作创建了一个帐户控制器.

So i created an account controller with the following action.

 public IActionResult Logins([FromQuery] string returnURL)
    {
        return RedirectToAction("Index", "Cal");           
        
    }

现在只会导致整个事情循环.为什么授权属性没有检测到它已登录并通过身份验证?

Which now just causes the whole thing to loop. Why isn't the authorize attribute detecting that it is logged in and authenticated?

如果我删除授权属性.登录用户并直接转到 cal 控制器,我可以访问他们的数据,一切正常.

If I remove the authorize attribute. Login the user and go directly to the cal controller i have access to their data and it all works.

但是一旦我添加了授权属性,它就无法检测到它已通过身份验证.

But as soon as i add the authorize attributed it cant detect that it is authenticated.

我最初在 Google .net 客户端库上发布了此内容 1584 不幸的是,即使它应该可以工作,该团队也无法帮助它与 asp .net core 一起工作.

I originally posted this over on the Google .net client libary 1584 unfortunately the team was not able to assist in getting this to work with asp .net core even though it is supposed to work.

我怀疑我的设置有问题,但我无法弄清楚可能是什么问题.

I suspect there is something wrong with my setup but i am at a lost to figure out what the issue could be.

推荐答案

我终于搞定了.

public class Client
    {
        public class Web
        {
            public string client_id { get; set; }
            public string client_secret { get; set; }
        }

        public Web web { get; set; }
    }



    public class ClientInfo
    {
        public Client Client { get; set;  }

        private readonly IConfiguration _configuration;

        public ClientInfo(IConfiguration configuration)
        {
            _configuration = configuration;
            Client = Load();
        }

        private Client Load()
        {
            var filePath = _configuration["TEST_WEB_CLIENT_SECRET_FILENAME"];
            if (string.IsNullOrEmpty(filePath))
            {
                throw new InvalidOperationException(
                    $"Please set the TEST_WEB_CLIENT_SECRET_FILENAME environment variable before running tests.");
            }

            if (!File.Exists(filePath))
            {
                throw new InvalidOperationException(
                    $"Please set the TEST_WEB_CLIENT_SECRET_FILENAME environment variable before running tests.");
            }

            var x = File.ReadAllText(filePath);

            return JsonConvert.DeserializeObject<Client>(File.ReadAllText(filePath));
        }
    }

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<ClientInfo>();

            services.AddControllers();

            services.AddAuthentication(o =>
                {
                    // This is for challenges to go directly to the Google OpenID Handler, so there's no
                    // need to add an AccountController that emits challenges for Login.
                    o.DefaultChallengeScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
                    // This is for forbids to go directly to the Google OpenID Handler, which checks if
                    // extra scopes are required and does automatic incremental auth.
                    o.DefaultForbidScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme;
                    o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                })
                .AddCookie()
                .AddGoogleOpenIdConnect(options =>
                {
                    var clientInfo = new ClientInfo(Configuration);
                    options.ClientId = clientInfo.Client.web.client_id;
                    options.ClientSecret = clientInfo.Client.web.client_secret;
                });
            services.AddMvc();
        }


        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();
            
            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
        }
    }

带身份验证的控制器

[ApiController]
[Route("[controller]")]
public class GAAnalyticsController : ControllerBase
{
    
    private readonly ILogger<WeatherForecastController> _logger;

    public GAAnalyticsController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    // Test showing use of incremental auth.
    // This attribute states that the listed scope(s) must be authorized in the handler.
    [GoogleScopedAuthorize(AnalyticsReportingService.ScopeConstants.AnalyticsReadonly)]
    public async Task<GetReportsResponse> Get([FromServices] IGoogleAuthProvider auth, [FromServices] ClientInfo clientInfo)
    {
        var GoogleAnalyticsViewId = "78110423";

        var cred = await auth.GetCredentialAsync();
        var service = new  AnalyticsReportingService(new BaseClientService.Initializer
        {
            HttpClientInitializer = cred
        });
        
        var dateRange = new DateRange
        {
            StartDate = "2015-06-15",
            EndDate = "2015-06-30"
        };

        // Create the Metrics object.
        var sessions = new Metric
        {
            Expression = "ga:sessions",
            Alias = "Sessions"
        };

        //Create the Dimensions object.
        var browser = new Dimension
        {
            Name = "ga:browser"
        };

        // Create the ReportRequest object.
        var reportRequest = new ReportRequest
        {
            ViewId = GoogleAnalyticsViewId,
            DateRanges = new List<DateRange> {dateRange},
            Dimensions = new List<Dimension> {browser},
            Metrics = new List<Metric> {sessions}
        };

        var requests = new List<ReportRequest> {reportRequest};

        // Create the GetReportsRequest object.
        var getReport = new GetReportsRequest {ReportRequests = requests};

        // Make the request.
        var response = service.Reports.BatchGet(getReport).Execute();
        return response;
    }
}

这篇关于通过 asp .net core 连接到 Google api 导致无休止的授权循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆