Skip to content

Commit ad59fda

Browse files
committed
feat(auth): support ChatGPT subscription auth via base64 auth.json
- Add input "codex-auth-json-b64" and write auth.json securely - New CLI command "write-auth-json" to decode/validate/write credentials - Update safety steps to protect subscription creds - Avoid proxy steps for subscription-only runs - Add code-review example using subscription auth - Update docs (README, security)
1 parent 02e7b29 commit ad59fda

File tree

7 files changed

+714
-371
lines changed

7 files changed

+714
-371
lines changed

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,15 @@ jobs:
8888
});
8989
```
9090
91+
For a ChatGPT subscription auth variant, see `examples/code-review-subscription.yml`.
92+
9193
## Inputs
9294

9395
| Name | Description | Default |
9496
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
9597
| `openai-api-key` | Secret used to start the Responses API proxy when you are using OpenAI (default). Store it in `secrets`. | `""` |
9698
| `responses-api-endpoint` | Optional Responses API endpoint override, e.g. `https://example.openai.azure.com/openai/v1/responses`. Leave empty to use the proxy's default. | `""` |
99+
| `codex-auth-json-b64` | Base64-encoded contents of `auth.json` for Codex CLI (ChatGPT subscription auth). The action decodes and writes it to `CODEX_HOME/auth.json`. | `""` |
97100
| `prompt` | Inline prompt text. Provide this or `prompt-file`. | `""` |
98101
| `prompt-file` | Path (relative to the repository root) of a file that contains the prompt. Provide this or `prompt`. | `""` |
99102
| `output-file` | File where the final Codex message is written. Leave empty to skip writing a file. | `""` |
@@ -169,6 +172,39 @@ Ultimately, your configured Action might look something like the following:
169172
prompt: "Debug all the things."
170173
```
171174

175+
### Using ChatGPT subscription auth
176+
177+
If you already have a Codex login on a developer machine, you can export your CLI credentials and provide them to this action via a base64-encoded `auth.json`:
178+
179+
1. On a trusted machine where `codex` is logged in, find `auth.json` under `~/.codex/auth.json`.
180+
2. Base64-encode it and save into a GitHub secret:
181+
182+
Linux/macOS:
183+
184+
```bash
185+
base64 -w0 ~/.codex/auth.json
186+
```
187+
188+
macOS (BSD base64):
189+
190+
```bash
191+
base64 -i ~/.codex/auth.json | tr -d '\n'
192+
```
193+
194+
3. In your workflow, pass the secret to the action:
195+
196+
```yaml
197+
- uses: openai/codex-action@v1
198+
with:
199+
codex-auth-json-b64: ${{ secrets.CODEX_AUTH_JSON_B64 }}
200+
prompt: |
201+
Hello from subscription auth.
202+
```
203+
204+
Notes:
205+
- Do not provide both `openai-api-key` and `codex-auth-json-b64` unless you specifically want to use the Responses API proxy; if both are present, the proxy configuration takes precedence.
206+
- `auth.json` is sensitive. This action writes it with file mode `0600`. Prefer `safety-strategy: drop-sudo` or `unprivileged-user` to limit risk.
207+
172208
## Version History
173209

174210
See the [`CHANGELOG`](./CHANGELOG.md) for details.

action.yml

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ inputs:
2222
description: "Optional Responses API endpoint override, e.g. https://example.openai.azure.com/openai/v1/responses. Defaults to the proxy's built-in endpoint when empty."
2323
required: false
2424
default: ""
25+
codex-auth-json-b64:
26+
description: "Base64-encoded contents of Codex auth.json (ChatGPT subscription auth)."
27+
required: false
28+
default: ""
2529
working-directory:
2630
description: "Working directory that Codex should use. Defaults to the repository root."
2731
required: false
@@ -155,6 +159,17 @@ runs:
155159
server_info_file="${{ steps.resolve_home.outputs.codex-home }}/${{ github.run_id }}.json"
156160
echo "server_info_file=$server_info_file" >> "$GITHUB_OUTPUT"
157161
162+
- name: Check server info file presence
163+
id: check_server_info
164+
shell: bash
165+
run: |
166+
server_info_file="${{ steps.derive_server_info.outputs.server_info_file }}"
167+
if [ -s "$server_info_file" ]; then
168+
echo "exists=true" >> "$GITHUB_OUTPUT"
169+
else
170+
echo "exists=false" >> "$GITHUB_OUTPUT"
171+
fi
172+
158173
- name: Check Responses API proxy status
159174
id: start_proxy
160175
if: ${{ inputs['openai-api-key'] != '' }}
@@ -168,6 +183,17 @@ runs:
168183
echo "server_info_file_exists=false" >> "$GITHUB_OUTPUT"
169184
fi
170185
186+
- name: Write Codex auth.json (subscription auth)
187+
if: ${{ inputs['codex-auth-json-b64'] != '' }}
188+
env:
189+
CODEX_AUTH_JSON_B64: ${{ inputs['codex-auth-json-b64'] }}
190+
shell: bash
191+
run: |
192+
node "${{ github.action_path }}/dist/main.js" write-auth-json \
193+
--codex-home "${{ steps.resolve_home.outputs.codex-home }}" \
194+
--safety-strategy "${{ inputs['safety-strategy'] }}" \
195+
--codex-user "${{ inputs['codex-user'] }}"
196+
171197
# This is its own step to minimize the runtime logic that has access to the
172198
# API key. Note we use `env -u PROXY_API_KEY` to ensure extra copies of the
173199
# key do not end up in the memory of the `codex-responses-api-proxy`
@@ -218,7 +244,7 @@ runs:
218244
# This step has an output named `port`.
219245
- name: Read server info
220246
id: read_server_info
221-
if: ${{ inputs['openai-api-key'] != '' || inputs.prompt != '' || inputs['prompt-file'] != '' }}
247+
if: ${{ inputs['openai-api-key'] != '' || steps.check_server_info.outputs.exists == 'true' }}
222248
shell: bash
223249
run: node "${{ github.action_path }}/dist/main.js" read-server-info "${{ steps.derive_server_info.outputs.server_info_file }}"
224250

@@ -232,7 +258,7 @@ runs:
232258
--safety-strategy "${{ inputs['safety-strategy'] }}"
233259
234260
- name: Drop sudo privilege, if appropriate
235-
if: ${{ inputs['safety-strategy'] == 'drop-sudo' && inputs['openai-api-key'] != '' }}
261+
if: ${{ inputs['safety-strategy'] == 'drop-sudo' && (inputs['openai-api-key'] != '' || inputs['codex-auth-json-b64'] != '') }}
236262
shell: bash
237263
run: |
238264
case "${RUNNER_OS}" in
@@ -249,7 +275,7 @@ runs:
249275
esac
250276
251277
- name: Verify sudo privilege removed
252-
if: ${{ inputs['safety-strategy'] == 'drop-sudo' && inputs['openai-api-key'] != '' }}
278+
if: ${{ inputs['safety-strategy'] == 'drop-sudo' && (inputs['openai-api-key'] != '' || inputs['codex-auth-json-b64'] != '') }}
253279
shell: bash
254280
run: |
255281
if sudo -n true 2>/dev/null; then

0 commit comments

Comments
 (0)