如何验证与外部提供程序(Google)的HttpClient连接

时间:2019-10-23 04:03:00

标签: c# .net asp.net-web-api openid google-authentication

编辑:

我的问题改写为:

我有一台具有安全的api端点的Web服务器-必须在使用它们之前先通过Google认证。我为此实现了ChallengeCallback端点。

这在具有我的SPA Web前端的浏览器中效果很好。用户被重定向到Google网站以登录,然后被重定向回我的webapp;然后浏览器将具有经过身份验证的cookie,并且Webapp可以使用端点来更新其状态。

我还有一个WPF应用程序,它将与Web服务器通信。 我希望WPF应用程序执行与Web前端相同的操作:在通过Google身份验证后,使用Web api端点。 WPF应用程序和我的Web服务器之间的连接是通过HttpClient完成的。​​

我的问题是我不知道如何验证WPF应用程序和Web服务器之间的HttpClient连接。

我尝试使用相同的Challenge端点,但是得到的响应当然是Google登录页面中的HTML,所以我想我不能将它与HttpClient一起使用...

我还尝试通过WPF应用使用GoogleApis进行身份验证,并使用经过身份验证的令牌在HttpClient中设置cookie,但这显然不兼容。

如何通过外部提供商(例如Google)对与Web api的HttpClient连接进行身份验证?


原始问题:

在WPF应用程序中,用户使用以下代码向Google进行身份验证:

using Google.Apis.Auth.OAuth2;
...
public void Authenticate()
{
    UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
        new ClientSecrets
        {
            ClientId = "myClientId",
            ClientSecret = "myClientSecret"
        },
        new[] { "email", "openid" },
        "user",
        CancellationToken.None).Result;
}

这有效,并且UserCredential对象包含已验证的令牌:

enter image description here

如何将此令牌信息嵌入通过HttpClient发出的Web请求中以调用我的webapi端点?

我认为该请求必须包含一些cookie才能通知服务器它已通过身份验证,但是我不知道确切地是哪个cookie。

服务器端的终结点通过IdentityServer验证用户的身份:

var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);
if (result?.Succeeded != true)
{
    throw new Exception("External authentication error");
}

4 个答案:

答案 0 :(得分:2)

如果我的问题正确,那么您只需设置Authorization标头

var credentials = await GoogleWebAuthorizationBroker.AuthorizeAsync(
        clientSecrets,
        new[] { "email", "openid" },
        "user",
        CancellationToken.None);

_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
        credentials.Token.TokenType, 
        credentials.Token.IdToken);

答案 1 :(得分:0)

也许您会在下面找到有用的提示,以更好地了解OpenID:)

混淆源于混合使用GoogleApis和IdentityServer框架。 认证/授权可以使用它们之一来实现。 Google.Apis.Auth.OAuth2和IdentityServer4命名空间中的对象并非旨在进行交互。 当然,不需要手动处理cookie。

问问自己,Google为用户提供了哪些信任。如果回拨到WPF,则信任WPF的webapi是一个单独的问题。

答案 2 :(得分:0)

您在问题中回答自己的问题:

  

然后,浏览器将具有经过身份验证的cookie,并且Webapp可以使用   端点更新其状态

HttpClient需要发送那些相同的cookie。 How do I set a cookie on HttpClient's HttpRequestMessage

答案 3 :(得分:0)

如果我正确理解了您的问题,那么不久前我也遇到了同样的问题。

我实现的方式是在后端,无论谁尝试访问端点,他们都必须发送Bearer X授权令牌。 令牌包含要访问资源的客户端的身份,我检查了是否允许他访问。

无论哪种客户端想要访问端点,它都只需要在他发送的请求中具有该身份验证标头,后端便会对其进行相同处理。

在我的场景中,我使用了一种身份验证服务,该服务通过一个包含身份信息的特定JWT将cookie返回给客户端。 然后,从客户端,我将从身份验证服务收到的JWT作为授权标头发送到后端的每个请求。

我必须将从服务接收的JWT放在标头中的原因是,身份验证服务和后端服务不在同一域中,因此无法共享cookie。

这样的设计使得无论您如何验证客户端,最终结果都必须是后端可以接收和读取的某种令牌。

希望这会有所帮助。