Passing credentials in Git Fetch and cache - bash

I am trying to configure a git client to checkout using git fetch followed by git checkout from a bash script.
I have a github PAT (personal access token).
My purpose is to use my github user-id and the PAT to pass to the git fetch command one time such that next git command onwards, it won't require.
I know in git clone, I can pass the password like this:
git clone https://<token>#github.com/<username>/repository.git
I also setup the credential.helper to the cache for credential caching.
git config --global user.name "git-user-id"
git config --global user.email "email"
git config --global credential.helper cache
Now I want to pass the user name and PAT to the git fetch:
git fetch --no-tags --progress --depth=1 -- https://github.com/RepoName/demo-internal.git +refs/heads/<branch>:refs/remotes/origin/<branch>
git checkout <branch>
How can I do it in the git command line?
Note: I am not looking for an interactive way like using Expect or something like that.

You shouldn't place credentials in the URL. The Git FAQ mentions why:
While it is possible to place the password (which must be percent-encoded) in the URL, this is not particularly secure and can lead to accidental exposure of credentials, so it is not recommended.
If your goal is to set up access for your own use (say, a personal or work desktop or laptop), then that FAQ entry tells you how to set up a credential helper that will save your credentials securely long term, using an appropriate encrypted credential store for your system.
If your goal is to set up credentials for some sort of automated system, you can set up a custom credential helper to read from the environment. You could also generate an Ed25519 SSH deploy key and use that.
Note that user.name is not a username; it is a personal name and has no effect on authentication. For example, the maintainer of Git has this value set to “Junio C Hamano.”

Related

Gitbash changing github account

I was using github account A on gitbash and I wanted to switch to B.
I deleted the credentials for github from control panel for account A and signed with B
When I run git config --list, user.email and user.name matched with account A
than I did:
git config --global user.name "AccountB'sname"
git config --global user.email AccountBemail
When I run git config --list , Now user.email and user.name matches with account B. And when I make a commit, It is seem to be with account B. So it's good.
My first question is: Is it all to do when changing github account on gitbash ?
2- why on my first git config --list run, name and email did not match even tho I updated credentials from control panel
Your GitHub credentials and your Git config are two unrelated things.
When you set user.name and user.email, what you are changing is the metadata that will be used in any commits your create. Creating commits is a local operation on your machine, and does not involved talking to GitHub or any other Git server.
When you want to connect to GitHub using a different account, you did the right thing: change your credentials for GitHub in the Windows Credentials Manager. That will not affect how commits are created on your machine, only how you will authenticate yourself when connecting to GitHub.

Git keeps storing credentials in Windows Credential Manager [duplicate]

