Authentication
The Symphony BDK authentication API allows developers to authenticate their bots and apps using either RSA or certificate authentication modes.
The following sections will explain you:
- how to authenticate your bot service account
- how to authentication your extension application
- how to use OBO (On Behalf Of) authentication
Bot authentication
In this section we will see how to authenticate a bot service account. You will notice that everything has to be done through your BDK config.yaml
, making your code completely agnostic to authentication modes (RSA or certificate).
Only one of certificate or RSA authentication should be configured in one BDK config.yaml
. If both of them are provided, an AuthInitializationException
will be thrown when you try to authenticate to the bot service account.
Bot authentication using RSA
Read more about RSA authentication here
Required config.yaml
setup:
host: acme.symphony.com
bot:
username: bot-username
privateKey:
path: /path/to/rsa/private-key.pem
Bot authentication using Client Certificate
Read more about Client Certificate authentication here
Required config.yaml
setup:
host: acme.symphony.com
bot:
username: bot-username
certificate:
path: /path/to/certificate.p12
password: YourCertificatePassword
Bot authentication deep-dive
The code snippet below explains how to manually retrieve your bot authentication session. However, note that by default those operations are done behind the scene through the SymphonyBdk
entry point.
@Slf4j
public class Example {
public static void main(String[] args) throws Exception {
// create bdk entry point
final SymphonyBdk bdk = new SymphonyBdk(loadFromClasspath("/config.yaml"));
// at this point your bot is already authenticated
// here's how to retrieve the authentication session
final AuthSession botSession = bdk.botSession();
log.info("sessionToken: {}", botSession.getSessionToken());
log.info("keyManagerToken: {}", botSession.getKeyManagerToken());
// if session has expired (e.g. an API endpoint returns 401), you can manually trigger a re-auth
botSession.refresh();
}
}
Authentication using private key and certificate content
Instead of configuring the path of RSA private key or certificate in config file, you can also authenticate the bot and extension app by using directly the private key or certificate content. This feature is useful when either RSA private key or certificate are fetched from an external secrets storage. The code snippet below will give you an example showing how to set directly the private key content to the Bdk configuration for authenticating the bot.
@Slf4j
public class Example {
public static void main(String[] args) throws Exception {
// Loading the configuration
BdkConfig config = loadFromClasspath("/config.yaml");
byte[] privateKeyContent = FileUtils.readFileToByteArray(new File("path/to/privatekey.pem"));
config.getBot().getPrivateKey().setContent(privateKeyContent);
// create bdk entry point
final SymphonyBdk bdk = new SymphonyBdk(config);
// at this point your bot is already authenticated
// here's how to retrieve the authentication session
final AuthSession botSession = bdk.botSession();
log.info("sessionToken: {}", botSession.getSessionToken());
log.info("keyManagerToken: {}", botSession.getKeyManagerToken());
// if session has expired (e.g. an API endpoint returns 401), you can manually trigger a re-auth
botSession.refresh();
}
}
At the same time, only one of path and the content of private key or certificate are allowed to be configured. If both of them are configured, an AuthInitializationException
will be thrown.
Multiple service accounts
By design, the SymphonyBdk
object contains a single bot session. However, you might want to create an application that has to handle multiple bot sessions, potentially using different authentication modes. This is possible by creating multiple instances of SymphonyBdk
using different configurations:
public class Example {
public static void main(String[] args) throws Exception {
final SymphonyBdk bot1 = new SymphonyBdk(loadFromClasspath("/config-bot1.yaml"));
final SymphonyBdk bot2 = new SymphonyBdk(loadFromClasspath("/config-bot2.yaml"));
// bot2 creates an IM with bot1
bot2.streams().create(bot1.botInfo().getId());
}
}
App authentication
Application authentication is completely optional but remains required if you want to implement the Circle Of trust or if you want to use OBO.
Only one of certificate or RSA authentication should be configured in one BDK config.yaml
. If both of them are provided, an AuthInitializationException
will be thrown when you try to authenticate to the extension application.
App authentication using RSA
Required config.yaml
setup:
host: acme.symphony.com
app:
appId: app-id
privateKey:
path: /path/to/rsa/private-key.pem
App Authentication using Client Certificate
Required config.yaml
setup:
host: acme.symphony.com
app:
appId: app-id
certificate:
path: /path/to/certificate.p12
password: YourCertificatePassword
Circle Of Trust
Read more about Circle Of Trust here
public class Example {
public static void main(String[] args) throws BdkConfigException, AuthInitializationException, AuthUnauthorizedException {
// setup SymphonyBdk facade object
final SymphonyBdk bdk = new SymphonyBdk(loadFromSymphonyDir("config.yaml"));
final AppAuthSession appAuth = bdk.appAuthenticator().authenticateExtensionApp("appToken");
final String ta = appAuth.getAppToken();
final String ts = appAuth.getSymphonyToken();
bdk.appAuthenticator().validateTokens(ta, ts);
}
}
OBO (On Behalf Of) authentication
Read more about OBO authentication here
The following example shows how to retrieve OBO sessions using username
(type String
) or userId
(type Long
) and to call services which have OBO endpoints (users, streams and messages so far):
public class Example {
public static void main(String[] args) throws BdkConfigException, AuthInitializationException, AuthUnauthorizedException {
// setup SymphonyBdk facade object
final SymphonyBdk bdk = new SymphonyBdk(loadFromSymphonyDir("config.yaml"));
final AuthSession oboSessionUsername = bdk.obo("user.name");
final AuthSession oboSessionUserId = bdk.obo(123456789L);
// list streams OBO user "user.name"
bdk.obo(oboSessionUsername).streams().listStreams(new StreamFilter());
// or send a message OBO:
Message message = Message.builder().content("<messageML>Hello, World</messageML>").build();
bdk.obo(oboSessionUserId).messages().send("streamID", message);
}
}
BDK running without Bot username (service account) configured
When the bot username
(service account) is not configured in the Bdk configuration, the bot project will be still runnable but only in the OBO mode if the app authentication is well-configured.
The config.yaml
requires at least the application configuration:
host: acme.symphony.com
app:
appId: app-id
privateKey:
path: /path/to/private-key.pem
If users still try to access to Bdk services directly from SymphonyBdk
facade object, a NoBotConfigException
will be thrown.
The following example shows how a bot project works without bot username
configured:
public class Example {
public static void main(String[] args) throws BdkConfigException, AuthInitializationException, AuthUnauthorizedException {
// setup SymphonyBdk facade object
// a warning will be logged to warn that the bot project will be runnable only in OBO mode
final SymphonyBdk bdk = new SymphonyBdk(loadFromSymphonyDir("no_bot_config.yaml"));
final AuthSession oboSessionUsername = bdk.obo("user.name");
// if user call bdk.streams().listStreams(new StreamFilter()), a NoBotConfigException will be thrown
// list streams OBO user "user.name"
bdk.obo(oboSessionUsername).streams().listStreams(new StreamFilter());
}
}