المصادقة مع GitHub (مفاتيح SSH أو tokens)
في هذا الدرس 11 موضوعات
هذا الدرس متاح حاليًا باللغة الإنجليزية فقط، ولم تُنشر نسخته العربية بعد.
Lesson Overview
In the last lesson you connected a local repository to a remote and pushed commits. That worked only because the remote knew you were allowed to write to it. Anyone can read a public repository, but only you (and people you invite) may change yours. So before GitHub accepts a push, it asks: who are you?
This lesson covers the two common safe ways to answer. One is a personal access token, a long random string that you use in place of a password. The other is an SSH key pair, two matching files where you give GitHub one and keep the other secret. You will also learn the one rule that matters most: never commit a token or a private key. Think of the shared bookshelf again: authentication is the key to the library door, and you do not tape your key to the shelf.
GitHub changes its settings pages from time to time, so menu names below are the ones documented when this lesson was written. If your screen differs, search GitHub's documentation for the topic named in each step.
Learning Objectives
By the end of this lesson you will be able to:
- Explain why GitHub does not accept your account password for Git over HTTPS.
- Describe a personal access token and how to treat it.
- Generate an SSH key pair with
ssh-keygen, and say which file is public and which is private. - Add a public key to GitHub, switch a remote to its SSH URL, and test the connection.
- Choose between the HTTPS-plus-token route and the SSH route for a given situation.
- Explain what to do if a secret is committed or pushed by accident.
Written Explanation
Authentication is not authorization
Two words are often mixed up. Authentication proves who you are. Authorization decides what that person may do. GitHub first authenticates you (token or key), then checks whether your account may push to that repository. A repository you do not own will reject your push even if you are authenticated perfectly.
Why not a password?
When you clone, fetch, pull, or push over HTTPS to a private repository, Git asks for a username and password. GitHub's documentation states that account passwords are no longer accepted for Git operations; you supply a personal access token (PAT) where the password goes, or use a tool that obtains credentials for you. This protects you: a token can be limited and revoked without changing your account password.
Route 1: HTTPS with a token
A personal access token is a string you create in your GitHub account settings (under Developer settings, then Personal access tokens). GitHub offers two kinds. Fine-grained tokens can be limited to specific repositories and specific permissions; classic tokens use broad scopes and reach every repository you can access. GitHub recommends fine-grained tokens whenever they can do the job, setting an expiry date, and choosing the minimum permissions needed. Treat a token exactly like a password.
You rarely type a token by hand every time. GitHub recommends letting a helper remember credentials: Git Credential Manager (it ships with current Git for Windows) or the GitHub CLI (gh auth login). On the first HTTPS operation that needs authentication, such a tool can open a browser login, and afterwards the credentials are kept in your system's secure store and reused. Where a manual token is needed, you paste it when Git asks for the password. The username is your GitHub username.
Route 2: SSH keys
An SSH key pair is two files made together:
- The private key stays on your computer. It is your proof of identity. Never share it, never copy it into a project, never commit it.
- The public key is a lock that matches it. It is safe to share, and you upload it to GitHub.
When you connect, GitHub challenges your computer to prove it holds the private key matching a public key on your account. The private key itself is never sent. That is why uploading the public half is safe.
To create a pair, GitHub documents the Ed25519 type:
ssh-keygen -t ed25519 -C "you@example.com"The -C value is only a label (a comment) stored in the public key. Run in a scratch folder with a fixed file name and an empty passphrase (for demonstration only), it printed:
Generating public/private ed25519 key pair.
Your identification has been saved in ./testkey
Your public key has been saved in ./testkey.pub
The key fingerprint is:
SHA256:2LKnZAZduWPYJw7QkS5Jbjml5zNFtoAVhJ9a5GTANnw you@example.comWith default settings, the files are id_ed25519 (private) and id_ed25519.pub (public) in the .ssh folder of your home directory. The .pub ending is your clue: it is the one you upload. When ssh-keygen asks for a passphrase, set one: it encrypts the private key file so a stolen file is not enough. An SSH agent can hold the unlocked key for the session so you do not retype the passphrase on every push; the setup differs by operating system, so follow GitHub's documented steps for yours.
To register the key, copy the full text of the .pub file and paste it into your account settings under SSH and GPG keys, using New SSH key, a descriptive title such as "Home laptop", and the key type "authentication". Then test:
ssh -T git@github.comOn the very first connection, SSH may ask you to confirm the server's fingerprint; GitHub tells you to compare it with the fingerprints GitHub publishes, and only then type yes. On success the message says you have successfully authenticated but that GitHub does not provide shell access. The command then exits with a non-zero code: that is normal, because GitHub intentionally offers no shell.
Finally, point your remote at the SSH URL (the git@github.com:you/repo.git form):
git remote set-url origin git@github.com:you/bank-accounts.git
git remote -vWhich route should you choose?
| HTTPS + token / credential manager | SSH key | |
|---|---|---|
| URL form | https://github.com/you/repo.git | git@github.com:you/repo.git |
| Secret you protect | The token | The private key (and its passphrase) |
| Works behind strict firewalls | Usually yes | Port 22 may be blocked (alternatives exist) |
| Setup | Credential manager handles it | Generate, upload, test once |
| Revoke access | Delete the token | Delete the key on GitHub |
Neither is "more correct". Either is fine for this course.
Secrets do not belong in the repository
Tokens, private keys, passwords, and API keys must never be committed. A repository's history is permanent and everyone who clones gets all of it. Deleting the file in a later commit does not remove it from earlier ones. GitHub scans public repositories for known kinds of secrets, and its advice if one leaks is to revoke or rotate the credential immediately: once revoked, it is worthless, and rewriting history becomes much less urgent. In the previous module you wrote a .gitignore that excludes secrets; that is your first line of defense. Keep tokens and keys in your credential manager, ~/.ssh, or an environment variable, outside any project folder.
Examples
Example 1: generate and inspect a key pair (simple)
ssh-keygen -t ed25519 -C "you@example.com"Press Enter to accept the default location, and choose a passphrase when asked. Now look at the public file:
cat ~/.ssh/id_ed25519.pubThe output is one line starting with ssh-ed25519, then a long string, then your label. Copy it. Never cat and paste the file without .pub: the private one starts with a line -----BEGIN OPENSSH PRIVATE KEY----- and must not leave your machine. (Terminal and folder conventions differ by operating system; Git Bash on Windows accepts these commands.)
Example 2: switch an existing remote to SSH (practical)
Your Bank Accounts repository was pushed over HTTPS last lesson. You uploaded your public key and ssh -T git@github.com greeted you by name. Now switch the remote:
git remote -v
git remote set-url origin git@github.com:you/bank-accounts.git
git remote -vorigin git@github.com:you/bank-accounts.git (fetch)
origin git@github.com:you/bank-accounts.git (push)The output shows the address Git will use from now on. History, branches, and commits are untouched: only the address changed. A git push now authenticates with your key, and it should not ask for your account password. If your key has a passphrase and no agent holds it, Git may ask for the passphrase; that is the key's own protection, not GitHub's.
Example 3: a token almost gets committed (realistic)
You write a small Java tool that calls an API and put the token in a file config.properties next to the code. You run git status:
Untracked files:
config.propertiesStop before git add .. The safe sequence is:
- Add
config.propertiesto.gitignoreand commit the.gitignore. - Keep the real file locally, and commit a harmless
config.example.propertieswith a placeholder liketoken=put-your-token-here. - Read
git statusandgit diff --stagedbefore every commit.
Now the unlucky version: you did commit and push the token. Order matters: first, in GitHub's token settings, delete the token (revoke it). Second, create a replacement and store it outside the repository. Third, remove the file from future commits. Revoking comes first because anything pushed to a public repository must be treated as already seen.
Backend Insight
Backend code touches secrets constantly: database passwords, API keys for payment or email services, signing keys. The habit from this lesson, secrets live outside the repository, is the same habit professionals use: configuration read from the environment or a secret store at run time, with the repository holding only placeholders. Many teams also give automated systems (such as a build server) their own narrow credentials rather than a person's, and GitHub's own guidance prefers minimum permissions and expiring tokens for the same reason: if a credential leaks, the damage should be small and short-lived.
You will also meet authentication as an error: Permission denied (publickey) means GitHub could not match you to an account. Read it as an identity problem, not a Git problem.
Common Mistakes
Mistake 1: Uploading the private key
- Incorrect: pasting the contents of
id_ed25519into GitHub. - Correct: paste the contents of
id_ed25519.pub. GitHub is designed to receive only the public half.
Mistake 2: Using the account password over HTTPS
When Git asks for a password and your account password fails, that is expected: use a token or a credential manager.
Mistake 3: Putting a token in the code, README, or a commit message
Anything in the repository is in the history forever. Keep secrets outside the project and revoke any that leaked.
Mistake 4: Leaving the remote on HTTPS after setting up SSH
You uploaded a key but git remote -v still shows an https:// address, so Git keeps asking for a token. Switch with git remote set-url.
Exercises
Never paste real tokens or private keys into chat tools, screenshots, or exercise answers.
Level A: Foundation
A1. Say whether each belongs on GitHub, or must stay on your machine: private key file, public key file, personal access token, key fingerprint line.
أظهر الحل A1
A1. Public key file: may be uploaded. Private key file: stays on your machine. Personal access token: stays secret (used at login, stored by a credential manager, never in a repo). Fingerprint line: a short summary of the public key, safe to share and used to verify keys.
A2. Why does GitHub's HTTPS Git access not accept your account password?
أظهر الحل A2
A2. GitHub removed password-based authentication for Git because tokens (and keys) can be limited in what they can do, can expire, and can be revoked without changing your account password.
A3. Which URL is the SSH one: https://github.com/you/app.git or git@github.com:you/app.git?
أظهر الحل A3
A3. git@github.com:you/app.git is the SSH URL.
Level B: Application
B1. Write the command that creates an Ed25519 key with the label dev@laptop. Then name the two files it creates (default names) and which one you upload.
أظهر الحل B1
B1. ssh-keygen -t ed25519 -C "dev@laptop". It creates id_ed25519 (private) and id_ed25519.pub (public) in your .ssh folder if you accept the defaults. You upload the .pub file.
B2. Your remote uses HTTPS but you now want SSH. Write the commands to change it and verify the change.
أظهر الحل B2
B2.
git remote set-url origin git@github.com:you/app.git
git remote -v-v should now show git@github.com: addresses for fetch and push.
B3. git push prints Permission denied (publickey). List three things to check, in an order that goes from quick to slow.
أظهر الحل B3
B3. (1) Run git remote -v: is the URL SSH and the right repository? (2) Did you add the public key to the GitHub account that owns or can write to the repository? (3) Run ssh -T git@github.com to see whether authentication works at all; if not, check that the key is loaded in the agent and that you uploaded the matching .pub. If everything above is fine, check that your account has write access to the repository.
Level C: Challenge
C1. A friend committed .env containing a database password and pushed it to a public repository. Write the steps in the right order, with one sentence on why that order. Include what to do about future commits.
أظهر الحل C1
C1. (1) Revoke or change the password in the database (and any other secrets in the file) right away. (2) Create a new password, stored outside the repository. (3) Add .env to .gitignore and stop tracking it (git rm --cached .env, then commit). (4) Optionally clean the history later. The order is important because the secret was public the moment it was pushed: only changing it makes it harmless, and history cleanup is slow and does not undo copies others may have.
C2. Compare tokens and SSH keys for three situations: (a) a laptop at a school with strict network rules, (b) a personal laptop you use daily, (c) a script that only needs to read one repository. Pick one for each and justify it briefly.
أظهر الحل C2
C2. (a) HTTPS with a credential manager or token is a safer bet if the network might block SSH's usual port, since HTTPS is more likely to pass through firewalls. (b) SSH is a good choice: set up once, nothing to type afterward. HTTPS with a credential manager is also fine. (c) A fine-grained token limited to that one repository with read-only access and an expiry date fits the minimum-permission advice.
Mini Challenge
Set up authentication for your own machine, whichever route you prefer, and prove it works.
- SSH route: generate a key with a passphrase, upload the
.pubfile, runssh -T git@github.com, and switch your remote to the SSH URL. Token route: install or enable a credential manager, or create a fine-grained token limited to one repository, with an expiry date. - Run
git pushto a repository you own and confirm it does not ask for your account password. - Write two sentences in your notes: where your private key or token lives, and what you would do first if it leaked.
Check your work: nothing secret is inside any project folder, git remote -v matches your chosen route, and git push succeeds.
Summary & Next Lesson
Key takeaways
- Authentication proves who you are; authorization decides what you may do.
- GitHub does not accept your account password for Git over HTTPS. Use a personal access token or a credential manager.
- An SSH key pair has a private half that never leaves your machine and a public half (
.pub) that you upload to GitHub. ssh -T git@github.comtests the SSH setup, andgit remote set-urlswitches a remote between HTTPS and SSH.- Never commit tokens or keys. If one leaks, revoke it first.
Next lesson
Now that you can push safely, you will use that power in a team-friendly way. The next lesson, "Pull requests and reviews", shows how to propose a change on a branch, get it reviewed, and merge it, instead of pushing straight to main.
Self-check
- Which half of an SSH key do you upload to GitHub?
- What should you use in place of a password when Git asks for one over HTTPS?
- What command tests an SSH connection to GitHub?
- You pushed a token to a public repository. What is the first action?
- Where should secrets be stored?
أظهر الإجابات
- The public key (the
.pubfile). - A personal access token, or a credential manager that supplies credentials for you.
ssh -T git@github.com.- Revoke the token, because it must be treated as already exposed.
- Outside the repository: in a credential manager, the
.sshfolder, or environment or secret configuration, with only placeholders committed.
References
- GitHub Docs, About remote repositories. Supports: HTTPS and SSH URL forms, password authentication for Git no longer accepted, tokens used in its place, credential helpers.
- GitHub Docs, Managing your personal access tokens. Supports: fine-grained versus classic tokens, recommendation to prefer fine-grained, expiry and minimum permissions, treating tokens like passwords, where to create and delete them.
- GitHub Docs, Generating a new SSH key and adding it to the ssh-agent. Supports: the
ssh-keygen -t ed25519 -Ccommand, default file names, passphrase advice, agent use. - GitHub Docs, Adding a new SSH key to your GitHub account. Supports: uploading the
.pubfile, settings location, title and key type. - GitHub Docs, Testing your SSH connection. Supports:
ssh -T git@github.com, the fingerprint check, the success message. - GitHub Docs, Caching your GitHub credentials in Git. Supports: Git Credential Manager and
gh auth login, credentials stored in the system store. - GitHub Docs, About secret scanning. Supports: scanning of public repositories and advice to rotate leaked credentials.
- Not verified: I did not test a real GitHub login. The ssh-keygen output came from a local run; the
git remote -voutput is illustrative.
التطبيق
طبّق هذا الدرس بمختبر الوحدة وتمارينها واختبارها.
تعليم الدرس كمكتمل اختياري ويمكنك التراجع عنه في أي وقت. يبقى تقدمك محفوظًا في هذا المتصفح.