Authentication in JGit is mostly on par with native Git. Commonly used protocols like SSH and HTTP(S) and their authentication methods are supported. This article summarizes how to use the JGit authentication API to access remote Git repositories securely.

Though the examples in this article use the CloneCommand, the described techniques can be applied to all classes that connect to remote repositories like FetchCommand, PushCommand, LsRemoteCommand, etc. All of these commands have a common base class – TransportCommand – which offers the methods discussed here.

HTTP(S) – https://example.com/repo.git

Authenticating via HTTP and HTTPS is straightforward. An implementation of CredentialsProvider is used to return the authentication credentials when the command requests them. The CredentialsProvider to be used for a certain command is specified through setCredentialsProvider().

For example, the code below clones a repository over HTTPS and authenticates with username and password.

CloneCommand cloneCommand = Git.cloneRepository(); cloneCommand.setURI( "https://example.com/repo.git" ); cloneCommand.setCredentialsProvider( new UsernamePasswordCredentialsProvider( "user", "password" ) );

The UsernamePasswordCredentialsProvider is an implementation of CredentialsProvider that comes with JGit and uses the given username and password to authenticate.

Alternatively, JGit (version 3.5 and later) can also read credentials from the user’s .netrc file. The NetRCCredentialsProvider uses the first machine entry from the file for authentication.

Though it is not recommendable to send credentials over unsecured connections, the described approach also works for plain HTTP connections like http://example.com/repo.git.



As of now, the CloneCommand does not consider the http.sslVerify configuration setting when connecting via https. SSL certificates and host names will always be verified. As of now, the CloneCommand does not consider theconfiguration setting when connecting via https. SSL certificates and host names will always be verified. This prevents JGit from being able to clone from servers that use self-signed certificates out of the box. See this SO post for how to work around this limitation.



SSH with Public Key – ssh://user@example.com/repo.git

JGit delegates creating and destroying SSH connections to the abstract SshSessionFactory. To use public key authentication for an SSH connection, such a session factory has to be specified for the executed command.

With setTransportConfigCallback(), a TransportConfigCallback interface can be specified to intercept the connection process. Its sole method – named configure() – is called just before a connection is established. It is passed a parameter of type Transport which will be used to copy objects between the local and the remote repository. For each protocol, there is a distinct subclass of Transport that handles the respective details of that protocol.

Like shown below the callback can be used to configure the Transport instance right before it is put into use:

SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() { @Override protected void configure( Host host, Session session ) { // do nothing } }; CloneCommand cloneCommand = Git.cloneRepository(); cloneCommand.setURI( "ssh://user@example.com/repo.git" ); cloneCommand.setTransportConfigCallback( new TransportConfigCallback() { @Override public void configure( Transport transport ) { SshTransport sshTransport = ( SshTransport )transport; sshTransport.setSshSessionFactory( sshSessionFactory ); } } );

JGit provides an abstract JSchConfigSessionFactory that uses JSch to establish SSH connections and requires its configure() to be overridden. Because in the simplest case there isn’t anything to be configured, the example above just overrides the method to let the code compile.

JSchConfigSessionFactory is mostly compatible with OpenSSH, the SSH implementation used by native Git. It loads the known hosts and private keys from their default locations (identity, id_rsa and id_dsa) in the user’s .ssh directory.

If your private key file is named differently or located elsewhere, I recommend to override createDefaultJSch(). After calling the base method, custom private keys can be added like so:

@Override protected JSch createDefaultJSch( FS fs ) throws JSchException { JSch defaultJSch = super.createDefaultJSch( fs ); defaultJSch.addIdentity( "/path/to/private_key" ); return defaultJSch; }

In this example a private key from a custom file location is added. If you look into the JSch JavaDoc you will find further overloaded addIdentity() methods.

In particular, if the private key is password-protected, a passphrase can be specified with addIdentity( "/path/to/private_key", "passphrase" ) .

For the sake of completeness, I should mention that there is also a global session factory. It can be obtained and changed through SshSessionFactory.get/setInstance() and is used as a default if no specific shSessionFactory was configured for a command. However, I recommend refraining from using it. Apart from making it harder to write isolated tests, there might be code outside of your control that changes the global session factory.

SSH with Password – ssh://user@example.com/repo.git

As with using SSH with public keys, an SshSessionFactory must be specified to use password-secured SSH connections. But this time, the session factory’s configure() method has a purpose.

SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() { @Override protected void configure( Host host, Session session ) { session.setPassword( "password" ); } } ); CloneCommand cloneCommand = Git.cloneRepository(); cloneCommand.setURI( "ssh://user@example.com/repo.git" ); cloneCommand.setTransportConfigCallback( new TransportConfigCallback() { @Override public void configure( Transport transport ) { SshTransport sshTransport = ( SshTransport )transport; sshTransport.setSshSessionFactory( sshSessionFactory ); } } );

A JSch session represents a connection to an SSH server and in line 4, the password for the current session is set. The rest of the code is the same that was used to connect via SSH with public key authentication.

Which Authentication Method to Use?

Some authentication methods discussed here can also be combined. For example, setting a credentials provider while attempting to connect to a remote repository via SSH with public-key won’t harm. However, you usually want to know what Transport will be used for a given repository-URL beforehand.

To determine that, use the TransportProtocol’s canHandle() method. It returns true if the protocol can handle the given URL and false otherwise. A list of all registered TransportProtocols can be obtained from Transport.getTransportProtocols(). And once the protocol is known, the appropriate authentication method can be chosen.

Authentication @ GitHub

GitHub supports a variety of protocols and authentications methods, but certainly not all possible combinations. A common mistake, for example, is to try to use SSH with password authentication. But this combination is not supported – only SSH with public keys is.

This comparison of protocols offered by GitHub lists what is supported and what not. Summarized, there is:

Plain Git (e.g. git://github.com/user/repo.git): The transfer is unencrypted and the server is not verified.

HTTPS (e.g. https://github.com/user/repo.git): Works practically everywhere. Uses password authentication for pushing but allows anonymous fetch and clone.

SSH (e.g. ssh://git@github.com:user/repo.git): Uses public key authentication, also for fetch and clone.

Please note one thing if you are accessing a GitHub repository through HTTPS with an OAuth access token. The token does not need to be specified in the URL but only given as a user name. The example below illustrates this:

command.setURI( "https://github.com/user/repo.git" ); command.setCredentialsProvider( new UsernamePasswordCredentialsProvider( "token", "" ) );

Authentication @ GitLab

GitLab offers slightly different authentication methods.

Of course, SSH is also among them (e.g. git@gitlab.com:user/repo.git). It uses public key authentication and, like at GitHub, it can be used to fetch and push.

HTTPS with username and password (e.g. https://gitlab.com/user/repo.git) is also supported. It uses password authentication for pushing but allows anonymous fetch and clone. The username and password need to be passed through a UsernamePasswordCredentialsProvider like this:

command.setCredentialsProvider( new UsernamePasswordCredentialsProvider( "username", "password" ) );

In addition, the GitLab Profile Settings allow to create Personal Access Tokens. These can also be used to authenticate HTTPS connections. Access tokens can have an expiration date or can be revoked manually at any time.

In order to use an access token, it must be encoded into the URL and given as a password as shown below:

command.setURI( "https://gitlab-ci-token:a1b2..x7z@gitlab.com/user/repo.git" ); command.setCredentialsProvider( new UsernamePasswordCredentialsProvider( "username", "a1b2..x7z" ) );

Concluding JGit Authentication

While I find the authentication facilities are a bit widely scattered over the JGit API, they get the task done. The recipes given here hopefully provide you with the necessary basics to authenticate connections in JGit and to hide the complexities of the API could be seen as an exercise to practice clean code ;)

In order to help with setting up the development environment, you may want to also read An Introduction to the JGit Sources. If you have difficulties or further questions, please leave a comment or ask the friendly and helpful JGit community for assistance.