Add OAuth2 Client Credentials Token credential plugin
- Dominant language
- Python
- Stars
- 9
- Forks
- 41
- Avg merge
- 8d 14h
- Merged PRs (30d)
- 2
Description
## Summary
Add a new external credential plugin that fetches a short-lived bearer token using the OAuth 2.0 `client_credentials` grant. This enables authentication with services that require OAuth2 tokens without storing long-lived credentials.
## Motivation
Azure DevOps has deprecated Personal Access Tokens (PATs) and SSH keys for service-to-service authentication in favour of Microsoft Entra ID (Azure AD) service principals. There is currently no built-in credential plugin to acquire OAuth2 tokens at runtime for use as SCM credentials.
This pattern is not limited to Azure DevOps. Any service that accepts bearer tokens obtained via the `client_credentials` grant can benefit, including:
- **Microsoft Entra ID** for Azure DevOps repositories
- **Keycloak** for on-premises services
- **Okta** and **Auth0** for SaaS integrations
- Any OAuth2-compliant identity provider
## Proposed solution
A new credential plugin (`oauth2_client_credentials`) that:
1. Accepts `token_url`, `client_id`, and `client_secret` as input fields.
2. Accepts an optional `scope` as metadata (set when linking to a target credential).
3. Calls the token endpoint using the `client_credentials` grant on every credential resolution.
4. Returns the `access_token` from the token response.
### Use case: Azure DevOps project sync
1. Admin creates an Entra ID App Registration with a client secret.
2. Admin adds the Service Principal to the ADO organisation with Basic access.
3. An "OAuth2 Client Credentials Token Lookup" credential is created with the Entra token endpoint, client ID, and client secret.
4. A Source Control credential is created with `x-token` as the username and its password field linked to the OAuth2 credential (scope: `499b84ac-1321-427f-aa17-267ca6975798/.default`).
5. Project sync automatically resolves a fresh Entra token on every run.
### Use case: generic OAuth2 provider (e.g. Keycloak)
The same plugin works with any compliant OAuth2 provider. Only the `token_url` and optionally `scope` differ.
## Files to change
- `src/awx_plugins/credentials/oauth2_client_credentials.py` (new plugin module)
- `tests/oauth2_client_credentials_test.py` (unit tests)
- `pyproject.toml` (entry point and optional dependency)
- `tests/importable_test.py` (add to entry point smoke tests)
- `docs/spelling_wordlist.txt` (add Entra, Keycloak if needed)
## Dependencies
- `requests` (already a dependency of several existing plugins)
- `awx_plugins.interfaces` (for `gettext_noop`)
Contributor guide
Research direction
Start with the proposed module at src/awx_plugins/credentials/oauth2_client_credentials.py and inspect the entry point configuration in pyproject.toml. Add unit coverage in tests/oauth2_client_credentials_test.py and include the plugin in tests/importable_test.py; done means resolving a credential requests a client-credentials token and returns its access_token, with the optional scope supported.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- authentication
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100