This question already has answers here:
How do I disable git's credential helper for a single repository?
(5 answers)
Closed 9 months ago.
I'd like to use some git credentials for only single command.
git -c remote.origin.url="http://pass:user#gitserver/GitRepo" push
But after doing that credentials are saved in Credential Manager (i can see them in Windows Credential Manager), and are used implicitly for the subsequent git push commands.
How do I prevent storing them?
First, determine your scope
You might want to disable the use of the Windows Credential Manager in one of three different scopes:
globally, so these creds are never stored in the manager,
locally, so the creds are not stored in the manager for this one repo, or
temporarily, for just one command.
In all cases, the answer is to unset the credential.helper in your configuration, but how you do it depends on the scope.
Globally
Run
git config --global credential.helper ""
and Git will no longer store credentials anywhere for you.
Locally
Once you've cloned a sandbox, you can disable the credential manager for operations inside that sandbox only with this command:
git config --local credential.helper ""
For one command only
Finally, you can use -c on the command line for one time overrides:
git -c credential.helper= <some command>
Locally, revisited
If you're going to disable credential management for a single repo, you'll actually have to use the -c variant when you clone the repo, to turn off credential storage on clone, and the --local setting in that sandbox, to turn off credential storage on push/pull/fetch operations.
Undoing it all
If you change your mind later, you can undo things by removing your own config setting that disables credential management:
git config --global --unset credential.helper
or
git config --local --unset credential.helper
This way, you go back to the system default (that's manager-core in my Git for Windows configuration, which uses the Windows Credential Manager).
Or, you can set your own credential manager choice explicitly, globally or in the sandbox, with:
git config --global credential.helper manager-core
or
git config --local credential.helper manager-core

Bash script to run git commands and automatically enter my username and password [duplicate]

Is it necessary to store the personal access token somewhere locally on the machine after generating it in GitHub?
If yes, is there any preferred way where it could be stored?
Half the point of passwords is that (ideally) you memorize them and the system hashes them, so therefore they're never stored anywhere in plain text.
Yet GitHub's personal access token system seems to basically force you to store the token in plain text?
First, a PAT (Personal Access Token) is not a simple password, but an equivalent that:
you can generate multiple time (for instance, one per machine from which you need to access GitHub repository)
you can revoke at any time (from the GitHub web interface), which makes that PAT obsolete, even if it lingers around on one of those machines.
That differs from your password, which is unique to your account, and cannot be easily changed without having to also modify it everywhere you happen to use it.
Since a PAT can be used in place of a password when performing Git operations over HTTPS with Git on the command line or the API, you can use a git credential helper to cache it securely.
On Windows, for instance, that would use the Windows Credential Manager, through the GCM -- Git Credential Manager -- for Windows, Mac or Linux:
git config --global credential.helper manager-core
# Git 2.39+
git config --global credential.helper manager
(manager-core is being replaced by/renamed as manager for Git 2.39+, Q4 2022)
The first time you are pushing to a repo, a popup will ask for your credentials: username and your PAT.
The next time, it won't ask, and reuse directly that PAT, which remains stored securely in your Credential Manager.
A similar idea applies for Mac with the OSX keychain, and Linux with the GNOME Keyring (in 2021, it would need a DBus session and libsecret), but in 2021, GCM-Core covers those use cases.
The idea remains: store the PAT in an encrypted credentials store.
As mentioned above, the more modern solution (Q4 2020) is Microsoft Git-Credential-Manager-Core, or, Q4 2022, Microsoft Git-Credential-Manager
git config --global credential.helper manager-core
# Git 2.39+:
git config --global credential.helper manager
Before Git 2.39 (Q4 2022), for Linux:
You need for that to install git-credential-manager-core, downloading its latest release, like gcmcore-linux_amd64.2.0.474.41365.deb
sudo dpkg -i <path-to-package>
git-credential-manager-core configure
Although, with GCM (Git-Credential-Manager-Core) on Linux, as noted by Mekky Mayata in the comments, you need to define a git config --global credential.credentialStore first.
See "Credential stores on Linux":
There are four options for storing credentials that Git Credential Manager (GCM) manages on Linux platforms:
freedesktop.org Secret Service API
GPG/pass compatible files
Git's built-in credential cache
Plaintext files
By default, GCM comes not configured.
You can select which credential store to use by setting the GCM_CREDENTIAL_STORE environment variable, or the credential.credentialStore Git configuration setting.
As noted by agent18 in the comments, using git-credential-libsecret after installing libsecret-1-0 and libsecret-1-dev is a good first step.
But, again, that should be now wrapped by credential-manager-core (before Git 2.39).
In my case, in Ubuntu, the accepted solution didn't work with a message like
git: 'credential-manager' is not a git command
but store instead of manager worked well:
git config --global credential.helper store
Alternatively, you can create a ~/.netrc file in home directory and save your login credentials to it.
cat ~/.netrc
machine github.com login <login-id> password <token-password>
Tested on Ubuntu 20.04, almost fresh install, with Git 2.25.1 and unity 7.5.
Authentication basics
Github needs an authentication key (with certain rights tied to said authentication key). A particular auth key has certain rights, (read private repos, read write public repos etc...) and "acts as a password" coupled with rights which can be revoked whenever the user wants.
Personal Access Token
We start with making a PAT. I.E., Settings --> Developer Settings--> Persaonl access tokens --> Generate new token --> Note --> set permissions (repo,repo_hook maybe) --> generate token
git push the repo and type the generated token(very long password) as password when asked.
Storing the password in different ways
Can be done in a file and then using xclip to bring it back to clipboard and paste it everytime (Screw this)
Cache with the help of git commands git config credential.helper cache <time-limit-of-cache>. But you still have to somehow clipboard the password after the timelimit.
Store it permanently in a file with git commands git config credential.helper store (don't use --global). This is NOT ENCRYPTED. You can open the file and read it. (e.g., If someone gets access to your laptop they can pretty much read the Password using a bootable USB (assuming your whole system is not encrypted)).
Or go the encryption route as per here. It is not complicated at all. 3 simple steps.
sudo apt-get install libsecret-1-0 libsecret-1-dev
sudo make --directory=/usr/share/doc/git/contrib/credential/libsecret
git config credential.helper /usr/share/doc/git/contrib/credential/libsecret/git-credential-libsecret
This allows to store the password/personal access token in an encrypted format. The git config file can be found in the .git/config file in your loca repo as shown here, if you ever need it.
P.S.
There are many places that suggest the use of Gnome-keyring but that is apparently deprecated.
Storing passwords/PATs for more than one account
This becomes tricky and it appears as #VonC suggests that we need a Git-Credential-Manager core (GCM core). This answer is enhanced based on my findings in this answer.
First install GCM core
Download latest .deb package
sudo dpkg -i <path-to-package>
git-credential-manager-core configure
git config --global credential.credentialStore secretservice as we use libsecret
Get latest git
In my case I had git 2.25 and got error error: unknown option 'show-scope'. It appears that GCM core is using higher git
(atleast 2.26).
So install the latest and greatest git as per here:
sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
apt list git # shows the latest git currently 2.31
sudo apt-get install git #or sudo apt-get upgrade
Update git remote path with username built in
GCM core needs this to identify the different accounts.:(
git remote set-url origin https://user1#github.com/user1/myRepo1.git
git remote set-url origin https://user2#github.com/user1/myRepo1.git
^^^^^
Your ~/.gitconfig file will thus have the following :
[credential]
helper = /usr/bin/git-credential-manager-core
credentialStore = secretservice
[credential "https://dev.azure.com"]
useHttpPath = true
To store your credentials in cache and avoid logging in every time you perform a git action, follow these steps:
Navigate to your local repository folder.
In the current folder's terminal: git config --global --replace-all credential.helper cache
Perform git push or git pull.
Login with username and access token (access token is your password). The token can be setup in GitHub and have access to repo, workflow, write:packages and delete:packages.
Repeat git push or any git action and you'll find that it doesn't ask for login credentials from now on.
I like to keep them encrypted within the repository and load them using .envrc (https://direnv.net/)
For doing this I use ssh-vault to encrypt the data using my ssh keys that GitHub already is exposing, for example:
echo MY_TOKEN="secret" | ssh-vault -u <github-user> create > my-encypted-vars.ssh
Then the content of .envrc looks something like this:
echo "Enter ssh key password"
context=$(ssh-vault view $HOME/projects/my-encrypted.ssh | tail -n +2)
export ${context}
This will decrypt the data in my-encrypted-vars.ssh file and set MY_TOKEN into my environment variables every time I cd into the project dir.
By doing this tokens/variables are stored "safely" and always ready to use as environment variables
try enabling this to help with persisting across push / pulls
git config credential.helper store
For ongoing cloning of repo / for macOS users / install iTerm2
https://iterm2.com/
Enable Toolbelt
Just click the snippet whenever you need it.
P.S. you are using oh-my-zsh, aren't you?
https://github.com/ohmyzsh/ohmyzsh
You can cache your credentials for a defined time using:
git config --global credential.helper cache
The default cache period is 900 sec (15 min) but can be changed with:
git config --global credential.helper 'cache --timeout=3600'
See the following Github page:
https://docs.github.com/en/github/using-git/caching-your-github-credentials-in-git
This is not a permanent store and as per other comments credentials should not be stored in plain text, which is a security risk. I use a password manager (https://bitwarden.com/) to store the PAT (Personal Access Token) then copy it in for the first use, where it is then cached. A PAT is required if you enable 2FA on your Github account.
Well, you have to save the token somewhere, when you don't want to type it each time your app asks for it :-)
A good solution is using environment variables, as already suggested in one comment.
But you still have to set the environment variable somewhere.
On Windows (which I'm using), you could use the dialog box in the system settings (I don't know if other operating systems have something similar).
I don't do this, I prefer a script in my project.
In a private project, you may commit this to source control, but this is a matter of preference.
In one of my personal projects, I'm calling the GitHub API as well, using a personal access token.
It's a command line app and the end user will save the token in a config file (which is OK).
But I need the token for development as well, because the project has integration tests where I'm calling the GitHub API.
And that project is public on GitHub, so I couldn't save the token in source control.
What I did is this:
I have a batch file (remember, I'm on Windows) called environment-variables.bat which sets all required environment variables including the access token
I'm calling this in my build script and in the batch file I'm using to run my tests
environment-variables.bat is ignored in source control
But in source control, there's environment-variables.bat.sample instead, which contains the same, but a fake token/password.
So I can just rename this file to environment-variables.bat, replace the fake password by the real one, and everything works.
This is not the perfect solution for all cases, though.
In my project, I have the problem that I need to use more tokens/passwords for more APIs in the future.
So the number of tokens in my environment-variables.bat will increase, making it difficult for potential contributors to actually execute all integration tests. And I still don't know how to deal with that.
In my use case, I store the PAT in a password manager, e.g. LastPass, KeePass, 1Password. When I need it in a Linux environment ( e.g. Docker ), I save the PAT in an environment variable and then use git's credential helper setting. For example:
git config --global credential.helper 'cache --timeout 600'
<< eof tr -d ' ' | git credential-cache store
protocol=https
host=github.com
username=nonce
password=${GITHUB_PAT}
eof
With a PAT the username can be anything except blank. Here's a gist that elaborates:
https://gist.github.com/rwcitek/da862e9e27cc28d3e96e62a2ca4b2b64
Use git insteadOf. Basically replace every https://github call with your access tokens + https://
git config --global url."https://<username>:<github-token>#github.com/".insteadOf "https://github.com/
Now every call to github will automatically be appended with your credentials.
I found this great answer in here.
Some more info about git insteadOf.
You can store the github https token using pass.
Two alternatives to map a git host to a pass entry:
bash script to map to the right pass entry:
#!/usr/bin/env bash
# assuming "get" action from git and a config like this
# git config --global credential.helper $XDG_BIN_HOME'/git_credentials_from_pass $#'
while IFS= read -r line
do
echo "$line"
if [[ "$line" =~ host=.*github.com.* ]]; then
echo "username=your_user_name"
echo "password=$(pass show token_github.com/your_username)"
#else ...
fi
done
Change your_username and token_github.com the way you set it up with pass insert.
This adds the token to pass without typing or pasting twice:
echo your_github_token | sed p | pass add token_github.com/your_username
Install pass-git-helper and:
git config --global credential.helper '!pass-git-helper $#'
pass-git-helper needs an ini-file to map between the git request and the pass entry.
${XDG_CONFIG_HOME}/pass-git-helper/git-pass-mapping.ini example:
[DEFAULT]
username_extractor=entry_name
[github.com*]
target=token_${host}/your_github_username
Basically I did this on my machine:
https://gist.github.com/bsara/5c4d90db3016814a3d2fe38d314f9c23
My profile script is slightly different than described:
env=~/.ssh/agent.env
agent_load_env () { test -f "$env" && . "$env" >| /dev/null ; }
agent_start () {
(umask 077; ssh-agent >| "$env")
. "$env" >| /dev/null ;
}
agent_load_env
# agent_run_state: 0=agent running w/ key; 1=agent w/o key; 2= agent not running
agent_run_state=$(ssh-add -l >| /dev/null 2>&1; echo $?)
if [ ! "$SSH_AUTH_SOCK" ] || [ $agent_run_state = 2 ]; then
agent_start
ssh-add
elif [ "$SSH_AUTH_SOCK" ] && [ $agent_run_state = 1 ]; then
ssh-add
fi
unset env
Install Git Credential Manager! https://github.com/GitCredentialManager/git-credential-manager . GCM supports caching as well as a variety of platform-specific credential stores that persist between sessions.
Even better: GCM supports user-friendly secure authentication to GitHub and GitLab via web browser with OAuth. This means you no longer even need to create personal access tokens. When you git push, simply follow a link to GitHub and authorize the app. Subsequent authentications require no interaction.
OAuth is more secure than personal access tokens, because the tokens have short expiry, refreshed when required using longer-lived refresh tokens.
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt update
sudo apt install gh
gh auth login
it will ask to enter the protocol and token
Then I clones the repo again . Its not asking for token

Easy way to switch between accounts on git in the terminal on windows?

Is there a quick way to just log out and log back in with a different account on git in cmd on windows?
I tried:
git config --global --unset user.name
git config --global --unset user.mail
git config --global --unset credential.helper
so I understand I should have been logged out with the old_user_name?
Then I used:
git config --global user.name "new_user_name"
git config --global user.email "new_email"
git push origin master
I got a massage:
remote: Permission to new_user_name/new_repo.git denied to old_user_name.
fatal: unable to access 'https://github.com/new_user_name/new_repo.git/': The requested URL returned error: 403
That means I'm still logged in with the old account. What else can I do?
The user.name and user.email settings are not logins, in any way, shape, or form. (The credential.helper setting is useful here, but just unsetting it is probably not right.)
Whenever you make a new commit (by, e.g., running git commit), Git needs to know what user name and email address to put in the new commit. Git gets these by reading user.name and user.email at that time. That's all they're for: to set these in new commits.1
When you run git push, you do (usually2) need to authenticate in order to send your new commits to some other Git repository. Git does not do this authentication. Git relies on other programs to do it. Those other programs include:
Web servers, via https URLs: here, Git has to send a user name and password or PAT or some other secret to the web server. Git gets these from:
the URL, if they're in the URL;
a credential helper, which you may configure: Windows Git comes with a Windows-specific credential helper, macOS Git comes with a macOS-specific credential helper, and so on; or
as a last resort, reading the user name and password from the keyboard.
Generally the right way to do this is with a credential helper. See the gitcredentials documentation and the specific credential helpers available for your particular Git installation. The problem with method #1 is that the password is visible right there in the URL by anyone looking at your computer; the problem with method #3 is obvious.
Unsetting the credential helper gets you the default for your system. This might not be the best thing to do. For Windows systems, see Remove credentials from Git and in particular VonC's answer here.
Secure Shell (SSH): here, Git simply runs the ssh command. Windows systems come with their own ssh command these days, and Git-for-Windows comes with its own ssh command because the older Windows systems either lacked ssh entirely or provided an inadequate version, so on Windows systems, you must make sure that you configure and use the correct ssh (whatever that may be for your installation).
Since you are using an https:// URL, you will need to set up your credential system. If you wish to use ssh:// URLs, set up ssh.
1Note that git rebase works by copying existing commits to new and (supposedly / intended-to-be) improved ones, so this too uses the settings: it's making new commits.
2One can set up a completely open, anonymous network where anyone can push anything at any time, but these are way too easy to abuse, so nobody does this in practice.

On OS X how do I securely save passwords for git repos accessed via https?

I access a lot of git repos on my Mac, that are cloned via https:
git clone https://git.someserver.com/myrepo1.git
which prompts me for username and password. I'm tired of entering these passwords each time I want to fetch/pull/push, and would like a secure mechanism for remembering them.
You can tell git to use a credential helper to remember your passwords, and rather than use a text file, you can tell it to use the keychain:
git config --global credential.helper osxkeychain
That will be a global setting, so now once you connect to a repo and enter your username/password the first time, it's remembered on subsequent actions.
(this specific answer gleaned from here and here)

Resources