-.- --. .-. --..

Using Git's credential helpers

18 Feb 2015

Git credentials are a easy way to authenticate the connection over non-SSH protocols. One of the more common use-cases is one where an app or an executable uses a Github remote and starts a connection over HTTPS protocol. In this case, you’ll be prompted for your Github username and password. This can get tedious if this were to be done regularly. Luckily, Git provides a way to automate this process via Git credentials.

Pre-defined Credential helpers

Git ships with some default helpers that can be plugged in to achieve this. On my machine, the following ones are available:

store

The store helper is the simplest helper which will save your credentials on disk protected only by file permissions. If you want to use this helper, use the command:

git config --global credential.helper store

Optionally, you can pass-in the file path where the file should be saved:

git config --global credential.helper store --file=path/to/store/the/file

You can store multiple credentials with any of the helpers. Read more about this helper in the manual

cache

The cache helper stores the credentials in memory for a certain period of time. This timeout is configurable by passing the value (in seconds) with the --timeout flag. Since this doesn’t save anything on the filesystem, it’s more secure than the store helper. Read more about this helper in the manual.

osxkeychain

This helper, if available, will use the OSX Keychain app to fetch the credentials. This can be quite handy and, not to mention, way secure than storing them on the file-system.

Refer to this post over at Github that explains how to set up this helper. It also has instructions on how to set up the helper if it’s not present by default.

Using custom helpers

There is another way to add programs that fetch user credentials. The program to run to fetch the credentials can be configured using three different ways. To quote the manual for git credentials:

 1. If the GIT_ASKPASS environment variable is set, the program
    specified by the variable is invoked. A suitable prompt is provided
    to the program on the command line, and the user's input is read
    from its standard output.

 2. Otherwise, if the core.askpass configuration variable is set, its
    value is used as above.

Which means, we can set the path of the program we need to run in the configuration variable core.askpass and Git will run that program for the user specified. An example program that would fetch the credentials might look like this:

#!/usr/bin/env ruby
require 'open3'

USERNAME = 'computer_user_name'
ACCOUNTNAME = 'github_account_name'

command = "sudo -u #{USERNAME} /usr/bin/security -v find-internet-password -g -a #{ACCOUNTNAME} /Users/#{USERNAME}/Library/Keychains/login.keychain"

stdout_and_err = Open3.capture2e(command)
password =
 Array(stdout_and_err)
   .first
   .split("\n")
   .select { |x| x.start_with?("password") }
   .first
puts password.match(/\Apassword\: "(.*)"/).captures.first

__END__

Location of this file: ~/.git_credential_helper.rb

Code snippet adopted from Steve Losh’s Mutt tutorial. Head over there to setup a keychain entry for your GitHub account if you don’t already have one. I’m too lazy to add images to this blog and style them properly, apologies.

Set the file as executable by running chmod +x ~/.git_credential_helper.rb and test it out — after setting up the GitHub keychain item, that is. Assuming you have a remote with the following URL https://github.com/myusername/mysecretproject, update the Git configuration to use the helper whenever it needs authentication:

$ git config --global \
credential.https://github.com/myusername/mysecretproject.username \
your_github_account_name

Note that the remote url is appended with a trailing .username fragment which becomes the key and the GitHub username becomes the value. Check the file ~/.gitconfig under the [credentials] section to see how this structure looks.

Once the username is set, map the helper:

$ git config --global core.askpass ~/.git_credential_helper.rb

Voilá! Next time you try to fetch the remote data via the HTTPS remote, you won’t be prompted for the credentials. Instead, the credentials will be queried using OSX’s keychain helper.