Skip to content
Snippets Groups Projects
Commit 189fcf86 authored by Jan Tattermusch's avatar Jan Tattermusch
Browse files

introduce auth interceptor context

parent 3e5cbee7
No related branches found
No related tags found
No related merge requests found
...@@ -57,9 +57,9 @@ namespace Grpc.Auth ...@@ -57,9 +57,9 @@ namespace Grpc.Auth
/// <returns>The interceptor.</returns> /// <returns>The interceptor.</returns>
public static AsyncAuthInterceptor FromCredential(ITokenAccess credential) public static AsyncAuthInterceptor FromCredential(ITokenAccess credential)
{ {
return new AsyncAuthInterceptor(async (authUri, metadata) => return new AsyncAuthInterceptor(async (context, metadata) =>
{ {
var accessToken = await credential.GetAccessTokenForRequestAsync(authUri, CancellationToken.None).ConfigureAwait(false); var accessToken = await credential.GetAccessTokenForRequestAsync(context.ServiceUrl, CancellationToken.None).ConfigureAwait(false);
metadata.Add(CreateBearerTokenHeader(accessToken)); metadata.Add(CreateBearerTokenHeader(accessToken));
}); });
} }
...@@ -72,7 +72,7 @@ namespace Grpc.Auth ...@@ -72,7 +72,7 @@ namespace Grpc.Auth
public static AsyncAuthInterceptor FromAccessToken(string accessToken) public static AsyncAuthInterceptor FromAccessToken(string accessToken)
{ {
Preconditions.CheckNotNull(accessToken); Preconditions.CheckNotNull(accessToken);
return new AsyncAuthInterceptor(async (authUri, metadata) => return new AsyncAuthInterceptor(async (context, metadata) =>
{ {
metadata.Add(CreateBearerTokenHeader(accessToken)); metadata.Add(CreateBearerTokenHeader(accessToken));
}); });
......
#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.Threading.Tasks;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core
{
/// <summary>
/// Asynchronous authentication interceptor for <see cref="CallCredentials"/>.
/// </summary>
/// <param name="context">The interceptor context.</param>
/// <param name="metadata">Metadata to populate with entries that will be added to outgoing call's headers.</param>
/// <returns></returns>
public delegate Task AsyncAuthInterceptor(AuthInterceptorContext context, Metadata metadata);
/// <summary>
/// Context for an RPC being intercepted by <see cref="AsyncAuthInterceptor"/>.
/// </summary>
public class AuthInterceptorContext
{
readonly string serviceUrl;
readonly string methodName;
/// <summary>
/// Initializes a new instance of <c>AuthInterceptorContext</c>.
/// </summary>
public AuthInterceptorContext(string serviceUrl, string methodName)
{
this.serviceUrl = Preconditions.CheckNotNull(serviceUrl);
this.methodName = Preconditions.CheckNotNull(methodName);
}
/// <summary>
/// The fully qualified service URL for the RPC being called.
/// </summary>
public string ServiceUrl
{
get { return serviceUrl; }
}
/// <summary>
/// The method name of the RPC being called.
/// </summary>
public string MethodName
{
get { return methodName; }
}
}
}
...@@ -40,14 +40,6 @@ using Grpc.Core.Utils; ...@@ -40,14 +40,6 @@ using Grpc.Core.Utils;
namespace Grpc.Core namespace Grpc.Core
{ {
/// <summary>
/// Asynchronous authentication interceptor for <see cref="CallCredentials"/>.
/// </summary>
/// <param name="authUri">URL of a service to which current remote call needs to authenticate</param>
/// <param name="metadata">Metadata to populate with entries that will be added to outgoing call's headers.</param>
/// <returns></returns>
public delegate Task AsyncAuthInterceptor(string authUri, Metadata metadata);
/// <summary> /// <summary>
/// Client-side call credentials. Provide authorization with per-call granularity. /// Client-side call credentials. Provide authorization with per-call granularity.
/// </summary> /// </summary>
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="AsyncDuplexStreamingCall.cs" /> <Compile Include="AsyncDuplexStreamingCall.cs" />
<Compile Include="AsyncServerStreamingCall.cs" /> <Compile Include="AsyncServerStreamingCall.cs" />
<Compile Include="AsyncAuthInterceptor.cs" />
<Compile Include="CallCredentials.cs" /> <Compile Include="CallCredentials.cs" />
<Compile Include="IClientStreamWriter.cs" /> <Compile Include="IClientStreamWriter.cs" />
<Compile Include="Internal\NativeMetadataCredentialsPlugin.cs" /> <Compile Include="Internal\NativeMetadataCredentialsPlugin.cs" />
...@@ -155,7 +156,5 @@ ...@@ -155,7 +156,5 @@
<Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" /> <Import Project="..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\packages\grpc.dependencies.openssl.redist.1.0.2.2\build\portable-net45\grpc.dependencies.openssl.redist.targets')" />
<Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" /> <Import Project="..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\portable-net45\grpc.dependencies.zlib.redist.targets')" />
<ItemGroup /> <ItemGroup />
<ItemGroup> <ItemGroup />
<Folder Include="Profiling\" /> </Project>
</ItemGroup> \ No newline at end of file
</Project>
...@@ -38,7 +38,7 @@ using Grpc.Core.Utils; ...@@ -38,7 +38,7 @@ using Grpc.Core.Utils;
namespace Grpc.Core.Internal namespace Grpc.Core.Internal
{ {
internal delegate void NativeMetadataInterceptor(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy); internal delegate void NativeMetadataInterceptor(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr methodNamePtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy);
internal class NativeMetadataCredentialsPlugin internal class NativeMetadataCredentialsPlugin
{ {
...@@ -71,7 +71,7 @@ namespace Grpc.Core.Internal ...@@ -71,7 +71,7 @@ namespace Grpc.Core.Internal
get { return credentials; } get { return credentials; }
} }
private void NativeMetadataInterceptorHandler(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy) private void NativeMetadataInterceptorHandler(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr methodNamePtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy)
{ {
if (isDestroy) if (isDestroy)
{ {
...@@ -81,8 +81,9 @@ namespace Grpc.Core.Internal ...@@ -81,8 +81,9 @@ namespace Grpc.Core.Internal
try try
{ {
string serviceUrl = Marshal.PtrToStringAnsi(serviceUrlPtr); var context = new AuthInterceptorContext(Marshal.PtrToStringAnsi(serviceUrlPtr),
StartGetMetadata(serviceUrl, callbackPtr, userDataPtr); Marshal.PtrToStringAnsi(methodNamePtr));
StartGetMetadata(context, callbackPtr, userDataPtr);
} }
catch (Exception e) catch (Exception e)
{ {
...@@ -91,12 +92,12 @@ namespace Grpc.Core.Internal ...@@ -91,12 +92,12 @@ namespace Grpc.Core.Internal
} }
} }
private async void StartGetMetadata(string serviceUrl, IntPtr callbackPtr, IntPtr userDataPtr) private async void StartGetMetadata(AuthInterceptorContext context, IntPtr callbackPtr, IntPtr userDataPtr)
{ {
try try
{ {
var metadata = new Metadata(); var metadata = new Metadata();
await interceptor(serviceUrl, metadata); await interceptor(context, metadata);
using (var metadataArray = MetadataArraySafeHandle.Create(metadata)) using (var metadataArray = MetadataArraySafeHandle.Create(metadata))
{ {
......
...@@ -67,7 +67,7 @@ namespace Grpc.IntegrationTesting ...@@ -67,7 +67,7 @@ namespace Grpc.IntegrationTesting
new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride) new ChannelOption(ChannelOptions.SslTargetNameOverride, TestCredentials.DefaultHostOverride)
}; };
var asyncAuthInterceptor = new AsyncAuthInterceptor(async (authUri, metadata) => var asyncAuthInterceptor = new AsyncAuthInterceptor(async (context, metadata) =>
{ {
await Task.Delay(100); // make sure the operation is asynchronous. await Task.Delay(100); // make sure the operation is asynchronous.
metadata.Add("authorization", "SECRET_TOKEN"); metadata.Add("authorization", "SECRET_TOKEN");
......
...@@ -927,7 +927,8 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin( ...@@ -927,7 +927,8 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin(
} }
typedef void(GPR_CALLTYPE *grpcsharp_metadata_interceptor_func)( typedef void(GPR_CALLTYPE *grpcsharp_metadata_interceptor_func)(
void *state, const char *service_url, grpc_credentials_plugin_metadata_cb cb, void *state, const char *service_url, const char *method_name,
grpc_credentials_plugin_metadata_cb cb,
void *user_data, gpr_int32 is_destroy); void *user_data, gpr_int32 is_destroy);
static void grpcsharp_get_metadata_handler( static void grpcsharp_get_metadata_handler(
...@@ -935,13 +936,13 @@ static void grpcsharp_get_metadata_handler( ...@@ -935,13 +936,13 @@ static void grpcsharp_get_metadata_handler(
grpc_credentials_plugin_metadata_cb cb, void *user_data) { grpc_credentials_plugin_metadata_cb cb, void *user_data) {
grpcsharp_metadata_interceptor_func interceptor = grpcsharp_metadata_interceptor_func interceptor =
(grpcsharp_metadata_interceptor_func)(gpr_intptr)state; (grpcsharp_metadata_interceptor_func)(gpr_intptr)state;
interceptor(state, context.service_url, cb, user_data, 0); interceptor(state, context.service_url, context.method_name, cb, user_data, 0);
} }
static void grpcsharp_metadata_credentials_destroy_handler(void *state) { static void grpcsharp_metadata_credentials_destroy_handler(void *state) {
grpcsharp_metadata_interceptor_func interceptor = grpcsharp_metadata_interceptor_func interceptor =
(grpcsharp_metadata_interceptor_func)(gpr_intptr)state; (grpcsharp_metadata_interceptor_func)(gpr_intptr)state;
interceptor(state, NULL, NULL, NULL, 1); interceptor(state, NULL, NULL, NULL, NULL, 1);
} }
GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_metadata_credentials_create_from_plugin( GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_metadata_credentials_create_from_plugin(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment