DEV Community

pr4th4m
pr4th4m

Posted on

Custom git credential helper

Git credential helper:

Git credential helper is used to save user credentials, so that user does not require to enter credentials on each git operation.
Git provides few default git credential helpers, see how to use them.
This blog will demonstrate on how to build custom git credential helper.

Simple python cli:

  • Let's write a python cli called auth_helper.py
  #!/usr/bin/env python
  import argparse

  class Credential(object):
      def get(self):
          # logic to get username/password from auth file
          pass
      def store(self):
          # logic to store username/password to auth file
          # its better to encrypt password if its in plain text
          pass
      def erase(self):
          # logic to delete auth file
          pass

  def main():
      parser = argparse.ArgumentParser()
      parser.add_argument('operation', action="store", type=str,
              help="Git action to be performed (get|store|erase)")
      # parser all arguments
      arguments = parser.parse_args()
      # get credentials
      credentials = Credential()

      if arguments.operation == "get":
          creds = credentials.get()
          print("username={0}".format(creds.get("username")))
          print("password={0}".format(creds.get("password")))
      elif arguments.operation == "store":
          credentials.store()
          # if credentials are already stored do not store again
      elif arguments.operation == "erase":
          credentials.erase()
      else:
          print "Invalid git operation"

  if __name__ == "__main__":
      main()
Enter fullscreen mode Exit fullscreen mode
  • This cli takes three git operations as cli arguments get, store and erase.
  • These arguments are not coincident, they are used by git. Let's know more about them.

Git credentials store:

  • Git credentials store looks for three arguments
    • get: called when triggered git pull, git fetch, git push etc.
    • store: called when triggered git pull, git fetch, git push etc.
    • erase: if our provided credentials fail, git will fallback to its own credentials prompt, if this fails as well erase is called.

Git helper configuration:

  • To configure our cli as git helper, trigger the below command
  git config --global credential.https://git.company.com.helper "./path/to/cli/auth_helper.py"
Enter fullscreen mode Exit fullscreen mode
  • This will define auth_helper.py under credential section of .gitconfig file (user's home directory).
  • https://git.company.com is the domain where git is hosted.

Done!! Next time we use git, our auth_helper.py should provide credentials for git authorization.

Top comments (2)

Collapse
 
richie765 profile image
Richard

The most important (and hard to find) information is missing from this post, making it not very useful. Here is a hint should help to figure out the missing parts. It took me quite a while to figure it out so I hope it helps someone.

# Store password
echo "username=john
protocol=https
host=remote-git.com
password=hello" | /usr/lib/git-core/git-credential-store store

# Get password
echo "username=john
protocol=https
host=remote-git.com" | /usr/lib/git-core/git-credential-store get
Collapse
 
mpyth profile image
mPyth • Edited

hi,
I've just tried to execute slightly modified code, but I always get error "fatal: Authentication failed for mydomain/git/myGitRepo.git/".

My environment:

OS version: Microsoft Windows 8.1 Pro
>git --version
git version 2.20.1.windows.1
>python --version
Python 3.8.2

Problem description

In the place of following

    if arguments.operation == "get":
          creds = credentials.get()
          print("username={0}".format(creds.get("username")))
          print("password={0}".format(creds.get("password")))

I've just hardcoded username and password which works when credential.helper is unset :

    if arguments.operation == "get":
        #print("protocol=https")    <-- even try with uncommented this line and the next one, but unsuccessfully
        #print("host=mydomain")
        print("username=myUsername")
        print("password=myPassword")

I've also tried another form of setting credential.helper (it is possible to check which is domain by using sys.stdin.read(), but for this example it is not so important ) :

    git config --global credential.helper abs/path/to/my/pyth/script.py

I read git credential documentation thoroughly, take a look on 5-6 different examples on the net (good example is this link ), but could not get this simple case to work.