. Net Core 3. + OAuth-аутентификация для распределенного сценария в kubernetes - PullRequest
0 голосов
/ 03 апреля 2020

У меня есть приложение, в котором я сейчас использую GitHub и GitLab в качестве поставщиков OAuth2.0. На данный момент приложение было единственным экземпляром, что означало, что после авторизации инфраструктура позаботилась обо всем остальном, используя httpContext, и, поскольку был только один экземпляр, мне не нужно было заботиться о синхронизации контекста в распределенной установке.

Требования к масштабируемости означают, что мы взяли маршрут в kubernetes, и в будущем у нас будут дополнительные копии API. Это оказалось проблемой, fx:

У меня есть настройка на 3 реплики за балансировщиком нагрузки, я авторизовался как обычно, и все работало нормально, пока я не сделал последующие вызовы, которые были направлены на другую реплику, которая не разделяла контекст авторизации.

Каков наилучший метод для OAuth2.0 в. Net Core 3. + в распределенном контексте с токенами на стороне сервера?

В моей текущей настройке оба провайдера были настроены в методе startup.cs configureServices с использованием стандартных AddAuthentication и AddOAuth, как показано ниже: (Это довольно многословно, просто для пояснения и для того, чтобы помочь другим, если интересно, Дайте мне знать, если вы хочу, чтобы оно было сокращено).

services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = "GitHub";
                })
                .AddCookie()
                .AddOAuth("GitHub", options =>
                {
                    options.ClientId = Configuration["GitHub:ClientId"];
                    options.ClientSecret = Configuration["GitHub:ClientSecret"];
                    options.CallbackPath = new PathString("/account/signin-github");

                    options.AuthorizationEndpoint = "https://github.com/login/oauth/authorize";
                    options.TokenEndpoint = "https://github.com/login/oauth/access_token";
                    options.UserInformationEndpoint = "https://api.github.com/user";

                    options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
                    options.ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
                    options.ClaimActions.MapJsonKey("urn:github:login", "login");
                    options.ClaimActions.MapJsonKey("urn:github:url", "html_url");
                    options.ClaimActions.MapJsonKey("urn:github:avatar", "avatar_url");

                    options.SaveTokens = true;

                    options.Events = new OAuthEvents
                    {
                        OnCreatingTicket = async context =>
                        {
                            var request =
                                new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
                            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                            request.Headers.Authorization =
                                new AuthenticationHeaderValue("Bearer", context.AccessToken);

                            var response = await context.Backchannel.SendAsync(request,
                                HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
                            response.EnsureSuccessStatusCode();

                            var user = JsonDocument.Parse(await response.Content.ReadAsStringAsync());

                            context.RunClaimActions(user.RootElement);
                        }
                    };
                })
                .AddOAuth("GitLab", options =>
                {
                    options.ClientId = Configuration["GitLab:ClientId"];
                    options.ClientSecret = Configuration["GitLab:ClientSecret"];
                    options.CallbackPath = new PathString("/account/signin-gitlab");

                    options.AuthorizationEndpoint = "https://gitlab.com/oauth/authorize";
                    options.TokenEndpoint = "https://gitlab.com/oauth/token";
                    options.UserInformationEndpoint = "https://gitlab.com/api/v4/user";

                    options.SaveTokens = true;

                    options.Events = new OAuthEvents
                    {
                        OnCreatingTicket = async context =>
                        {
                            var request =
                                new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
                            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                            request.Headers.Authorization =
                                new AuthenticationHeaderValue("bearer", context.AccessToken);
                            var response = await context.Backchannel.SendAsync(request,
                                HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
                            response.EnsureSuccessStatusCode();

                            var user = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
                            context.RunClaimActions(user.RootElement);
                        }
                    };
                });
...