Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 1 | #region Copyright notice and license |
| 2 | |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 3 | // Copyright 2015 gRPC authors. |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 4 | // |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 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 |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 8 | // |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 9 | // http://www.apache.org/licenses/LICENSE-2.0 |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 10 | // |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 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. |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 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> |
| 39 | public static CallCredentials Compose(params CallCredentials[] credentials) |
| 40 | { |
| 41 | return new CompositeCallCredentials(credentials); |
| 42 | } |
| 43 | |
| 44 | /// <summary> |
Jan Tattermusch | 18729a0 | 2015-10-08 18:40:00 -0700 | [diff] [blame] | 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> |
| 49 | public static CallCredentials FromInterceptor(AsyncAuthInterceptor interceptor) |
| 50 | { |
| 51 | return new MetadataCredentials(interceptor); |
| 52 | } |
| 53 | |
| 54 | /// <summary> |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 55 | /// Creates native object for the credentials. |
| 56 | /// </summary> |
| 57 | /// <returns>The native credentials.</returns> |
Jan Tattermusch | 08dea32 | 2015-10-26 17:34:10 -0700 | [diff] [blame] | 58 | internal abstract CallCredentialsSafeHandle ToNativeCredentials(); |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 59 | } |
| 60 | |
| 61 | /// <summary> |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 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> |
Jan Tattermusch | 18729a0 | 2015-10-08 18:40:00 -0700 | [diff] [blame] | 65 | internal sealed class MetadataCredentials : CallCredentials |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 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> |
| 73 | public MetadataCredentials(AsyncAuthInterceptor interceptor) |
| 74 | { |
Jan Tattermusch | 7a3ee6a | 2016-02-18 10:36:02 -0800 | [diff] [blame] | 75 | this.interceptor = GrpcPreconditions.CheckNotNull(interceptor); |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 76 | } |
| 77 | |
Jan Tattermusch | 08dea32 | 2015-10-26 17:34:10 -0700 | [diff] [blame] | 78 | internal override CallCredentialsSafeHandle ToNativeCredentials() |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 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> |
| 97 | public CompositeCallCredentials(params CallCredentials[] credentials) |
| 98 | { |
Jan Tattermusch | 7a3ee6a | 2016-02-18 10:36:02 -0800 | [diff] [blame] | 99 | GrpcPreconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials."); |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 100 | this.credentials = new List<CallCredentials>(credentials); |
| 101 | } |
| 102 | |
Jan Tattermusch | 08dea32 | 2015-10-26 17:34:10 -0700 | [diff] [blame] | 103 | internal override CallCredentialsSafeHandle ToNativeCredentials() |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 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. |
Jan Tattermusch | 08dea32 | 2015-10-26 17:34:10 -0700 | [diff] [blame] | 110 | private CallCredentialsSafeHandle ToNativeRecursive(int startIndex) |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 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 | { |
Jan Tattermusch | 08dea32 | 2015-10-26 17:34:10 -0700 | [diff] [blame] | 120 | var nativeComposite = CallCredentialsSafeHandle.CreateComposite(cred1, cred2); |
Jan Tattermusch | 5bd7005 | 2015-10-06 16:47:49 -0700 | [diff] [blame] | 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 | } |