Merge pull request #2895 from jtattermusch/switch_to_usable_auth

migrate to usable auth library
pull/2612/head
Jan Tattermusch 10 years ago
commit 3b226512d4
  1. 125
      src/csharp/Grpc.Auth/GoogleCredential.cs
  2. 27
      src/csharp/Grpc.Auth/Grpc.Auth.csproj
  3. 26
      src/csharp/Grpc.Auth/OAuth2Interceptors.cs
  4. 4
      src/csharp/Grpc.Auth/app.config
  5. 4
      src/csharp/Grpc.Auth/packages.config
  6. 4
      src/csharp/Grpc.Core.Tests/ChannelTest.cs
  7. 24
      src/csharp/Grpc.Core/Channel.cs
  8. 11
      src/csharp/Grpc.Core/ClientBase.cs
  9. 4
      src/csharp/Grpc.IntegrationTesting.Client/app.config
  10. 4
      src/csharp/Grpc.IntegrationTesting.Server/app.config
  11. 38
      src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
  12. 80
      src/csharp/Grpc.IntegrationTesting/InteropClient.cs
  13. 4
      src/csharp/Grpc.IntegrationTesting/app.config
  14. 4
      src/csharp/Grpc.IntegrationTesting/packages.config

@ -1,125 +0,0 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Auth.OAuth2.Responses;
using Newtonsoft.Json.Linq;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
namespace Grpc.Auth
{
// TODO(jtattermusch): Remove this class once possible.
/// <summary>
/// A temporary placeholder for Google credential from
/// Google Auth library for .NET. It emulates the usage pattern
/// for Usable auth.
/// </summary>
public class GoogleCredential
{
private const string GoogleApplicationCredentialsEnvName = "GOOGLE_APPLICATION_CREDENTIALS";
private const string ClientEmailFieldName = "client_email";
private const string PrivateKeyFieldName = "private_key";
private ServiceCredential credential;
private GoogleCredential(ServiceCredential credential)
{
this.credential = credential;
}
public static GoogleCredential GetApplicationDefault()
{
return new GoogleCredential(null);
}
public bool IsCreateScopedRequired
{
get
{
return true;
}
}
public GoogleCredential CreateScoped(IEnumerable<string> scopes)
{
var credsPath = Environment.GetEnvironmentVariable(GoogleApplicationCredentialsEnvName);
if (credsPath == null)
{
// Default to ComputeCredentials if path to JSON key is not set.
// ComputeCredential is not scoped actually, but for our use case it's
// fine to treat is as such.
return new GoogleCredential(new ComputeCredential(new ComputeCredential.Initializer()));
}
JObject jsonCredentialParameters = JObject.Parse(File.ReadAllText(credsPath));
string clientEmail = jsonCredentialParameters.GetValue(ClientEmailFieldName).Value<string>();
string privateKeyString = jsonCredentialParameters.GetValue(PrivateKeyFieldName).Value<string>();
var serviceCredential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(clientEmail)
{
Scopes = scopes,
}.FromPrivateKey(privateKeyString));
return new GoogleCredential(serviceCredential);
}
public Task<bool> RequestAccessTokenAsync(CancellationToken taskCancellationToken)
{
return credential.RequestAccessTokenAsync(taskCancellationToken);
}
public TokenResponse Token
{
get
{
return credential.Token;
}
}
internal ServiceCredential InternalCredential
{
get
{
return credential;
}
}
}
}

@ -11,7 +11,7 @@
<AssemblyName>Grpc.Auth</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<DocumentationFile>bin\$(Configuration)\Grpc.Auth.Xml</DocumentationFile>
<NuGetPackageImportStamp>9b408026</NuGetPackageImportStamp>
<NuGetPackageImportStamp>4f8487a9</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -41,28 +41,32 @@
<AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="BouncyCastle.Crypto">
<Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Auth, Version=1.9.2.27817, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<Reference Include="Google.Apis.Auth, Version=1.9.3.19379, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Apis.Auth.1.9.2\lib\net40\Google.Apis.Auth.dll</HintPath>
<HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Auth.PlatformServices, Version=1.9.2.27820, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<Reference Include="Google.Apis.Auth.PlatformServices, Version=1.9.3.19383, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Apis.Auth.1.9.2\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
<HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Core, Version=1.9.2.27816, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<Reference Include="Google.Apis.Core, Version=1.9.3.19379, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Apis.Core.1.9.2\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
<HintPath>..\packages\Google.Apis.Core.1.9.3\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks">
<Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<Reference Include="Microsoft.Threading.Tasks.Extensions, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
@ -87,7 +91,6 @@
<Link>Version.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="GoogleCredential.cs" />
<Compile Include="OAuth2Interceptors.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

