blob: c1bd95b9e22807196bd68f6894e3ec50d9c8e4fb [file] [log] [blame]
Jan Tattermusch5bd70052015-10-06 16:47:49 -07001#region Copyright notice and license
2
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003// Copyright 2015 gRPC authors.
Jan Tattermusch5bd70052015-10-06 16:47:49 -07004//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005// 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 Tattermusch5bd70052015-10-06 16:47:49 -07008//
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009// http://www.apache.org/licenses/LICENSE-2.0
Jan Tattermusch5bd70052015-10-06 16:47:49 -070010//
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011// 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 Tattermusch5bd70052015-10-06 16:47:49 -070016
17#endregion
18
19using System;
20using System.Collections.Generic;
21using System.Threading.Tasks;
22
23using Grpc.Core.Internal;
24using Grpc.Core.Utils;
25
26namespace 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 Tattermusch18729a02015-10-08 18:40:00 -070045 /// 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 Tattermusch5bd70052015-10-06 16:47:49 -070055 /// Creates native object for the credentials.
56 /// </summary>
57 /// <returns>The native credentials.</returns>
Jan Tattermusch08dea322015-10-26 17:34:10 -070058 internal abstract CallCredentialsSafeHandle ToNativeCredentials();
Jan Tattermusch5bd70052015-10-06 16:47:49 -070059 }
60
61 /// <summary>
Jan Tattermusch5bd70052015-10-06 16:47:49 -070062 /// 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 Tattermusch18729a02015-10-08 18:40:00 -070065 internal sealed class MetadataCredentials : CallCredentials
Jan Tattermusch5bd70052015-10-06 16:47:49 -070066 {
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 Tattermusch7a3ee6a2016-02-18 10:36:02 -080075 this.interceptor = GrpcPreconditions.CheckNotNull(interceptor);
Jan Tattermusch5bd70052015-10-06 16:47:49 -070076 }
77
Jan Tattermusch08dea322015-10-26 17:34:10 -070078 internal override CallCredentialsSafeHandle ToNativeCredentials()
Jan Tattermusch5bd70052015-10-06 16:47:49 -070079 {
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 Tattermusch7a3ee6a2016-02-18 10:36:02 -080099 GrpcPreconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials.");
Jan Tattermusch5bd70052015-10-06 16:47:49 -0700100 this.credentials = new List<CallCredentials>(credentials);
101 }
102
Jan Tattermusch08dea322015-10-26 17:34:10 -0700103 internal override CallCredentialsSafeHandle ToNativeCredentials()
Jan Tattermusch5bd70052015-10-06 16:47:49 -0700104 {
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 Tattermusch08dea322015-10-26 17:34:10 -0700110 private CallCredentialsSafeHandle ToNativeRecursive(int startIndex)
Jan Tattermusch5bd70052015-10-06 16:47:49 -0700111 {
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 Tattermusch08dea322015-10-26 17:34:10 -0700120 var nativeComposite = CallCredentialsSafeHandle.CreateComposite(cred1, cred2);
Jan Tattermusch5bd70052015-10-06 16:47:49 -0700121 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}