#region Copyright notice and license // Copyright 2015 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #endregion using System.Threading; using System.Threading.Tasks; using Google.Apis.Auth.OAuth2; using Grpc.Core; using Grpc.Core.Utils; namespace Grpc.Auth { /// /// Factory methods to create authorization interceptors for Google credentials. /// /// public static class GoogleAuthInterceptors { private const string AuthorizationHeader = "Authorization"; private const string Schema = "Bearer"; /// /// Creates an that will obtain access token from any credential type that implements /// ITokenAccess. (e.g. GoogleCredential). /// /// The credential to use to obtain access tokens. /// The interceptor. public static AsyncAuthInterceptor FromCredential(ITokenAccess credential) { if (credential is ITokenAccessWithHeaders credentialWithHeaders) { return FromCredential(credentialWithHeaders); } return new AsyncAuthInterceptor(async (context, metadata) => { var accessToken = await credential.GetAccessTokenForRequestAsync(context.ServiceUrl, CancellationToken.None).ConfigureAwait(false); metadata.Add(CreateBearerTokenHeader(accessToken)); }); } /// /// Creates an that will obtain access token and associated information /// from any credential type that implements /// /// The credential to use to obtain access tokens. /// The interceptor. public static AsyncAuthInterceptor FromCredential(ITokenAccessWithHeaders credential) { return new AsyncAuthInterceptor(async (context, metadata) => { AccessTokenWithHeaders tokenAndHeaders = await credential.GetAccessTokenWithHeadersForRequestAsync(context.ServiceUrl, CancellationToken.None).ConfigureAwait(false); metadata.Add(CreateBearerTokenHeader(tokenAndHeaders.AccessToken)); foreach (var header in tokenAndHeaders.Headers) { foreach (var headerValue in header.Value) { metadata.Add(new Metadata.Entry(header.Key, headerValue)); } } }); } /// /// Creates an that will use given access token as authorization. /// /// OAuth2 access token. /// The interceptor. public static AsyncAuthInterceptor FromAccessToken(string accessToken) { GrpcPreconditions.CheckNotNull(accessToken); return new AsyncAuthInterceptor((context, metadata) => { metadata.Add(CreateBearerTokenHeader(accessToken)); return GetCompletedTask(); }); } private static Metadata.Entry CreateBearerTokenHeader(string accessToken) { return new Metadata.Entry(AuthorizationHeader, Schema + " " + accessToken); } /// /// Framework independent equivalent of Task.CompletedTask. /// private static Task GetCompletedTask() { #if NETSTANDARD return Task.CompletedTask; #else return Task.FromResult(null); // for .NET45, emulate the functionality #endif } } }