Custom Authentication Module
Custom authentication API is based on Sun JAAS API. To provide your own authentication scheme, you should provide a login module class which must implement interface javax.security.auth.spi.LoginModule and register it in the jetbrains.buildServer.serverSide.auth.LoginConfiguration.
For example:
public class CustomLoginModule implements javax.security.auth.spi.LoginModule {
private Subject mySubject;
private CallbackHandler myCallbackHandler;
private Callback[] myCallbacks;
private NameCallback myNameCallback;
private PasswordCallback myPasswordCallback;
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
// We should remember callback handler and create our own callbacks.
// TeamCity authorization scheme supports two callbacks only: NameCallback and PasswordCallback.
// From these callbacks you will receive username and password entered on the login page.
myCallbackHandler = callbackHandler;
myNameCallback = new NameCallback("login:");
myPasswordCallback = new PasswordCallback("password:", false);
// remember references to newly created callbacks
myCallbacks = new Callback[] {myNameCallback, myPasswordCallback};
// Subject is a place where authorized entity credentials are stored.
// When user is successfully authorized, the jetbrains.buildServer.serverSide.auth.ServerPrincipal
// instance should be added to the subject. Based on this information the principal server will know a real name of
// the authorized entity and realm where this entity was authorized.
mySubject = subject;
}
public boolean login() throws LoginException {
// invoke callback handler so that username and password were added
// to the name and password callbacks
try {
myCallbackHandler.handle(myCallbacks);
}
catch (Throwable t) {
throw new LoginException(t.toString());
}
// retrieve login and password
final String login = myNameCallback.getName();
final String password = new String(myPasswordCallback.getPassword());
// perform authentication
if (checkPassword(login, password)) {
// create ServerPrincipal and put it in the subject
mySubject.getPrincipals().add(new ServerPrincipal(null, login));
return true;
}
return false;
}
private boolean checkPassword(final String login, final String password) {
return true;
}
public boolean commit() throws LoginException {
// simply return true
return true;
}
public boolean abort() throws LoginException {
return true;
}
public boolean logout() throws LoginException {
return true;
}
}
Now we should register this module in the server. To do so, we create a login module descriptor:
public class CustomLoginModuleDescriptor implements jetbrains.buildServer.serverSide.auth.LoginModuleDescriptor {
// Spring framework will provide reference to LoginConfiguration when
// the CustomLoginModuleDescriptor is instantiated
public CustomLoginModuleDescriptor(LoginConfiguration loginConfiguration) {
// register this descriptor in the login configuration
loginConfiguration.registerLoginModule(this);
}
public Class<? extends LoginModule> getLoginModuleClass() {
// return our custom login module class
return CustomLoginModule.class;
}
public Map<String, ?> getOptions() {
// return options which can be passed to our custom login module
// for example, we could store reference to SBuildServer instance here
return null;
}
public String getTextForLoginPage() {
// return text to show on the login page which could describe
// what should be entered in the user name and password fields
return null;
}
public String getDisplayName() {
// presentable name of this plugin
return "My custom authentication plugin";
}
}
Finally we should create build-server-plugin-ourUserAuth.xml
and zip archive with plugin classes as it is described Plugins Packaging and write there CustomLoginModuleDescriptor
bean:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="constructor">
<bean id="customLoginModuleDescriptor" class="some.package.CustomLoginModuleDescriptor"/>
</beans>
Now you should be able to change authentication scheme by specifying name of your class in the main-config.xml file, Authentication Settings.
Last modified: 20 April 2023