Commit f099834
feat: Config-driven opt-in authentication registry with multi-platform support (#2393)
* Initial plan
* feat: add authentication provider registry (GitHub + Azure DevOps)
Agent-Logs-Url: https://github.com/github/spec-kit/sessions/da7ecfd0-e1c9-48dc-b692-27be0879e976
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
* feat: add try-each-provider HTTP helper and wire all catalog fetches through auth registry
- Add authentication/http.py with open_url() that tries each configured
provider in registry order, falling through on 401/403 to the next,
and finally to unauthenticated
- Add build_request() for one-shot request construction
- Add configured_providers() to registry __init__
- Remove api_base_url() from AuthProvider ABC (unused)
- Remove hosts attribute from providers (no host matching)
- Replace _github_http.py usage in ExtensionCatalog and PresetCatalog
- Wire IntegrationCatalog and WorkflowCatalog through open_url (were unauthenticated)
- Wire _fetch_latest_release_tag() through open_url
- Wire all inline --from-url downloads through open_url
- Fix unused stub variable flagged by code-quality bot
- 49 auth tests (positive + negative), 1805 total tests passing
* fix: address review — fix stale docstrings, restore Accept header, add extra_headers to open_url
- Fix _open_url() docstrings in extensions.py and presets.py that
incorrectly claimed redirect stripping behavior
- Add extra_headers parameter to open_url() so callers can pass
additional headers (e.g. Accept) that persist across retries
- Restore Accept: application/vnd.github+json header in
_fetch_latest_release_tag() via extra_headers
* feat: config-driven opt-in auth via ~/.specify/auth.json
Security-first redesign: no credentials are sent unless the user
explicitly creates ~/.specify/auth.json mapping hosts to providers.
- Add authentication/config.py: loads and validates auth.json with
host-to-provider mappings, supports token/token_env/azure-ad/azure-cli
- Refactor AuthProvider ABC: auth_headers(token, scheme) + resolve_token(entry)
- Refactor GitHubAuth: bearer scheme only, token from config entry
- Refactor AzureDevOpsAuth: 4 schemes (basic-pat, bearer, azure-cli, azure-ad)
with dynamic token acquisition for azure-cli and azure-ad
- Rewrite authentication/http.py: host matching, redirect stripping,
provider fallthrough on 401/403, unauthenticated fallback
- Add docs/reference/authentication.md with full reference and template
- 1823 tests passing (67 auth-specific)
* fix: address review — unused imports, host normalization, provider+scheme validation, security hardening
- Remove unused imports (os, field, Any) in config.py
- Normalize hosts during load (strip + lowercase)
- Validate token/token_env are non-empty strings during load
- Validate provider+scheme compatibility during load
- Fix extra_headers order: auth headers applied last, cannot be overridden
- Remove unused 'tried' variable in http.py
- Warn (once) on malformed auth.json instead of silent fallback
- URL-encode OAuth2 client credentials body in azure_devops.py
- Update 403 message to mention auth.json configuration
- Fix registry leak in test_register_duplicate (try/finally)
- Fix import style consistency in test_authentication.py
- Add azure-cli and azure-ad token acquisition tests (mock subprocess/urlopen)
- Add autouse fixture to isolate upgrade tests from real auth.json
- 1829 tests passing
* fix: reject unknown providers, validate azure-ad fields, strip Authorization from extra_headers
- Reject unknown provider keys during auth.json load with clear error message
- Validate azure-ad tenant_id/client_id/client_secret_env as non-empty strings
- Strip Authorization from extra_headers in both build_request and open_url
to prevent accidental or intentional bypass of provider-configured auth
- Add tests for unknown provider and incompatible scheme validation
- 1831 tests passing
* fix: extract shared auth test helpers, global config isolation, align docstring
- Move _inject_github_config / make_github_auth_entry to tests/auth_helpers.py
to eliminate duplication across test_extensions, test_presets, test_upgrade
- Move auth config isolation fixture to global conftest.py (autouse) so ALL
tests are isolated from ~/.specify/auth.json, not just test_upgrade
- Align load_auth_config docstring with actual behavior: ValueError may be
caught by higher-level HTTP helpers that warn and continue unauthenticated
- 1831 tests passing
* fix: preserve auth header across multi-hop redirect chains
- Read Authorization from both headers and unredirected_hdrs in
_StripAuthOnRedirect to survive multi-hop chains within allowed hosts
- Add test_multi_hop_redirect_within_hosts_preserves_auth
- 1832 tests passing
* fix: use resolved config path in warning/error messages and patch build_opener in no-network test
Agent-Logs-Url: https://github.com/github/spec-kit/sessions/86df9557-54f1-4fe4-a25f-9501cb2356cf
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
* fix: assert full resolved config path in rate-limit output test
Agent-Logs-Url: https://github.com/github/spec-kit/sessions/86df9557-54f1-4fe4-a25f-9501cb2356cf
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
* fix: close HTTPError on 401/403, remove _VALID_AUTH_SCHEMES, catch TimeoutExpired, skip POSIX test on Windows, remove unused import
Agent-Logs-Url: https://github.com/github/spec-kit/sessions/a1e29737-dd6e-4287-96c1-509e0c96fb21
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
* fix: use stable ~/.specify/auth.json in rate-limit message, skip POSIX permission check on Windows
Agent-Logs-Url: https://github.com/github/spec-kit/sessions/4636bcdb-87ae-45d6-9545-a40e4effd617
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
* fix: validate host patterns, cache auth config per-process
Agent-Logs-Url: https://github.com/github/spec-kit/sessions/889b58a7-7f8c-47e2-8056-931ebcc671cc
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
* fix: clarify _is_valid_host_pattern docstring, clean up test sentinel type
Agent-Logs-Url: https://github.com/github/spec-kit/sessions/889b58a7-7f8c-47e2-8056-931ebcc671cc
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
* fix: improve _is_valid_host_pattern docstring and test observability
Agent-Logs-Url: https://github.com/github/spec-kit/sessions/889b58a7-7f8c-47e2-8056-931ebcc671cc
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>1 parent 5563269 commit f099834
19 files changed
Lines changed: 1851 additions & 174 deletions
File tree
- docs/reference
- src/specify_cli
- authentication
- integrations
- workflows
- tests
- integrations
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1762 | 1762 | | |
1763 | 1763 | | |
1764 | 1764 | | |
1765 | | - | |
1766 | | - | |
1767 | | - | |
1768 | | - | |
1769 | | - | |
1770 | | - | |
1771 | | - | |
1772 | | - | |
1773 | | - | |
1774 | | - | |
1775 | | - | |
1776 | | - | |
1777 | | - | |
1778 | | - | |
| 1765 | + | |
| 1766 | + | |
1779 | 1767 | | |
1780 | | - | |
| 1768 | + | |
| 1769 | + | |
| 1770 | + | |
| 1771 | + | |
| 1772 | + | |
1781 | 1773 | | |
1782 | 1774 | | |
1783 | 1775 | | |
| |||
1786 | 1778 | | |
1787 | 1779 | | |
1788 | 1780 | | |
1789 | | - | |
| 1781 | + | |
| 1782 | + | |
| 1783 | + | |
1790 | 1784 | | |
1791 | 1785 | | |
1792 | 1786 | | |
| |||
3381 | 3375 | | |
3382 | 3376 | | |
3383 | 3377 | | |
3384 | | - | |
| 3378 | + | |
| 3379 | + | |
| 3380 | + | |
3385 | 3381 | | |
3386 | 3382 | | |
3387 | 3383 | | |
| |||
4285 | 4281 | | |
4286 | 4282 | | |
4287 | 4283 | | |
4288 | | - | |
| 4284 | + | |
| 4285 | + | |
| 4286 | + | |
4289 | 4287 | | |
4290 | 4288 | | |
4291 | 4289 | | |
| |||
5500 | 5498 | | |
5501 | 5499 | | |
5502 | 5500 | | |
5503 | | - | |
| 5501 | + | |
5504 | 5502 | | |
5505 | 5503 | | |
5506 | 5504 | | |
| |||
5517 | 5515 | | |
5518 | 5516 | | |
5519 | 5517 | | |
5520 | | - | |
| 5518 | + | |
5521 | 5519 | | |
5522 | 5520 | | |
5523 | 5521 | | |
| |||
5613 | 5611 | | |
5614 | 5612 | | |
5615 | 5613 | | |
5616 | | - | |
| 5614 | + | |
5617 | 5615 | | |
5618 | 5616 | | |
5619 | | - | |
| 5617 | + | |
5620 | 5618 | | |
5621 | 5619 | | |
5622 | 5620 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
0 commit comments