I am trying to create an API on Google App Engine which can be called by a .NET client with authentication.
The .NET client authenticates the user using
UserCredential credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = "<client id>",
ClientSecret = "<client secret"
},
new[] { "email", "profile", "https://www.googleapis.com/auth/devstorage.read_write" }, "user", CancellationToken.None);
and that works fine.
I have a servlet which is protected by
<security-constraint>
<web-resource-collection>
<web-resource-name>servlet</web-resource-name>
<url-pattern>/servlet/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
So it is only accessible to authenticated users, which is how I want it.
I want to be able to get the current user using
User currentUser = UserServiceFactory.getUserService().getCurrentUser();
but I can't get the .NET client to authenticate to the servlet.
I have tried
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {credential.Token.AccessToken}");
httpClient.PutAsync("http://<my app>/servlet", content);
however this fails as the put returns a 302 redirect to a URL starting with https://www.google.com/accounts/ServiceLogin..., which the .NET HTTP client presumably follows, as it then ends up with a 405 method not allowed.
I've also tried
Google.Apis.Http.HttpClientFactory httpClientFactory = new HttpClientFactory();
Google.Apis.Http.CreateHttpClientArgs httpClientArgs = new CreateHttpClientArgs();
Google.Apis.Http.ConfigurableHttpClient httpClient = httpClientFactory.CreateHttpClient(new CreateHttpClientArgs());
credential.Initialize(httpClient);
(credential is the UserCredential gained above from GoogleWebAuthorizationBroker.AuthorizeAsync)
however that does the same thing - issues a redirect to google/accounts/ServiceLogin URl - which fails.
Is what I'm trying to do even possible? Surely there must be a way for a servlet to be able to authenticate users that are calling it programatically via an API rather than from the web?