Skip to content
This repository was archived by the owner on Dec 4, 2023. It is now read-only.

Commit d936ed0

Browse files
authored
Added CertificateAppCredentials (untested) (#998)
1 parent 46398f0 commit d936ed0

File tree

5 files changed

+318
-3
lines changed

5 files changed

+318
-3
lines changed

libraries/bot-builder/src/main/java/com/microsoft/bot/builder/BotFrameworkAdapter.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1218,11 +1218,26 @@ private CompletableFuture<AppCredentials> getAppCredentials(String appId, String
12181218
return CompletableFuture.completedFuture(appCredentials);
12191219
}
12201220

1221+
// Create a new AppCredentials and add it to the cache.
1222+
return buildAppCredentials(appId, scope)
1223+
.thenApply(credentials -> {
1224+
appCredentialMap.put(cacheKey, credentials);
1225+
return credentials;
1226+
});
1227+
}
1228+
1229+
/**
1230+
* Creates an AppCredentials object for the specified appId and scope.
1231+
*
1232+
* @param appId The appId.
1233+
* @param scope The scope.
1234+
* @return An AppCredentials object.
1235+
*/
1236+
protected CompletableFuture<AppCredentials> buildAppCredentials(String appId, String scope) {
12211237
return credentialProvider.getAppPassword(appId).thenApply(appPassword -> {
12221238
AppCredentials credentials = channelProvider != null && channelProvider.isGovernment()
12231239
? new MicrosoftGovernmentAppCredentials(appId, appPassword, scope)
12241240
: new MicrosoftAppCredentials(appId, appPassword);
1225-
appCredentialMap.put(cacheKey, credentials);
12261241
return credentials;
12271242
});
12281243
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for
3+
// license information.
4+
5+
package com.microsoft.bot.connector.authentication;
6+
7+
import java.io.IOException;
8+
import java.security.KeyStoreException;
9+
import java.security.NoSuchAlgorithmException;
10+
import java.security.NoSuchProviderException;
11+
import java.security.UnrecoverableKeyException;
12+
import java.security.cert.CertificateException;
13+
14+
/**
15+
* AppCredentials using a certificate.
16+
*/
17+
public class CertificateAppCredentials extends AppCredentials {
18+
private Authenticator authenticator;
19+
20+
/**
21+
* Initializes a new instance of the AppCredentials class.
22+
*
23+
* @param withOptions The options for CertificateAppCredentials.
24+
* @throws CertificateException During Authenticator creation.
25+
* @throws UnrecoverableKeyException During Authenticator creation.
26+
* @throws NoSuchAlgorithmException During Authenticator creation.
27+
* @throws KeyStoreException During Authenticator creation.
28+
* @throws NoSuchProviderException During Authenticator creation.
29+
* @throws IOException During Authenticator creation.
30+
*/
31+
public CertificateAppCredentials(CertificateAppCredentialsOptions withOptions)
32+
throws CertificateException,
33+
UnrecoverableKeyException,
34+
NoSuchAlgorithmException,
35+
KeyStoreException,
36+
NoSuchProviderException,
37+
IOException {
38+
39+
super(withOptions.getChannelAuthTenant(), withOptions.getoAuthScope());
40+
41+
// going to create this now instead of lazy loading so we don't have some
42+
// awkward InputStream hanging around.
43+
authenticator =
44+
new CertificateAuthenticator(withOptions, new OAuthConfiguration(oAuthEndpoint(), oAuthScope()));
45+
}
46+
47+
/**
48+
* Returns a CertificateAuthenticator.
49+
*
50+
* @return An Authenticator object.
51+
*/
52+
@Override
53+
protected Authenticator buildAuthenticator() {
54+
return authenticator;
55+
}
56+
}
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for
3+
// license information.
4+
5+
package com.microsoft.bot.connector.authentication;
6+
7+
import java.io.InputStream;
8+
9+
/**
10+
* CertificateAppCredentials Options.
11+
*/
12+
public class CertificateAppCredentialsOptions {
13+
private String appId;
14+
private String channelAuthTenant;
15+
private String oAuthScope;
16+
private InputStream pkcs12Certificate;
17+
private String pkcs12Password;
18+
private boolean sendX5c = true;
19+
20+
/**
21+
* Initializes the CertificateAppCredentialsOptions with the required arguments.
22+
*
23+
* @param withAppId The Microsoft app ID.
24+
* @param withPkcs12Certificate The InputStream to the pkcs certificate.
25+
* @param withPkcs12Password The pkcs certificate password.
26+
*/
27+
public CertificateAppCredentialsOptions(
28+
String withAppId,
29+
InputStream withPkcs12Certificate,
30+
String withPkcs12Password
31+
) {
32+
this(withAppId, withPkcs12Certificate, withPkcs12Password, null, null, true);
33+
}
34+
35+
/**
36+
* Initializes the CertificateAppCredentialsOptions.
37+
*
38+
* @param withAppId The Microsoft app ID.
39+
* @param withPkcs12Certificate The InputStream to the pkcs certificate.
40+
* @param withPkcs12Password The pkcs certificate password.
41+
* @param withChannelAuthTenant Optional. The oauth token tenant.
42+
* @param withOAuthScope Optional. The scope for the token.
43+
* @param withSendX5c Specifies if the x5c claim (public key of the
44+
* certificate) should be sent to the STS.
45+
*/
46+
public CertificateAppCredentialsOptions(
47+
String withAppId,
48+
InputStream withPkcs12Certificate,
49+
String withPkcs12Password,
50+
String withChannelAuthTenant,
51+
String withOAuthScope,
52+
boolean withSendX5c
53+
) {
54+
appId = withAppId;
55+
channelAuthTenant = withChannelAuthTenant;
56+
oAuthScope = withOAuthScope;
57+
pkcs12Certificate = withPkcs12Certificate;
58+
pkcs12Password = withPkcs12Password;
59+
sendX5c = withSendX5c;
60+
}
61+
62+
/**
63+
* Gets the Microsfot AppId.
64+
*
65+
* @return The app id.
66+
*/
67+
public String getAppId() {
68+
return appId;
69+
}
70+
71+
/**
72+
* Sets the Microsfot AppId.
73+
*
74+
* @param withAppId The app id.
75+
*/
76+
public void setAppId(String withAppId) {
77+
appId = withAppId;
78+
}
79+
80+
/**
81+
* Gets the Channel Auth Tenant.
82+
*
83+
* @return The OAuth Channel Auth Tenant.
84+
*/
85+
public String getChannelAuthTenant() {
86+
return channelAuthTenant;
87+
}
88+
89+
/**
90+
* Sets the Channel Auth Tenant.
91+
*
92+
* @param withChannelAuthTenant The OAuth Channel Auth Tenant.
93+
*/
94+
public void setChannelAuthTenant(String withChannelAuthTenant) {
95+
channelAuthTenant = withChannelAuthTenant;
96+
}
97+
98+
/**
99+
* Gets the OAuth scope.
100+
*
101+
* @return The OAuthScope.
102+
*/
103+
public String getoAuthScope() {
104+
return oAuthScope;
105+
}
106+
107+
/**
108+
* Sets the OAuth scope.
109+
*
110+
* @param withOAuthScope The OAuthScope.
111+
*/
112+
public void setoAuthScope(String withOAuthScope) {
113+
oAuthScope = withOAuthScope;
114+
}
115+
116+
/**
117+
* Gets the InputStream to the PKCS12 certificate.
118+
*
119+
* @return The InputStream to the certificate.
120+
*/
121+
public InputStream getPkcs12Certificate() {
122+
return pkcs12Certificate;
123+
}
124+
125+
/**
126+
* Sets the InputStream to the PKCS12 certificate.
127+
*
128+
* @param withPkcs12Certificate The InputStream to the certificate.
129+
*/
130+
public void setPkcs12Certificate(InputStream withPkcs12Certificate) {
131+
pkcs12Certificate = withPkcs12Certificate;
132+
}
133+
134+
/**
135+
* Gets the pkcs12 certiciate password.
136+
*
137+
* @return The password for the certificate.
138+
*/
139+
public String getPkcs12Password() {
140+
return pkcs12Password;
141+
}
142+
143+
/**
144+
* Sets the pkcs12 certiciate password.
145+
*
146+
* @param withPkcs12Password The password for the certificate.
147+
*/
148+
public void setPkcs12Password(String withPkcs12Password) {
149+
pkcs12Password = withPkcs12Password;
150+
}
151+
152+
/**
153+
* Gets if the x5c claim (public key of the certificate) should be sent to the
154+
* STS.
155+
*
156+
* @return true to send x5c.
157+
*/
158+
public boolean getSendX5c() {
159+
return sendX5c;
160+
}
161+
162+
/**
163+
* Sets if the x5c claim (public key of the certificate) should be sent to the
164+
* STS.
165+
*
166+
* @param withSendX5c true to send x5c.
167+
*/
168+
public void setSendX5c(boolean withSendX5c) {
169+
sendX5c = withSendX5c;
170+
}
171+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for
3+
// license information.
4+
5+
package com.microsoft.bot.connector.authentication;
6+
7+
import com.microsoft.aad.msal4j.ClientCredentialFactory;
8+
import com.microsoft.aad.msal4j.ClientCredentialParameters;
9+
import com.microsoft.aad.msal4j.ConfidentialClientApplication;
10+
import com.microsoft.aad.msal4j.IAuthenticationResult;
11+
import java.io.IOException;
12+
import java.security.KeyStoreException;
13+
import java.security.NoSuchAlgorithmException;
14+
import java.security.NoSuchProviderException;
15+
import java.security.UnrecoverableKeyException;
16+
import java.security.cert.CertificateException;
17+
import java.util.Collections;
18+
import java.util.concurrent.CompletableFuture;
19+
20+
/**
21+
* A provider of tokens for CertificateAppCredentials.
22+
*/
23+
public class CertificateAuthenticator implements Authenticator {
24+
private final ConfidentialClientApplication app;
25+
private final ClientCredentialParameters parameters;
26+
27+
/**
28+
* Constructs an Authenticator using appId and pkcs certificate.
29+
*
30+
* @param withOptions The options for CertificateAppCredentials.
31+
* @param withConfiguration The OAuthConfiguration.
32+
* @throws CertificateException During MSAL app creation.
33+
* @throws UnrecoverableKeyException During MSAL app creation.
34+
* @throws NoSuchAlgorithmException During MSAL app creation.
35+
* @throws KeyStoreException During MSAL app creation.
36+
* @throws NoSuchProviderException During MSAL app creation.
37+
* @throws IOException During MSAL app creation.
38+
*/
39+
public CertificateAuthenticator(CertificateAppCredentialsOptions withOptions, OAuthConfiguration withConfiguration)
40+
throws CertificateException,
41+
UnrecoverableKeyException,
42+
NoSuchAlgorithmException,
43+
KeyStoreException,
44+
NoSuchProviderException,
45+
IOException {
46+
47+
app = ConfidentialClientApplication.builder(
48+
withOptions.getAppId(),
49+
ClientCredentialFactory.createFromCertificate(
50+
withOptions.getPkcs12Certificate(),
51+
withOptions.getPkcs12Password())
52+
)
53+
.authority(withConfiguration.getAuthority()).sendX5c(withOptions.getSendX5c()).build();
54+
55+
parameters = ClientCredentialParameters.builder(Collections.singleton(withConfiguration.getScope())).build();
56+
}
57+
58+
/**
59+
* Returns a token.
60+
*
61+
* @return The MSAL token result.
62+
*/
63+
@Override
64+
public CompletableFuture<IAuthenticationResult> acquireToken() {
65+
return app.acquireToken(parameters)
66+
.exceptionally(
67+
exception -> {
68+
// wrapping whatever msal throws into our own exception
69+
throw new AuthenticationException(exception);
70+
}
71+
);
72+
}
73+
}

libraries/bot-connector/src/main/java/com/microsoft/bot/connector/authentication/CredentialsAuthenticator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
* An Authenticator using app id and password.
1717
*/
1818
public class CredentialsAuthenticator implements Authenticator {
19-
private ConfidentialClientApplication app;
20-
private ClientCredentialParameters parameters;
19+
private final ConfidentialClientApplication app;
20+
private final ClientCredentialParameters parameters;
2121

2222
/**
2323
* Constructs an Authenticator using appId and appPassword.

0 commit comments

Comments
 (0)