@ -54,7 +54,7 @@ namespace Grpc.Auth
/// </summary>
public static MetadataInterceptorDelegate FromCredential(GoogleCredential googleCredential)
{
var interceptor = new OAuth2Interceptor(googleCredential.InternalCredential, SystemClock.Default);
var interceptor = new OAuth2Interceptor(googleCredential, SystemClock.Default);
return new MetadataInterceptorDelegate(interceptor.InterceptHeaders);
}
@ -66,7 +66,7 @@ namespace Grpc.Auth
public static MetadataInterceptorDelegate FromAccessToken(string oauth2Token)
{
Preconditions.CheckNotNull(oauth2Token);
return new MetadataInterceptorDelegate((metadata) =>
return new MetadataInterceptorDelegate((authUri, metadata) =>
{
metadata.Add(OAuth2Interceptor.CreateBearerTokenHeader(oauth2Token));
});
@ -80,10 +80,10 @@ namespace Grpc.Auth
private const string AuthorizationHeader = "Authorization";
private const string Schema = "Bearer";
private ServiceCredential credential;
private ITokenAccess credential;
private IClock clock;
public OAuth2Interceptor(ServiceCredential credential, IClock clock)
public OAuth2Interceptor(ITokenAccess credential, IClock clock)
{
this.credential = credential;
this.clock = clock;
@ -94,23 +94,15 @@ namespace Grpc.Auth
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public string GetAccessToken(CancellationToken cancellationToken)
public string GetAccessToken(string authUri, CancellationToken cancellationToken)
{
if (credential.Token == null || credential.Token.IsExpired(clock))
{
// TODO(jtattermusch): Parallel requests will spawn multiple requests to refresh the token once the token expires.
// TODO(jtattermusch): Rethink synchronous wait to obtain the result.
if (!credential.RequestAccessTokenAsync(cancellationToken).Result)
{
throw new InvalidOperationException("The access token has expired but we can't refresh it");
}
}
return credential.Token.AccessToken;
// TODO(jtattermusch): Rethink synchronous wait to obtain the result.
return credential.GetAccessTokenForRequestAsync(authUri, cancellationToken: cancellationToken).GetAwaiter().GetResult();
}
public void InterceptHeaders(Metadata metadata)
public void InterceptHeaders(string authUri, Metadata metadata)
{
var accessToken = GetAccessToken(CancellationToken.None);
var accessToken = GetAccessToken(authUri, CancellationToken.None);
metadata.Add(CreateBearerTokenHeader(accessToken));
}

@ -10,6 +10,10 @@
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Google.Apis.Core" publicKeyToken="4b01fa6e34db77ab" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.9.2.38523" newVersion="1.9.2.38523" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
<package id="Google.Apis.Auth" version="1.9.2" targetFramework="net45" />
<package id="Google.Apis.Core" version="1.9.2" targetFramework="net45" />
<package id="Google.Apis.Auth" version="1.9.3" targetFramework="net45" />
<package id="Google.Apis.Core" version="1.9.3" targetFramework="net45" />
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="net45" />
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net45" />

@ -72,11 +72,11 @@ namespace Grpc.Core.Tests
}
[Test]
public void Target()
public void ResolvedTarget()
{
using (var channel = new Channel("127.0.0.1", Credentials.Insecure))
{
Assert.IsTrue(channel.Target.Contains("127.0.0.1"));
Assert.IsTrue(channel.ResolvedTarget.Contains("127.0.0.1"));
}
}

@ -49,6 +49,7 @@ namespace Grpc.Core
{
static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<Channel>();
readonly string target;
readonly GrpcEnvironment environment;
readonly ChannelSafeHandle handle;
readonly List<ChannelOption> options;
@ -58,12 +59,12 @@ namespace Grpc.Core
/// Creates a channel that connects to a specific host.
/// Port will default to 80 for an unsecure channel and to 443 for a secure channel.
/// </summary>
/// <param name="host">The name or IP address of the host.</param>
/// <param name="target">Target of the channel.</param>
/// <param name="credentials">Credentials to secure the channel.</param>
/// <param name="options">Channel options.</param>
public Channel(string host, Credentials credentials, IEnumerable<ChannelOption> options = null)
public Channel(string target, Credentials credentials, IEnumerable<ChannelOption> options = null)
{
Preconditions.CheckNotNull(host, "host");
this.target = Preconditions.CheckNotNull(target, "target");
this.environment = GrpcEnvironment.GetInstance();
this.options = options != null ? new List<ChannelOption>(options) : new List<ChannelOption>();
@ -73,11 +74,11 @@ namespace Grpc.Core
{
if (nativeCredentials != null)
{
this.handle = ChannelSafeHandle.CreateSecure(nativeCredentials, host, nativeChannelArgs);
this.handle = ChannelSafeHandle.CreateSecure(nativeCredentials, target, nativeChannelArgs);
}
else
{
this.handle = ChannelSafeHandle.CreateInsecure(host, nativeChannelArgs);
this.handle = ChannelSafeHandle.CreateInsecure(target, nativeChannelArgs);
}
}
}
@ -131,8 +132,8 @@ namespace Grpc.Core
return tcs.Task;
}
/// <summary> Address of the remote endpoint in URI format.</summary>
public string Target
/// <summary>Resolved address of the remote endpoint in URI format.</summary>
public string ResolvedTarget
{
get
{
@ -140,6 +141,15 @@ namespace Grpc.Core
}
}
/// <summary>The original target used to create the channel.</summary>
public string Target
{
get
{
return this.target;
}
}
/// <summary>
/// Allows explicitly requesting channel to connect without starting an RPC.
/// Returned task completes once state Ready was seen. If the deadline is reached,

@ -35,21 +35,26 @@ using System;
using System.Collections.Generic;
using Grpc.Core.Internal;
using System.Text.RegularExpressions;
namespace Grpc.Core
{
public delegate void MetadataInterceptorDelegate(Metadata metadata);
public delegate void MetadataInterceptorDelegate(string authUri, Metadata metadata);
/// <summary>
/// Base class for client-side stubs.
/// </summary>
public abstract class ClientBase
{
static readonly Regex TrailingPortPattern = new Regex(":[0-9]+/?$");
readonly Channel channel;
readonly string authUriBase;
public ClientBase(Channel channel)
{
this.channel = channel;
// TODO(jtattermush): we shouldn't need to hand-curate the channel.Target contents.
this.authUriBase = "https://" + TrailingPortPattern.Replace(channel.Target, "") + "/";
}
/// <summary>
@ -99,8 +104,8 @@ namespace Grpc.Core
{
options = options.WithHeaders(new Metadata());
}
interceptor(options.Headers);
options.Headers.Freeze();
var authUri = authUriBase + method.ServiceName;
interceptor(authUri, options.Headers);
}
return new CallInvocationDetails<TRequest, TResponse>(channel, method, Host, options);
}

@ -10,6 +10,10 @@
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Google.Apis.Core" publicKeyToken="4b01fa6e34db77ab" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.9.2.38523" newVersion="1.9.2.38523" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -10,6 +10,10 @@
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Google.Apis.Core" publicKeyToken="4b01fa6e34db77ab" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.9.2.38523" newVersion="1.9.2.38523" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -8,7 +8,7 @@
<RootNamespace>Grpc.IntegrationTesting</RootNamespace>
<AssemblyName>Grpc.IntegrationTesting</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<NuGetPackageImportStamp>041c163e</NuGetPackageImportStamp>
<NuGetPackageImportStamp>6566287f</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -38,20 +38,33 @@
<AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="BouncyCastle.Crypto">
<Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Auth, Version=1.9.2.27817, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<Reference Include="Google.Apis.Auth, Version=1.9.3.19379, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Auth.PlatformServices, Version=1.9.3.19383, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Core, Version=1.9.3.19379, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Apis.Core.1.9.3\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Apis.Auth.1.9.2\lib\net40\Google.Apis.Auth.dll</HintPath>
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Auth.PlatformServices, Version=1.9.2.27820, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<Reference Include="Microsoft.Threading.Tasks.Extensions, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Apis.Auth.1.9.2\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Google.Apis.Core, Version=1.9.2.27816, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop, Version=1.0.168.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Apis.Core.1.9.2\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@ -78,15 +91,6 @@
<HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">

@ -43,6 +43,7 @@ using Grpc.Auth;
using Grpc.Core;
using Grpc.Core.Utils;
using NUnit.Framework;
using Google.Apis.Auth.OAuth2;
namespace Grpc.IntegrationTesting
{
@ -97,10 +98,10 @@ namespace Grpc.IntegrationTesting
}
var interopClient = new InteropClient(options);
interopClient.Run();
interopClient.Run().Wait();
}
private void Run()
private async Task Run()
{
Credentials credentials = null;
if (options.useTls)
@ -120,17 +121,7 @@ namespace Grpc.IntegrationTesting
using (Channel channel = new Channel(options.serverHost, options.serverPort.Value, credentials, channelOptions))
{
TestService.TestServiceClient client = new TestService.TestServiceClient(channel);
if (options.testCase == "service_account_creds" || options.testCase == "compute_engine_creds")
{
var credential = GoogleCredential.GetApplicationDefault();
if (credential.IsCreateScopedRequired)
{
credential = credential.CreateScoped(new[] { AuthScope });
}
client.HeaderInterceptor = OAuth2Interceptors.FromCredential(credential);
}
RunTestCaseAsync(options.testCase, client).Wait();
await RunTestCaseAsync(options.testCase, client);
}
GrpcEnvironment.Shutdown();
}
@ -158,16 +149,19 @@ namespace Grpc.IntegrationTesting
await RunEmptyStreamAsync(client);
break;
case "service_account_creds":
RunServiceAccountCreds(client);
await RunServiceAccountCredsAsync(client);
break;
case "compute_engine_creds":
RunComputeEngineCreds(client);
await RunComputeEngineCredsAsync(client);
break;
case "jwt_token_creds":
await RunJwtTokenCredsAsync(client);
break;
case "oauth2_auth_token":
RunOAuth2AuthToken(client);
await RunOAuth2AuthTokenAsync(client);
break;
case "per_rpc_creds":
RunPerRpcCreds(client);
await RunPerRpcCredsAsync(client);
break;
case "cancel_after_begin":
await RunCancelAfterBeginAsync(client);
@ -309,9 +303,13 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunServiceAccountCreds(TestService.ITestServiceClient client)
public static async Task RunServiceAccountCredsAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running service_account_creds");
var credential = await GoogleCredential.GetApplicationDefaultAsync();
credential = credential.CreateScoped(new[] { AuthScope });
client.HeaderInterceptor = OAuth2Interceptors.FromCredential(credential);
var request = SimpleRequest.CreateBuilder()
.SetResponseType(PayloadType.COMPRESSABLE)
.SetResponseSize(314159)
@ -329,9 +327,13 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunComputeEngineCreds(TestService.ITestServiceClient client)
public static async Task RunComputeEngineCredsAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running compute_engine_creds");
var credential = await GoogleCredential.GetApplicationDefaultAsync();
Assert.IsFalse(credential.IsCreateScopedRequired);
client.HeaderInterceptor = OAuth2Interceptors.FromCredential(credential);
var request = SimpleRequest.CreateBuilder()
.SetResponseType(PayloadType.COMPRESSABLE)
.SetResponseSize(314159)
@ -349,12 +351,35 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunOAuth2AuthToken(TestService.TestServiceClient client)
public static async Task RunJwtTokenCredsAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running jwt_token_creds");
var credential = await GoogleCredential.GetApplicationDefaultAsync();
// check this a credential with scope support, but don't add the scope.
Assert.IsTrue(credential.IsCreateScopedRequired);
client.HeaderInterceptor = OAuth2Interceptors.FromCredential(credential);
var request = SimpleRequest.CreateBuilder()
.SetResponseType(PayloadType.COMPRESSABLE)
.SetResponseSize(314159)
.SetPayload(CreateZerosPayload(271828))
.SetFillUsername(true)
.SetFillOauthScope(true)
.Build();
var response = client.UnaryCall(request);
Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
Assert.AreEqual(314159, response.Payload.Body.Length);
Assert.AreEqual(ServiceAccountUser, response.Username);
Console.WriteLine("Passed!");
}
public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running oauth2_auth_token");
var credential = GoogleCredential.GetApplicationDefault().CreateScoped(new[] { AuthScope });
Assert.IsTrue(credential.RequestAccessTokenAsync(CancellationToken.None).Result);
string oauth2Token = credential.Token.AccessToken;
ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { AuthScope });
string oauth2Token = await credential.GetAccessTokenForRequestAsync();
client.HeaderInterceptor = OAuth2Interceptors.FromAccessToken(oauth2Token);
@ -370,13 +395,12 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunPerRpcCreds(TestService.TestServiceClient client)
public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running per_rpc_creds");
var credential = GoogleCredential.GetApplicationDefault().CreateScoped(new[] { AuthScope });
Assert.IsTrue(credential.RequestAccessTokenAsync(CancellationToken.None).Result);
string oauth2Token = credential.Token.AccessToken;
ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { AuthScope });
string oauth2Token = await credential.GetAccessTokenForRequestAsync();
var headerInterceptor = OAuth2Interceptors.FromAccessToken(oauth2Token);
var request = SimpleRequest.CreateBuilder()
@ -385,7 +409,7 @@ namespace Grpc.IntegrationTesting
.Build();
var headers = new Metadata();
headerInterceptor(headers);
headerInterceptor("", headers);
var response = client.UnaryCall(request, headers: headers);
Assert.AreEqual(AuthScopeResponse, response.OauthScope);

@ -10,6 +10,10 @@
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Google.Apis.Core" publicKeyToken="4b01fa6e34db77ab" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.9.2.38523" newVersion="1.9.2.38523" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
<package id="Google.Apis.Auth" version="1.9.2" targetFramework="net45" />
<package id="Google.Apis.Core" version="1.9.2" targetFramework="net45" />
<package id="Google.Apis.Auth" version="1.9.3" targetFramework="net45" />
<package id="Google.Apis.Core" version="1.9.3" targetFramework="net45" />
<package id="Google.ProtocolBuffers" version="2.4.1.521" targetFramework="net45" />
<package id="Ix-Async" version="1.2.3" targetFramework="net45" />
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="net45" />

Loading…
Cancel
Save