代码之家  ›  专栏  ›  技术社区  ›  Peter

正在运行asp。将OAuth2作为Azure Appservice的net core 2应用程序导致502个错误

  •  1
  • Peter  · 技术社区  · 8 年前

    我创建了一个简单的ASP。NET核心Web应用程序,使用来自Google的OAuth身份验证。我在本地机器上运行的很好。 然而,在将其作为AppService部署到Azure之后,OAuth重定向似乎变得一团糟。

    应用程序本身可以在以下位置找到:
    https://gcalworkshiftui20180322114905.azurewebsites.net/

    下面是一个url,它实际返回一个结果并显示应用程序正在运行:
    https://gcalworkshiftui20180322114905.azurewebsites.net/Account/Login?ReturnUrl=%2F

    有时,该应用程序的响应很好,但一旦我尝试使用谷歌登录,它会一直加载,最终返回以下消息:

    The specified CGI application encountered an error and the server terminated the process.
    

    在幕后,身份验证回调似乎失败,出现502.3错误:

    502.3 Bad Gateway “The operation timed out”
    

    可以在以下位置找到错误跟踪: https://gcalworkshiftui20180322114905.azurewebsites.net/errorlog.xml

    微软的文档还没有真正起到作用。
    https://docs.microsoft.com/en-us/azure/app-service/app-service-authentication-overview

    进一步调查使我相信,这与以下代码有关:

    public GCalService(string clientId, string secret)
    {
        string credPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
        credPath = Path.Combine(credPath, ".credentials/calendar-dotnet-quickstart.json");
    
        var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
            new ClientSecrets
            {
                ClientId = clientId,
                ClientSecret = secret
            },
            new[] {CalendarService.Scope.Calendar},
            "user",
            CancellationToken.None,
            new FileDataStore(credPath, true)).Result;
    
        // Create Google Calendar API service.
        _service = new CalendarService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = "gcalworkshift"
        });
    }
    

    我可以想象Azure不支持个人文件夹?在谷歌上搜索这个并不能告诉我太多。

    1 回复  |  直到 8 年前
        1
  •  2
  •   Bruce Chen    8 年前

    我跟着 Facebook, Google, and external provider authentication in ASP.NET Core Google external login setup in ASP.NET Core 创建ASP。NET核心Web应用程序,通过Google身份验证来检查此问题。

    我也跟着 .NET console application to access the Google Calendar API Calendar.ASP.NET.MVC5 来构建我的示例项目。以下是核心代码,您可以参考它们:

    启动。cs公司

        public class Startup
        {
            public readonly IDataStore dataStore = new FileDataStore(GoogleWebAuthorizationBroker.Folder); //C:\Users\{username}\AppData\Roaming\Google.Apis.Auth
            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.AddDbContext<ApplicationDbContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    
                services.AddIdentity<ApplicationUser, IdentityRole>()
                    .AddEntityFrameworkStores<ApplicationDbContext>()
                    .AddDefaultTokenProviders();
    
                services.AddAuthentication().AddGoogle(googleOptions =>
                {
                    googleOptions.ClientId = "{ClientId}";
                    googleOptions.ClientSecret = "{ClientSecret}";
                    googleOptions.Scope.Add(CalendarService.Scope.CalendarReadonly); //"https://www.googleapis.com/auth/calendar.readonly"
                    googleOptions.AccessType = "offline"; //request a refresh_token
                    googleOptions.Events = new OAuthEvents()
                    {
                        OnCreatingTicket = async (context) =>
                        {
                            var userEmail = context.Identity.FindFirst(ClaimTypes.Email).Value;
    
                            var tokenResponse = new TokenResponse()
                            {
                                AccessToken = context.AccessToken,
                                RefreshToken = context.RefreshToken,
                                ExpiresInSeconds = (long)context.ExpiresIn.Value.TotalSeconds,
                                IssuedUtc = DateTime.UtcNow
                            };
    
                            await dataStore.StoreAsync(userEmail, tokenResponse);
                        }
                    };
                });
    
                services.AddMvc();
            }
    
        }
    }
    

    日历控制器。cs公司

        [Authorize]
        public class CalendarController : Controller
        {
    
            private readonly IDataStore dataStore = new FileDataStore(GoogleWebAuthorizationBroker.Folder);
    
            private async Task<UserCredential> GetCredentialForApiAsync()
            {
                var initializer = new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = new ClientSecrets
                    {
                        ClientId = "{ClientId}",
                        ClientSecret = "{ClientSecret}",
                    },
                    Scopes = new[] {
                        "openid",
                        "email",
                        CalendarService.Scope.CalendarReadonly
                    }
                };
                var flow = new GoogleAuthorizationCodeFlow(initializer);
    
                string userEmail = ((ClaimsIdentity)HttpContext.User.Identity).FindFirst(ClaimTypes.Name).Value;
    
                var token = await dataStore.GetAsync<TokenResponse>(userEmail);
                return new UserCredential(flow, userEmail, token);
            }
    
            // GET: /Calendar/ListCalendars
            public async Task<ActionResult> ListCalendars()
            {
                const int MaxEventsPerCalendar = 20;
                const int MaxEventsOverall = 50;
    
                var credential = await GetCredentialForApiAsync();
    
                var initializer = new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "ASP.NET Core Google Calendar Sample",
                };
                var service = new CalendarService(initializer);
    
                // Fetch the list of calendars.
                var calendars = await service.CalendarList.List().ExecuteAsync();
    
                return Json(calendars.Items);
            }
        }    
    

    在部署到Azure web app之前,我更改了 folder 用于构造的参数 FileDataStore D:\home ,但出现以下错误:

    UnauthorizedAccessException:访问路径“D:\home\Google”。API。授权。OAuth2.Responses。TokenResponse-{用户标识符}被拒绝。

    然后,我尝试设置参数 文件夹 D:\home\site 并重新部署我的web应用程序,发现它可以按预期工作,并且记录的用户凭据将保存在 D: \主页\网站 azure web app服务器的。

    enter image description here

    Azure Web应用程序运行在一个称为沙盒的安全环境中,该环境有一些限制,您可以遵循一些详细信息 Azure Web App sandbox

    此外,您提到 App Service Authentication 它提供内置身份验证,而无需在代码中添加任何代码。由于您已经在web应用程序中编写了用于身份验证的代码,因此无需设置应用程序服务身份验证。

    要使用应用程序服务身份验证,您可以按照 here 对于配置,您的NetCore后端可以获取其他用户详细信息( access_token ,则, refresh_token ,等等)通过 /.auth/me 端点,详细信息您可以遵循以下类似的 issue 。检索到登录用户的令牌响应后,可以手动构造 UserCredential ,然后构建 CalendarService

    推荐文章