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

Added CertificateAppCredentials #998

Merged
merged 2 commits into from
Feb 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1218,11 +1218,26 @@ private CompletableFuture<AppCredentials> getAppCredentials(String appId, String
return CompletableFuture.completedFuture(appCredentials);
}

// Create a new AppCredentials and add it to the cache.
return buildAppCredentials(appId, scope)
.thenApply(credentials -> {
appCredentialMap.put(cacheKey, credentials);
return credentials;
});
}

/**
* Creates an AppCredentials object for the specified appId and scope.
*
* @param appId The appId.
* @param scope The scope.
* @return An AppCredentials object.
*/
protected CompletableFuture<AppCredentials> buildAppCredentials(String appId, String scope) {
return credentialProvider.getAppPassword(appId).thenApply(appPassword -> {
AppCredentials credentials = channelProvider != null && channelProvider.isGovernment()
? new MicrosoftGovernmentAppCredentials(appId, appPassword, scope)
: new MicrosoftAppCredentials(appId, appPassword);
appCredentialMap.put(cacheKey, credentials);
return credentials;
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for
// license information.

package com.microsoft.bot.connector.authentication;

import java.io.IOException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

/**
* AppCredentials using a certificate.
*/
public class CertificateAppCredentials extends AppCredentials {
private Authenticator authenticator;

/**
* Initializes a new instance of the AppCredentials class.
*
* @param withOptions The options for CertificateAppCredentials.
* @throws CertificateException During Authenticator creation.
* @throws UnrecoverableKeyException During Authenticator creation.
* @throws NoSuchAlgorithmException During Authenticator creation.
* @throws KeyStoreException During Authenticator creation.
* @throws NoSuchProviderException During Authenticator creation.
* @throws IOException During Authenticator creation.
*/
public CertificateAppCredentials(CertificateAppCredentialsOptions withOptions)
throws CertificateException,
UnrecoverableKeyException,
NoSuchAlgorithmException,
KeyStoreException,
NoSuchProviderException,
IOException {

super(withOptions.getChannelAuthTenant(), withOptions.getoAuthScope());

// going to create this now instead of lazy loading so we don't have some
// awkward InputStream hanging around.
authenticator =
new CertificateAuthenticator(withOptions, new OAuthConfiguration(oAuthEndpoint(), oAuthScope()));
}

/**
* Returns a CertificateAuthenticator.
*
* @return An Authenticator object.
*/
@Override
protected Authenticator buildAuthenticator() {
return authenticator;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for
// license information.

package com.microsoft.bot.connector.authentication;

import java.io.InputStream;

/**
* CertificateAppCredentials Options.
*/
public class CertificateAppCredentialsOptions {
private String appId;
private String channelAuthTenant;
private String oAuthScope;
private InputStream pkcs12Certificate;
private String pkcs12Password;
private boolean sendX5c = true;

/**
* Initializes the CertificateAppCredentialsOptions with the required arguments.
*
* @param withAppId The Microsoft app ID.
* @param withPkcs12Certificate The InputStream to the pkcs certificate.
* @param withPkcs12Password The pkcs certificate password.
*/
public CertificateAppCredentialsOptions(
String withAppId,
InputStream withPkcs12Certificate,
String withPkcs12Password
) {
this(withAppId, withPkcs12Certificate, withPkcs12Password, null, null, true);
}

/**
* Initializes the CertificateAppCredentialsOptions.
*
* @param withAppId The Microsoft app ID.
* @param withPkcs12Certificate The InputStream to the pkcs certificate.
* @param withPkcs12Password The pkcs certificate password.
* @param withChannelAuthTenant Optional. The oauth token tenant.
* @param withOAuthScope Optional. The scope for the token.
* @param withSendX5c Specifies if the x5c claim (public key of the
* certificate) should be sent to the STS.
*/
public CertificateAppCredentialsOptions(
String withAppId,
InputStream withPkcs12Certificate,
String withPkcs12Password,
String withChannelAuthTenant,
String withOAuthScope,
boolean withSendX5c
) {
appId = withAppId;
channelAuthTenant = withChannelAuthTenant;
oAuthScope = withOAuthScope;
pkcs12Certificate = withPkcs12Certificate;
pkcs12Password = withPkcs12Password;
sendX5c = withSendX5c;
}

/**
* Gets the Microsfot AppId.
*
* @return The app id.
*/
public String getAppId() {
return appId;
}

/**
* Sets the Microsfot AppId.
*
* @param withAppId The app id.
*/
public void setAppId(String withAppId) {
appId = withAppId;
}

/**
* Gets the Channel Auth Tenant.
*
* @return The OAuth Channel Auth Tenant.
*/
public String getChannelAuthTenant() {
return channelAuthTenant;
}

/**
* Sets the Channel Auth Tenant.
*
* @param withChannelAuthTenant The OAuth Channel Auth Tenant.
*/
public void setChannelAuthTenant(String withChannelAuthTenant) {
channelAuthTenant = withChannelAuthTenant;
}

/**
* Gets the OAuth scope.
*
* @return The OAuthScope.
*/
public String getoAuthScope() {
return oAuthScope;
}

/**
* Sets the OAuth scope.
*
* @param withOAuthScope The OAuthScope.
*/
public void setoAuthScope(String withOAuthScope) {
oAuthScope = withOAuthScope;
}

/**
* Gets the InputStream to the PKCS12 certificate.
*
* @return The InputStream to the certificate.
*/
public InputStream getPkcs12Certificate() {
return pkcs12Certificate;
}

/**
* Sets the InputStream to the PKCS12 certificate.
*
* @param withPkcs12Certificate The InputStream to the certificate.
*/
public void setPkcs12Certificate(InputStream withPkcs12Certificate) {
pkcs12Certificate = withPkcs12Certificate;
}

/**
* Gets the pkcs12 certiciate password.
*
* @return The password for the certificate.
*/
public String getPkcs12Password() {
return pkcs12Password;
}

/**
* Sets the pkcs12 certiciate password.
*
* @param withPkcs12Password The password for the certificate.
*/
public void setPkcs12Password(String withPkcs12Password) {
pkcs12Password = withPkcs12Password;
}

/**
* Gets if the x5c claim (public key of the certificate) should be sent to the
* STS.
*
* @return true to send x5c.
*/
public boolean getSendX5c() {
return sendX5c;
}

/**
* Sets if the x5c claim (public key of the certificate) should be sent to the
* STS.
*
* @param withSendX5c true to send x5c.
*/
public void setSendX5c(boolean withSendX5c) {
sendX5c = withSendX5c;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for
// license information.

package com.microsoft.bot.connector.authentication;

import com.microsoft.aad.msal4j.ClientCredentialFactory;
import com.microsoft.aad.msal4j.ClientCredentialParameters;
import com.microsoft.aad.msal4j.ConfidentialClientApplication;
import com.microsoft.aad.msal4j.IAuthenticationResult;
import java.io.IOException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Collections;
import java.util.concurrent.CompletableFuture;

/**
* A provider of tokens for CertificateAppCredentials.
*/
public class CertificateAuthenticator implements Authenticator {
private final ConfidentialClientApplication app;
private final ClientCredentialParameters parameters;

/**
* Constructs an Authenticator using appId and pkcs certificate.
*
* @param withOptions The options for CertificateAppCredentials.
* @param withConfiguration The OAuthConfiguration.
* @throws CertificateException During MSAL app creation.
* @throws UnrecoverableKeyException During MSAL app creation.
* @throws NoSuchAlgorithmException During MSAL app creation.
* @throws KeyStoreException During MSAL app creation.
* @throws NoSuchProviderException During MSAL app creation.
* @throws IOException During MSAL app creation.
*/
public CertificateAuthenticator(CertificateAppCredentialsOptions withOptions, OAuthConfiguration withConfiguration)
throws CertificateException,
UnrecoverableKeyException,
NoSuchAlgorithmException,
KeyStoreException,
NoSuchProviderException,
IOException {

app = ConfidentialClientApplication.builder(
withOptions.getAppId(),
ClientCredentialFactory.createFromCertificate(
withOptions.getPkcs12Certificate(),
withOptions.getPkcs12Password())
)
.authority(withConfiguration.getAuthority()).sendX5c(withOptions.getSendX5c()).build();

parameters = ClientCredentialParameters.builder(Collections.singleton(withConfiguration.getScope())).build();
}

/**
* Returns a token.
*
* @return The MSAL token result.
*/
@Override
public CompletableFuture<IAuthenticationResult> acquireToken() {
return app.acquireToken(parameters)
.exceptionally(
exception -> {
// wrapping whatever msal throws into our own exception
throw new AuthenticationException(exception);
}
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
* An Authenticator using app id and password.
*/
public class CredentialsAuthenticator implements Authenticator {
private ConfidentialClientApplication app;
private ClientCredentialParameters parameters;
private final ConfidentialClientApplication app;
private final ClientCredentialParameters parameters;

/**
* Constructs an Authenticator using appId and appPassword.
Expand Down