GoogleAuthInterceptors.cs 4.4 KB

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