3
3
using Microsoft . Graph . Auth ;
4
4
using Microsoft . Graph . PowerShell . Authentication ;
5
5
using Microsoft . Graph . PowerShell . Authentication . Helpers ;
6
+
6
7
using System ;
7
8
using System . Linq ;
8
9
using System . Net ;
9
10
using System . Net . Http ;
10
11
using System . Security . Cryptography ;
11
12
using System . Security . Cryptography . X509Certificates ;
12
13
using System . Threading . Tasks ;
14
+
13
15
using Xunit ;
14
16
public class AuthenticationHelpersTests
15
17
{
@@ -78,7 +80,7 @@ public void ShouldUseClientCredentialProviderWhenAppOnlyContextIsProvided()
78
80
CertificateName = "cn=dummyCert" ,
79
81
ContextScope = ContextScope . Process
80
82
} ;
81
- CreateSelfSignedCert ( appOnlyAuthContext . CertificateName ) ;
83
+ CreateAndStoreSelfSignedCert ( appOnlyAuthContext . CertificateName ) ;
82
84
83
85
// Act
84
86
IAuthenticationProvider authProvider = AuthenticationHelpers . GetAuthProvider ( appOnlyAuthContext ) ;
@@ -87,12 +89,155 @@ public void ShouldUseClientCredentialProviderWhenAppOnlyContextIsProvided()
87
89
Assert . IsType < ClientCredentialProvider > ( authProvider ) ;
88
90
89
91
// reset
90
- DeleteSelfSignedCert ( appOnlyAuthContext . CertificateName ) ;
92
+ DeleteSelfSignedCertByName ( appOnlyAuthContext . CertificateName ) ;
93
+ GraphSession . Reset ( ) ;
94
+
95
+ }
96
+
97
+ [ Fact ]
98
+ public void ShouldUseInMemoryCertificateWhenProvided ( )
99
+ {
100
+ // Arrange
101
+ var certificate = CreateSelfSignedCert ( "cn=inmemorycert" ) ;
102
+ AuthContext appOnlyAuthContext = new AuthContext
103
+ {
104
+ AuthType = AuthenticationType . AppOnly ,
105
+ ClientId = Guid . NewGuid ( ) . ToString ( ) ,
106
+ Certificate = certificate ,
107
+ ContextScope = ContextScope . Process
108
+ } ;
109
+ // Act
110
+ IAuthenticationProvider authProvider = AuthenticationHelpers . GetAuthProvider ( appOnlyAuthContext ) ;
111
+
112
+ // Assert
113
+ Assert . IsType < ClientCredentialProvider > ( authProvider ) ;
114
+ var clientCredentialProvider = ( ClientCredentialProvider ) authProvider ;
115
+ // Assert: That the certificate created and set above is the same as used here.
116
+ Assert . Equal ( clientCredentialProvider . ClientApplication . AppConfig . ClientCredentialCertificate , certificate ) ;
91
117
GraphSession . Reset ( ) ;
92
-
93
118
}
94
119
95
- private void CreateSelfSignedCert ( string certName )
120
+ [ Fact ]
121
+ public void ShouldUseCertNameInsteadOfPassedInCertificateWhenBothAreSpecified ( )
122
+ {
123
+ // Arrange
124
+ var dummyCertName = "CN=dummycert" ;
125
+ var inMemoryCertName = "CN=inmemorycert" ;
126
+ CreateAndStoreSelfSignedCert ( dummyCertName ) ;
127
+ var inMemoryCertificate = CreateSelfSignedCert ( inMemoryCertName ) ;
128
+ AuthContext appOnlyAuthContext = new AuthContext
129
+ {
130
+ AuthType = AuthenticationType . AppOnly ,
131
+ ClientId = Guid . NewGuid ( ) . ToString ( ) ,
132
+ CertificateName = dummyCertName ,
133
+ Certificate = inMemoryCertificate ,
134
+ ContextScope = ContextScope . Process
135
+ } ;
136
+ // Act
137
+ IAuthenticationProvider authProvider = AuthenticationHelpers . GetAuthProvider ( appOnlyAuthContext ) ;
138
+
139
+ // Assert
140
+ Assert . IsType < ClientCredentialProvider > ( authProvider ) ;
141
+ var clientCredentialProvider = ( ClientCredentialProvider ) authProvider ;
142
+ // Assert: That the certificate used is dummycert, that is in the store
143
+ Assert . NotEqual ( inMemoryCertName , clientCredentialProvider . ClientApplication . AppConfig . ClientCredentialCertificate . SubjectName . Name ) ;
144
+ Assert . Equal ( appOnlyAuthContext . CertificateName , clientCredentialProvider . ClientApplication . AppConfig . ClientCredentialCertificate . SubjectName . Name ) ;
145
+
146
+ //CleanUp
147
+ DeleteSelfSignedCertByName ( appOnlyAuthContext . CertificateName ) ;
148
+ GraphSession . Reset ( ) ;
149
+ }
150
+
151
+ [ Fact ]
152
+ public void ShouldUseCertThumbPrintInsteadOfPassedInCertificateWhenBothAreSpecified ( )
153
+ {
154
+ // Arrange
155
+ var dummyCertName = "CN=dummycert" ;
156
+ var inMemoryCertName = "CN=inmemorycert" ;
157
+ var storedDummyCertificate = CreateAndStoreSelfSignedCert ( dummyCertName ) ;
158
+ var inMemoryCertificate = CreateSelfSignedCert ( inMemoryCertName ) ;
159
+ AuthContext appOnlyAuthContext = new AuthContext
160
+ {
161
+ AuthType = AuthenticationType . AppOnly ,
162
+ ClientId = Guid . NewGuid ( ) . ToString ( ) ,
163
+ CertificateThumbprint = storedDummyCertificate . Thumbprint ,
164
+ Certificate = inMemoryCertificate ,
165
+ ContextScope = ContextScope . Process
166
+ } ;
167
+ // Act
168
+ IAuthenticationProvider authProvider = AuthenticationHelpers . GetAuthProvider ( appOnlyAuthContext ) ;
169
+
170
+ // Assert
171
+ Assert . IsType < ClientCredentialProvider > ( authProvider ) ;
172
+ var clientCredentialProvider = ( ClientCredentialProvider ) authProvider ;
173
+ // Assert: That the certificate used is dummycert (Thumbprint), that is in the store
174
+ Assert . NotEqual ( inMemoryCertName , clientCredentialProvider . ClientApplication . AppConfig . ClientCredentialCertificate . SubjectName . Name ) ;
175
+ Assert . Equal ( appOnlyAuthContext . CertificateThumbprint , clientCredentialProvider . ClientApplication . AppConfig . ClientCredentialCertificate . Thumbprint ) ;
176
+
177
+ //CleanUp
178
+ DeleteSelfSignedCertByThumbprint ( appOnlyAuthContext . CertificateThumbprint ) ;
179
+ GraphSession . Reset ( ) ;
180
+ }
181
+
182
+ [ Fact ]
183
+ public void ShouldThrowIfNonExistentCertNameIsProvided ( )
184
+ {
185
+ // Arrange
186
+ var dummyCertName = "CN=NonExistingCert" ;
187
+ AuthContext appOnlyAuthContext = new AuthContext
188
+ {
189
+ AuthType = AuthenticationType . AppOnly ,
190
+ ClientId = Guid . NewGuid ( ) . ToString ( ) ,
191
+ CertificateName = dummyCertName ,
192
+ ContextScope = ContextScope . Process
193
+ } ;
194
+ // Act
195
+ Action action = ( ) => AuthenticationHelpers . GetAuthProvider ( appOnlyAuthContext ) ;
196
+
197
+ //Assert
198
+ Assert . ThrowsAny < Exception > ( action ) ;
199
+ }
200
+
201
+ [ Fact ]
202
+ public void ShouldThrowIfNullInMemoryCertIsProvided ( )
203
+ {
204
+ // Arrange
205
+ AuthContext appOnlyAuthContext = new AuthContext
206
+ {
207
+ AuthType = AuthenticationType . AppOnly ,
208
+ ClientId = Guid . NewGuid ( ) . ToString ( ) ,
209
+ Certificate = null ,
210
+ ContextScope = ContextScope . Process
211
+ } ;
212
+ // Act
213
+ Action action = ( ) => AuthenticationHelpers . GetAuthProvider ( appOnlyAuthContext ) ;
214
+
215
+ //Assert
216
+ Assert . Throws < ArgumentNullException > ( action ) ;
217
+ }
218
+
219
+ /// <summary>
220
+ /// Create and Store a Self Signed Certificate
221
+ /// </summary>
222
+ /// <param name="certName"></param>
223
+ private static X509Certificate2 CreateAndStoreSelfSignedCert ( string certName )
224
+ {
225
+ var cert = CreateSelfSignedCert ( certName ) ;
226
+ using ( var store = new X509Store ( StoreName . My , StoreLocation . CurrentUser ) )
227
+ {
228
+ store . Open ( OpenFlags . ReadWrite ) ;
229
+ store . Add ( cert ) ;
230
+ }
231
+
232
+ return cert ;
233
+ }
234
+
235
+ /// <summary>
236
+ /// Create a Self Signed Certificate
237
+ /// </summary>
238
+ /// <param name="certName"></param>
239
+ /// <returns></returns>
240
+ private static X509Certificate2 CreateSelfSignedCert ( string certName )
96
241
{
97
242
ECDsa ecdsaKey = ECDsa . Create ( ) ;
98
243
CertificateRequest certificateRequest = new CertificateRequest ( certName , ecdsaKey , HashAlgorithmName . SHA256 ) ;
@@ -108,14 +253,11 @@ private void CreateSelfSignedCert(string certName)
108
253
{
109
254
dummyCert = new X509Certificate2 ( cert . Export ( X509ContentType . Pfx , "P@55w0rd" ) , "P@55w0rd" , X509KeyStorageFlags . PersistKeySet ) ;
110
255
}
111
- using ( X509Store store = new X509Store ( StoreName . My , StoreLocation . CurrentUser ) )
112
- {
113
- store . Open ( OpenFlags . ReadWrite ) ;
114
- store . Add ( dummyCert ) ;
115
- }
256
+
257
+ return dummyCert ;
116
258
}
117
259
118
- private void DeleteSelfSignedCert ( string certificateName )
260
+ private static void DeleteSelfSignedCertByName ( string certificateName )
119
261
{
120
262
using ( X509Store xStore = new X509Store ( StoreName . My , StoreLocation . CurrentUser ) )
121
263
{
@@ -134,6 +276,25 @@ private void DeleteSelfSignedCert(string certificateName)
134
276
xStore . Remove ( xCertificate ) ;
135
277
}
136
278
}
279
+ private static void DeleteSelfSignedCertByThumbprint ( string certificateThumbPrint )
280
+ {
281
+ using ( X509Store xStore = new X509Store ( StoreName . My , StoreLocation . CurrentUser ) )
282
+ {
283
+ xStore . Open ( OpenFlags . ReadWrite ) ;
284
+
285
+ X509Certificate2Collection unexpiredCerts = xStore . Certificates
286
+ . Find ( X509FindType . FindByTimeValid , DateTime . Now , false )
287
+ . Find ( X509FindType . FindByThumbprint , certificateThumbPrint , false ) ;
288
+
289
+ // Only return current cert.
290
+ var xCertificate = unexpiredCerts
291
+ . OfType < X509Certificate2 > ( )
292
+ . OrderByDescending ( c => c . NotBefore )
293
+ . FirstOrDefault ( ) ;
294
+
295
+ xStore . Remove ( xCertificate ) ;
296
+ }
297
+ }
137
298
#endif
138
299
139
300
}
0 commit comments