-
Notifications
You must be signed in to change notification settings - Fork 2
Support auth_code, client_credentials, device_code authentication #143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Support auth_code, client_credentials, device_code authentication #143
Conversation
- Detect cached vs new tokens by comparing AccessToken before/after SDK call in PerformDeviceCodeLogin, PerformAuthCodeLogin, PerformClientCredentialsLogin - Add GetAuthMethodKeyFromConfig() to extract grant type from Configuration instead of reading from config file (fixes incorrect auth method detection) - Fix device_code nil pointer by always calling WithDeviceCodeScopes() - Alphabetize PingOne authentication flags in platform export command - Update test assertions and clean up unused parameters Login commands now correctly show "Already authenticated" for cached tokens and "Successfully logged in" only for new authentication.
- Use Cobra flag validation (MarkFlagsMutuallyExclusive/MarkFlagsOneRequired) - Consolidate duplicate switch statements and applyRegionConfiguration functions - Validate auth methods against SDK grant type enums - Use errors.Join() in ClearToken() - Add error handling in GetAuthMethodKey() - Remove worker type support and unused test helpers - Clean up commented code blocks and fix linting issues All three OAuth2 methods tested and working with proper cache detection.
…authentication Add comprehensive OAuth2 authentication support with three methods: - Authorization code flow (auth_code) - now default when no flag specified - Client credentials flow (client_credentials) - Device code flow (device_code) Changes: - Add auth method flags to login command: --auth-code/-a, --client-credentials/-c, --device-code/-d - Make auth_code the default authentication method (no flag required) - Add auth method flags to logout command for targeted credential clearing - Implement keychain storage per auth method using SDK's GenerateKeychainAccountName - Replace custom token key hashing with SDK's built-in implementation - Add comprehensive integration tests for all three authentication flows - Update unit tests with table-driven approach for better coverage - Simplify token verification in tests (SDK handles keychain storage internally)
…code-authentication
- Token validation: Check cached tokens before re-authenticating (all 3 auth methods) - Dual storage: System keychain (primary) + ~/.pingcli/credentials/ (fallback) - --use-keychain flag (default: true) with PINGCLI_AUTH_USE_KEYCHAIN env var - Per-method token storage using hash-based keys to prevent conflicts - Logout clears both keychain and file storage - Updated messages to reflect "storage" instead of "Keychain" * Update 18 auth tests to handle automatic authentication behavior * Fix platform export tests to use correct static error definitions * Add comprehensive test coverage (auth_services_test.go, workflow tests) * Resolve all linting violations (err113, errorlint, nlreturn, gocritic, staticcheck) * Use newly implemented Errors package Enables: pingcli login --auth_code | --client_credentials | --device_code All 83 tests passing (50 command + 33 auth). UAT verified.
Implements dual storage strategy for OAuth2 tokens to ensure reliability across all environments (SSH, containers, CI/CD, desktop). Token Storage: - Primary: OS credential stores (Keychain/Credential Manager/Secret Service) - Secondary: File storage at ~/.pingcli/credentials/*.json - Tokens saved to BOTH locations on authentication - One file per auth method (device-code-token.json, auth-code-token.json, etc.) New --use-keychain Flag: - Controls token retrieval preference (default: true with fallback) - Added to: auth login, platform export, request commands - --use-keychain=true: Keychain only (fails if unavailable) - Default behavior: Try keychain first, fallback to file automatically Commands Updated: - platform export: Added --use-keychain and PingOne auth flags - request: Added --use-keychain and PingOne auth flags Testing: - New test-auth Makefile target for sequential auth test execution - Prevents parallel test resource conflicts - Refactored list_keys_test.go to table-driven pattern Documentation: - Updated README.md with improved installation instructions - Added comprehensive dual storage documentation - Updated auth docs (login.md, logout.md) with storage behavior - Removed redundant overview.md Code Cleanup: - Removed deprecated legacy worker token caching - Removed unused generateLegacyWorkerTokenKey function - Removed unused crypto/sha256 import - Removed local go.mod replacement line
| case options.PINGONE_REGION_CODE: | ||
| switch typedValue := vValue.(type) { | ||
| case *customtypes.PingOneRegionCode: | ||
| case *customtypes.String: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this has been reverted
- refactor redirectURI to include path and port for auth_code flow, update tests - revert auth-specific parallel tests, run all tests in parallel - replace --use-keychain flag with --file-storage flag, which disables keychain usage - remove unused ClearPingOneClientCache method - correct login_interactive file name
* clear any previous token keychain entries or files if previous use of the same grant type was found on login and logout * use new WithStorageName method * update package name call for top level domain * correct context in internal auth method * use GetOptionValue methods to retrieve auth method values * remove redundant login and logout logic based on auth type * return missing configuration error, do not ask user if they'd like to reconfigure * remove unreliable isMissingConfigError, return authentication failed error instead * correct some errors to use PingCLI error type * update logout output message to include where token storage method was removed * correct login and logout documentation * improve error handling and logic in credentials.go * correct comment lines * remove unused pingfederate and pingone files * remove unneeded legacy methods * remove old test-auth references from Makefile * use ParseBool for file storage option * remove redundant check for cached token * require redirecturi port when using device code flow * store profile name and auth method in json file name, adding ability to clean up and remove past used token files. Added test coverage for this as well.
…code, use one environment id for all grant types
…remove unused clearAllTokenFiles function
…t for worker applications
…ction Add token expiry tracking to distinguish between new authentication and cached token reuse. Improve user messaging to clearly indicate when tokens are being refreshed automatically vs. using existing valid tokens.
…and, add fallback for worker environment id, change storage flag to only login command, fix Makefile formatting
…when not in CI environment
| protoc --proto_path=./internal/proto --go_out=./internal --go-grpc_out=./internal ./internal/proto/*.proto | ||
| echo "✅ gRPC code generated." | ||
|
|
||
| test: _check_ping_env ## Run all tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this removed?
| if s == "" { | ||
| return true // default to keychain | ||
| } | ||
| // Back-compat: boolean handling (true => file_system, false => secure_local) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove usage of s here.
| // Format: token-<hash>_<service>_<grantType>_<profile>.json | ||
| // The hash is based on service:environmentID:clientID:grantType for uniqueness | ||
| // Service and profile name are added as suffixes to enable service-specific token management and cleanup | ||
| func generateTokenKey(providerName, profileName, environmentID, clientID, grantType string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method is not used.
| authType = "device_code" | ||
| case "authorizationCode": | ||
| authType = "authorization_code" | ||
| case "authorization_code": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This case doesn't do anything
| authType = "device_code" | ||
| case "authorizationCode": | ||
| authType = "authorization_code" | ||
| case "authorization_code": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"
| } | ||
|
|
||
| // Determine which authentication method was requested and convert to auth type format | ||
| // If flags were provided, they take precedence. Otherwise, preserve configured authType (including legacy 'worker'). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem to preserve the configured auth type. Update comment and include case in the switch specific for auth code.
docs/authentication/logout.md
Outdated
| - **Linux**: Secret Service API (GNOME Keyring/KDE KWallet) | ||
|
|
||
| 2. **File Storage:** | ||
| - `~/.pingcli/credentials/<env-id>_<client-id>_<method>.json` - Encrypted token files |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These aren't encrypted
| } | ||
|
|
||
| // Get and set the environment ID for API endpoints | ||
| // Prefer the environment ID already present on cfg; fallback to profile values. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem right for this method to handle. Remove env logic here
| var tld string | ||
| switch regionCode { | ||
| case customtypes.ENUM_PINGONE_REGION_CODE_AP: | ||
| tld = "asia" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These domains are already defined in pingone_region_code.go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file should be deleted
…eeded backwards compatability messages
Change Description
authorization_code,client_credentials, anddevice_code~/.pingcli/credentials/)--use-keychainflag tologinandexportcommands for storage controlChange Characteristics
Checklist
All full (or complete) PRs that need review prior to merge should have the following box checked.
If contributing a partial or incomplete change (expecting the development team to complete the remaining work) please leave the box unchecked
Required SDK Upgrades
https://github.com/pingidentity/pingone-go-clientv0.5.1Testing
This PR has been tested with:
Shell Command(s)
Testing Results
Expand Results
End-to-end Tests Workflow Links