• 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;
20 using System.Collections.Generic;
21 using System.Threading.Tasks;
22 
23 using Grpc.Core.Internal;
24 using Grpc.Core.Utils;
25 
26 namespace Grpc.Core
27 {
28     /// <summary>
29     /// Client-side call credentials. Provide authorization with per-call granularity.
30     /// </summary>
31     public abstract class CallCredentials
32     {
33         /// <summary>
34         /// Composes multiple multiple <c>CallCredentials</c> objects into
35         /// a single <c>CallCredentials</c> object.
36         /// </summary>
37         /// <param name="credentials">credentials to compose</param>
38         /// <returns>The new <c>CompositeCallCredentials</c></returns>
Compose(params CallCredentials[] credentials)39         public static CallCredentials Compose(params CallCredentials[] credentials)
40         {
41             return new CompositeCallCredentials(credentials);
42         }
43 
44         /// <summary>
45         /// Creates a new instance of <c>CallCredentials</c> class from an
46         /// interceptor that can attach metadata to outgoing calls.
47         /// </summary>
48         /// <param name="interceptor">authentication interceptor</param>
FromInterceptor(AsyncAuthInterceptor interceptor)49         public static CallCredentials FromInterceptor(AsyncAuthInterceptor interceptor)
50         {
51             return new MetadataCredentials(interceptor);
52         }
53 
54         /// <summary>
55         /// Creates native object for the credentials.
56         /// </summary>
57         /// <returns>The native credentials.</returns>
ToNativeCredentials()58         internal abstract CallCredentialsSafeHandle ToNativeCredentials();
59     }
60 
61     /// <summary>
62     /// Client-side credentials that delegate metadata based auth to an interceptor.
63     /// The interceptor is automatically invoked for each remote call that uses <c>MetadataCredentials.</c>
64     /// </summary>
65     internal sealed class MetadataCredentials : CallCredentials
66     {
67         readonly AsyncAuthInterceptor interceptor;
68 
69         /// <summary>
70         /// Initializes a new instance of <c>MetadataCredentials</c> class.
71         /// </summary>
72         /// <param name="interceptor">authentication interceptor</param>
MetadataCredentials(AsyncAuthInterceptor interceptor)73         public MetadataCredentials(AsyncAuthInterceptor interceptor)
74         {
75             this.interceptor = GrpcPreconditions.CheckNotNull(interceptor);
76         }
77 
ToNativeCredentials()78         internal override CallCredentialsSafeHandle ToNativeCredentials()
79         {
80             NativeMetadataCredentialsPlugin plugin = new NativeMetadataCredentialsPlugin(interceptor);
81             return plugin.Credentials;
82         }
83     }
84 
85     /// <summary>
86     /// Credentials that allow composing multiple credentials objects into one <see cref="CallCredentials"/> object.
87     /// </summary>
88     internal sealed class CompositeCallCredentials : CallCredentials
89     {
90         readonly List<CallCredentials> credentials;
91 
92         /// <summary>
93         /// Initializes a new instance of <c>CompositeCallCredentials</c> class.
94         /// The resulting credentials object will be composite of all the credentials specified as parameters.
95         /// </summary>
96         /// <param name="credentials">credentials to compose</param>
CompositeCallCredentials(params CallCredentials[] credentials)97         public CompositeCallCredentials(params CallCredentials[] credentials)
98         {
99             GrpcPreconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials.");
100             this.credentials = new List<CallCredentials>(credentials);
101         }
102 
ToNativeCredentials()103         internal override CallCredentialsSafeHandle ToNativeCredentials()
104         {
105             return ToNativeRecursive(0);
106         }
107 
108         // Recursive descent makes managing lifetime of intermediate CredentialSafeHandle instances easier.
109         // In practice, we won't usually see composites from more than two credentials anyway.
ToNativeRecursive(int startIndex)110         private CallCredentialsSafeHandle ToNativeRecursive(int startIndex)
111         {
112             if (startIndex == credentials.Count - 1)
113             {
114                 return credentials[startIndex].ToNativeCredentials();
115             }
116 
117             using (var cred1 = credentials[startIndex].ToNativeCredentials())
118             using (var cred2 = ToNativeRecursive(startIndex + 1))
119             {
120                 var nativeComposite = CallCredentialsSafeHandle.CreateComposite(cred1, cred2);
121                 if (nativeComposite.IsInvalid)
122                 {
123                     throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials.");
124                 }
125                 return nativeComposite;
126             }
127         }
128     }
129 }
130