简体   繁体   English

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

[英]How to authenticate an HttpClient connection with an external provider (Google)

Edit:编辑:

Here is my question reformulated:这是我重新提出的问题:

I have a web server with secured api endpoints - one must have been authenticated with Google prior to using them.我有一台 web 服务器,带有安全的 api 端点——在使用它们之前,必须先通过 Google 的身份验证。 I implemented Challenge and Callback endpoints for that.我为此实现了ChallengeCallback端点。

This works well from a browser with my SPA web front-end.这适用于带有我的 SPA web 前端的浏览器。 The user gets redirected to the Google website to sign-in and then gets redirected back to my webapp;用户被重定向到谷歌网站进行登录,然后被重定向回我的 webapp; the browser then has the authenticated cookies and the webapp can use the endpoints to update its state.然后浏览器拥有经过身份验证的 cookies 并且 webapp 可以使用端点更新其 state。

I also have a WPF application that will communicate with the web server.我还有一个 WPF 应用程序,它将与 web 服务器通信。 I want the WPF application to do the same as the web front-end: Use the web api endpoints after being authenticated with Google. I want the WPF application to do the same as the web front-end: Use the web api endpoints after being authenticated with Google. The connection between the WPF application and my web server is done through an HttpClient. WPF 应用程序和我的 web 服务器之间的连接是通过 HttpClient 完成的。

My problem is I don't know how to authenticate that HttpClient connection between the WPF app and the web server.我的问题是我不知道如何验证 WPF 应用程序和 web 服务器之间的 HttpClient 连接。

I tried using the same Challenge endpoint but the response I get is of course the HTML from the Google Sign-In page, so I guess I can't use that with an HttpClient...我尝试使用相同的Challenge端点,但我得到的响应当然是来自 Google 登录页面的 HTML,所以我想我不能将它与 HttpClient 一起使用......

I also tried authenticating with GoogleApis from the WPF app and use the authenticated token to set cookies in the HttpClient but apparently this is not compatible.我还尝试使用 WPF 应用程序中的 GoogleApis 进行身份验证,并使用经过身份验证的令牌在HttpClient中设置 cookies 但显然这不兼容。

How to authenticate an HttpClient connection to a web api with an external provider such as Google?如何使用 Google 等外部提供商验证与 web api 的 HttpClient 连接?


Original question:原始问题:

From a WPF application, the user authenticates with Google with this code:从 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;
}

This works and the UserCredential object contains the authenticated token:这有效,并且UserCredential object 包含经过身份验证的令牌:

在此处输入图像描述

How to embed this token information in a web request made with an HttpClient in order to call my webapi endpoint?如何将此令牌信息嵌入到使用HttpClient发出的 web 请求中以调用我的 webapi 端点?

I think the request must include some cookies to inform the server that it has been authenticated, but I don't know which ones exactly.我认为请求必须包含一些 cookies 以通知服务器它已通过身份验证,但我不知道具体是哪些。

The endpoint on the server-side validates that the user is authenticated with the help of IdentityServer:服务器端的端点在 IdentityServer 的帮助下验证用户是否经过身份验证:

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

If I got your question right, you just have to set the Authorization header如果我的问题正确,您只需设置Authorization header

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

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

Maybe you'll find below a helpful hint to better understand OpenID:)也许您会在下面找到一个有用的提示,以更好地理解 OpenID:)

The confusion stems from mixing GoogleApis and IdentityServer frameworks.混淆源于混合了 GoogleApis 和 IdentityServer 框架。 Authentication/authorization can be achieved using either of them.可以使用其中任何一个来实现身份验证/授权。 Objects from Google.Apis.Auth.OAuth2 and IdentityServer4 namespaces are not designed to interact. Google.Apis.Auth.OAuth2 和 IdentityServer4 命名空间中的对象并非旨在交互。 No manual cookie handling is necessary, for sure.当然,不需要手动处理 cookie。

Ask yourself to whom does Google provide trust for the user.问问自己,Google 为用户提供了对谁的信任。 If it calls back to WPF, then webapi trusting WPF is a separate issue.如果它回调 WPF,那么 webapi 信任 WPF 是一个单独的问题。

You answer your own question in the question:您在问题中回答自己的问题:

the browser then has the authenticated cookies and the webapp can use the endpoints to update its state然后浏览器具有经过身份验证的 cookies 并且 webapp 可以使用端点更新其 state

HttpClient needs to send those same cookies. HttpClient 需要发送相同的 cookies。 How do I set a cookie on HttpClient's HttpRequestMessage 如何在 HttpClient 的 HttpRequestMessage 上设置 cookie

If I understood your question right, then I faced the same problem not too long ago.如果我正确理解了您的问题,那么不久前我遇到了同样的问题。

The way I implemented it is that in the backend, no matter who tries to access the endpoint, they had to send a Bearer X authorization token.我实现它的方式是,在后端,无论谁尝试访问端点,他们都必须发送一个Bearer X授权令牌。 The token contained the identity of the client that wanted to access the resource, and I checked if he was permitted.令牌包含想要访问资源的客户端的身份,我检查了他是否被允许。

No matter what kind of client wants to access the endpoint, it just has to have that authroziation header in the request that he sends and the backend will treat it the same.无论哪种客户端想要访问端点,它只需要在他发送的请求中具有该授权 header 并且后端将对其进行相同处理。

In my scenario, I used an authentication service that returns a cookie to the client with a certain JWT that contains the identity information.在我的场景中,我使用了一个身份验证服务,该服务使用包含身份信息的某个 JWT 向客户端返回一个 cookie。 Then from the client I send in every request the JWT received from the authentication service as an authorization header to the backend.然后从客户端发送每个请求 JWT 从身份验证服务收到作为授权 header 到后端。

The reason I had to put the JWT that I receive from the service in a header, is that the authentication service and the backend service are not in the same domain, so cookies cant be shared.我必须将从服务中收到的 JWT 放在 header 中的原因是身份验证服务和后端服务不在同一个域中,因此可以共享 Z55E7DD3016CE4AC57B9A0F56AF12F7C2。

This results in such design that no matter how you authenticate the client, the end result must be some sort of token that the backend can receive and read.这导致这样的设计,无论您如何验证客户端,最终结果都必须是后端可以接收和读取的某种令牌。

Hope this helps.希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何注册将验证域用户的 HttpClient - How to register HttpClient that will authenticate domain user 如何使用 HttpClient 处理数据提供者实例? - How to dispose the data provider instance using HttpClient? 如何使用DotNetOpenAuth对任何邮件提供商进行身份验证? - How to authenticate to any mail provider using DotNetOpenAuth? 通过Azure ACS与Google作为身份提供者对Restful服务进行身份验证 - Authenticate Restful service through Azure ACS with Google as an identity provider 如何防止HttpClient发送Connection头 - How to prevent HttpClient from sending the Connection header 如何管理最大连接数,HttpClient,C#? - How to manage max connection, HttpClient, C#? 如何为HttpClient的特定连接设置HttpHeader? - How to set an HttpHeader on for a specific connection of HttpClient? 使用身份提供者对用户进行身份验证后如何获取身份验证访问令牌? - How to get the authentication access token after Authenticate Users with an Identity Provider? 如何将 IdentityServer4 设置为外部身份提供者 - How to setup IdentityServer4 to be an external identity provider 如何验证用于Dialogflow集成的Google凭据 - How to authenticate Google Credentials for Dialogflow Integration
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM