TeamCity 4.0 Help

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