Как войти во внешний ClaimsIdentity, используя IdentityUser Asp.Net Core 2.2? - PullRequest
0 голосов
/ 16 мая 2019

Контекстная информация

Я создаю прототип WebApp, который я хочу интегрировать в Quickbooks Online.

Это WebApp, в свою очередь, будетпредложить варианты для вызова WebApi, который будет отвечать за запросы к WebApi Quickbooks Online.

Для этого я зарегистрировал службы Identity, чтобы мне было проще входить в систему и т. д.

Теперь, похоже, я запутался между индивидуальной учетной записью (IdentityUser) и ClaimsIdentity.

Вход в систему

Когда я щелкаю опцию «Вход в систему» ​​в верхнем меню, меня корректно перенаправляют на экран онлайн-аутентификации Quickbooks, где:

  • Я ввожу свои учетные данные пользователя
  • Я выбираю компанию, которую хочуиспользуйте
  • Я разрешаю WebApp получить доступ к необходимым областям

При обратном вызове я выполняю запрос к конечной точке информации о пользователе и извлекаю всю необходимую информацию о пользователе.

  • sub
  • GivenName
  • familyName
  • email
  • emailVerified

И

  • ClaimsIdentity.IsAuthenticated == true

Итак, я создаю список утверждений для ClaimsPrincipal.Identity, который только что был аутентифицирован извне, и пытаюсь войти в него.

var result = JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
var user = (ClaimsIdentity)context.Principal.Identities.Single(claimsIdentity => claimsIdentity.AuthenticationType == "ecm-qbo");
user.AddClaim(new Claim(type: ClaimTypes.Name, result["givenName"]));
result.ToList().ForEach(kvp => {
    user.AddClaim(new Claim(type: kvp.Key, value: kvp.Value, valueType: null, issuer: "qbo", originalIssuer: "qbo", subject: user));
});

Но я получаю эту ошибку, когда мой процесс подписания завершен.

Error loading external login information

Что я могу сделать, чтобы избежать этого, илиисправить это так, чтобы он подписал моего пользователя?

Пример кода

    public void ConfigureServices(IServiceCollection services) {
        services.Configure<CookiePolicyOptions>(options => {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.ConfigureApplicationCookie(o => {
            o.Cookie.Name = "auth_cookie";
            o.Cookie.SameSite = SameSiteMode.None;

            o.Events.OnRedirectToLogin = context => {
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                return Task.CompletedTask;
            };
        });

        services.AddAuthentication(o => {
            o.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            o.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            o.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        })
            .AddOAuth("qbo", "qbo", o => {
                o.CallbackPath = new PathString("/signin-qbo");
                o.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub");
                o.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
                o.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "givenName");
                o.ClaimActions.MapJsonKey(ClaimTypes.Surname, "familyName");
                o.ClaimActions.MapJsonKey(ClaimTypes.Name, "givenName");
                o.ClientId = Configuration["ecm.qbo.client-id"];
                o.ClientSecret = Configuration["ecm.qbo.client-secret"];
                o.SaveTokens = true;
                o.ClaimsIssuer = "ecm-qbo";
                o.Scope.Add("openid");
                o.Scope.Add("profile");
                o.Scope.Add("email");
                o.Scope.Add("com.intuit.quickbooks.accounting");

                o.AuthorizationEndpoint = Configuration["ecm.qbo.authorization-endpoint"];
                o.TokenEndpoint = Configuration["ecm.qbo.token-endpoint"];
                o.UserInformationEndpoint = Configuration["ecm.qbo.user-info-endpoint"];

                o.Events.OnCreatingTicket = async context => {
                    var companyId = context.Request.Query["realmid"].FirstOrDefault() ?? throw new ArgumentNullException("realmId");
                    var accessToken = context.AccessToken;
                    var refreshToken = context.RefreshToken;
                    var tokens = context.Properties.GetTokens();

                    Configuration["ecm.qbo.access-token"] = accessToken;
                    Configuration["ecm.qbo.refresh-token"] = refreshToken;
                    Configuration["ecm.qbo.realm-id"] = companyId;

                    context.Backchannel.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
                    context.Backchannel.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    var response = await context.Backchannel.GetStringAsync(context.Options.UserInformationEndpoint);

                    var result = JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
                    var user = (ClaimsIdentity)context.Principal.Identities.Single(claimsIdentity => claimsIdentity.AuthenticationType == "ecm-qbo");
                    user.AddClaim(new Claim(type: ClaimTypes.Name, result["givenName"]));
                    result.ToList().ForEach(kvp => {
                        user.AddClaim(new Claim(type: kvp.Key, value: kvp.Value, valueType: null, issuer: "qbo", originalIssuer: "qbo", subject: user));
                    });

                    await context.HttpContext.SignInAsync(IdentityConstants.ExternalScheme, context.Principal, new AuthenticationProperties {
                        IsPersistent = false,
                        RedirectUri = "/"
                    });
                };
            });

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));

        services.AddIdentity<IdentityUser, IdentityRole>()
            .AddDefaultUI(UIFramework.Bootstrap4)
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...