• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 
3 // Copyright 2015 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #endregion
18 
19 using System.Threading;
20 using System.Threading.Tasks;
21 
22 using Google.Apis.Auth.OAuth2;
23 using Grpc.Core;
24 using Grpc.Core.Utils;
25 
26 namespace Grpc.Auth
27 {
28     /// <summary>
29     /// Factory methods to create authorization interceptors for Google credentials.
30     /// <seealso cref="GoogleGrpcCredentials"/>
31     /// </summary>
32     public static class GoogleAuthInterceptors
33     {
34         private const string AuthorizationHeader = "Authorization";
35         private const string Schema = "Bearer";
36 
37         /// <summary>
38         /// Creates an <see cref="AsyncAuthInterceptor"/> that will obtain access token from any credential type that implements
39         /// <c>ITokenAccess</c>. (e.g. <c>GoogleCredential</c>).
40         /// </summary>
41         /// <param name="credential">The credential to use to obtain access tokens.</param>
42         /// <returns>The interceptor.</returns>
FromCredential(ITokenAccess credential)43         public static AsyncAuthInterceptor FromCredential(ITokenAccess credential)
44         {
45             if (credential is ITokenAccessWithHeaders credentialWithHeaders)
46             {
47                 return FromCredential(credentialWithHeaders);
48             }
49 
50             return new AsyncAuthInterceptor(async (context, metadata) =>
51             {
52                 var accessToken = await credential.GetAccessTokenForRequestAsync(context.ServiceUrl, CancellationToken.None).ConfigureAwait(false);
53                 metadata.Add(CreateBearerTokenHeader(accessToken));
54             });
55         }
56 
57         /// <summary>
58         /// Creates an <see cref="AsyncAuthInterceptor"/> that will obtain access token and associated information
59         /// from any credential type that implements <see cref="ITokenAccessWithHeaders"/>
60         /// </summary>
61         /// <param name="credential">The credential to use to obtain access tokens.</param>
62         /// <returns>The interceptor.</returns>
FromCredential(ITokenAccessWithHeaders credential)63         public static AsyncAuthInterceptor FromCredential(ITokenAccessWithHeaders credential)
64         {
65             return new AsyncAuthInterceptor(async (context, metadata) =>
66             {
67                 AccessTokenWithHeaders tokenAndHeaders = await credential.GetAccessTokenWithHeadersForRequestAsync(context.ServiceUrl, CancellationToken.None).ConfigureAwait(false);
68                 metadata.Add(CreateBearerTokenHeader(tokenAndHeaders.AccessToken));
69                 foreach (var header in tokenAndHeaders.Headers)
70                 {
71                     foreach (var headerValue in header.Value)
72                     {
73                         metadata.Add(new Metadata.Entry(header.Key, headerValue));
74                     }
75                 }
76             });
77         }
78 
79         /// <summary>
80         /// Creates an <see cref="AsyncAuthInterceptor"/> that will use given access token as authorization.
81         /// </summary>
82         /// <param name="accessToken">OAuth2 access token.</param>
83         /// <returns>The interceptor.</returns>
FromAccessToken(string accessToken)84         public static AsyncAuthInterceptor FromAccessToken(string accessToken)
85         {
86             GrpcPreconditions.CheckNotNull(accessToken);
87             return new AsyncAuthInterceptor((context, metadata) =>
88             {
89                 metadata.Add(CreateBearerTokenHeader(accessToken));
90                 return GetCompletedTask();
91             });
92         }
93 
CreateBearerTokenHeader(string accessToken)94         private static Metadata.Entry CreateBearerTokenHeader(string accessToken)
95         {
96             return new Metadata.Entry(AuthorizationHeader, Schema + " " + accessToken);
97         }
98 
99         /// <summary>
100         /// Framework independent equivalent of <c>Task.CompletedTask</c>.
101         /// </summary>
GetCompletedTask()102         private static Task GetCompletedTask()
103         {
104 #if NETSTANDARD
105             return Task.CompletedTask;
106 #else
107             return Task.FromResult<object>(null);  // for .NET45, emulate the functionality
108 #endif
109         }
110     }
111 }
112