opencode-oci-oidc
v1.1.13
Published
OpenCode plugin: OCI OIDC Auth — authenticates with OCI IAM (Confidential App or Mobile App / Device flow) and injects Bearer tokens into an OpenAI-compatible LLM endpoint.
Maintainers
Readme
opencode-oci-oidc
An OpenCode plugin that authenticates with Oracle Cloud Infrastructure (OCI) IAM and injects a Bearer token into every request sent to an OpenAI-compatible LLM endpoint running on OCI.
Two auth methods are supported:
| Method | Status | Description |
|--------|--------|-------------|
| confidential_app | Tested | Browser-based OAuth 2.0 Authorization Code flow with a client secret |
| mobile_app | Not tested | OCI Device Authorization Grant (RFC 8628) — no browser, no secret; approve on the OCI Mobile Authenticator app |
Tokens are cached in memory and on disk and refreshed automatically using the refresh token when they expire. If the refresh token is also expired, the plugin prompts for re-authentication.
Installation
npm install opencode-oci-oidcThen add the plugin to your opencode.json:
{
"plugin": ["opencode-oci-oidc"]
}Configuration
Copy oci-auth.config.example.jsonc (included in the package) to one of these locations and fill in your values:
| Location | Scope |
|----------|-------|
| <your-project>/oci-auth.config.jsonc | Per-project (takes priority) |
| ~/.config/opencode/oci-auth.config.jsonc | Machine-wide default |
{
// ── OCI IAM credentials ─────────────────────────────────────────────
"domain_url": "https://idcs-<your-idcs-id>.identity.oraclecloud.com",
"client_id": "<your-client-id>",
// Confidential app: provide client_secret as a plain string or file reference
// Mobile app: omit client_secret entirely
"client_secret": "<your-client-secret>",
// Or reference a file to keep the secret out of this file:
// "client_secret": "{file:~/.secrets/oci-client-secret}",
"redirect_uri": "http://localhost:8888/callback",
"scope": "openid profile",
// Base URL of the OpenAI-compatible LLM endpoint (no trailing slash)
"llm_base_url": "https://<your-oci-gpu-endpoint>/v1",
// ── Plugin behaviour ─────────────────────────────────────────────────
"auth_method": "confidential_app", // or "mobile_app"
"log_level": "INFO" // NONE | ERROR | WARN | INFO | DEBUG | VERBOSE
}Client secret options You can provide the secret as a plain string directly in the config, or use
"{file:~/.secrets/oci-client-secret}"to read it from a separate file (useful if this config file is inside a version-controlled project). The plugin blocks the AI agent from reading files under~/.secrets/.
Provider and model setup
Model IDs, context sizes, and the provider endpoint are managed in opencode.json alongside your other providers — not in the plugin config:
// opencode.json
{
"plugin": ["opencode-oci-oidc"],
"provider": {
"oci-oidc": {
"npm": "@ai-sdk/openai-compatible",
"name": "OCI GPU",
"options": {
"baseURL": "https://<your-oci-gpu-endpoint>/v1"
},
"models": {
"llama-3-1-70b": {
"id": "meta-llama/Llama-3.1-70B-Instruct",
"name": "Llama 3.1 70B (OCI)",
"limit": { "context": 131072, "output": 8192 }
}
}
}
},
"model": "oci-oidc/llama-3-1-70b"
}The plugin automatically injects the Authorization: Bearer <token> header into every request sent to the oci-oidc provider.
Auth flows
Confidential App (browser)
- Run
/connectin OpenCode — a browser window opens to the OCI login page - Complete login; the browser redirects back to
localhost:8888/callback - The plugin exchanges the code for a token, caches it, and subsequent requests are automatic
Mobile App (device flow)
- Run
/connectin OpenCode — a short code is printed to the terminal - Open the OCI Mobile Authenticator app and enter the code
- The plugin polls for approval and caches the token when granted
Tools available to the AI agent
| Tool | Description |
|------|-------------|
| oci_oidc_refresh | Force-refresh the Bearer token (useful after a 401) |
| oci_oidc_status | Show current token validity, expiry, endpoint, and auth method |
OCI application setup
Confidential App
- OCI Console → Identity & Security → Domains → <your domain>
- Integrated Applications → Add Application → Confidential Application
- Under Configure this application as a client:
- Grant types: ✅ Authorization Code, ✅ Refresh Token
- Redirect URL:
http://localhost:8888/callback - Scopes:
openid profile(and any resource scopes your LLM endpoint requires)
- Click Finish → Activate
- Copy Client ID and Client Secret
Mobile App (Device Authorization Grant) [not tested, may nto work]
Same steps as above but:
- Grant types: ✅ Device Code, ✅ Refresh Token
- No client secret needed
Logs
The plugin writes a log file from the moment it loads — even before your config is read. This makes it the primary tool for diagnosing any issue.
Default log file location:
| Platform | Path |
|----------|------|
| Linux / macOS | ~/oci-oidc-debug.log |
| Windows | %LOCALAPPDATA%\opencode-oci-oidc\plugin.log |
To follow logs in real time:
tail -f ~/oci-oidc-debug.logTo enable detailed logging, add these two lines to your oci-auth.config.jsonc:
"log_level": "DEBUG",
"log_file": "~/oci-oidc-debug.log"On Windows, use forward slashes or double backslashes for the path — single backslashes are invalid in JSON and will prevent the config from loading:
"log_file": "C:/Users/you/oci-auth.log" // recommended
"log_file": "C:\\Users\\you\\oci-auth.log" // also validAvailable log levels (most to least verbose): VERBOSE → DEBUG → INFO → WARN → ERROR → NONE
The log file is written to the default path even if your config fails to load. Check the default location first — the
[WARN]entry will show exactly what went wrong and which paths were searched.
Troubleshooting
"undefined/chat/completions" cannot be parsed as a URL
The plugin could not find or read your oci-auth.config.jsonc. Steps to diagnose:
- Open
~/oci-oidc-debug.log— look for a[WARN]entry listing the paths that were searched - Make sure your config file is named exactly
oci-auth.config.jsonc(not.json, notoci-oidc.jsonc) - Place it in one of these locations:
- Per-project: same directory as
opencode.json/opencode.jsonc - Machine-wide:
~/.config/opencode/oci-auth.config.jsonc
- Per-project: same directory as
- Verify the file contains at least
domain_url,client_id, andllm_base_urlwith real values (not<placeholders>) - Validate the JSON is valid — JSONC comments (
// ...) are supported but trailing commas are not
Other issues
| Symptom | Fix |
|---------|-----|
| Browser doesn't open on /connect | Check redirect_uri matches what is registered in your OCI Confidential App |
| Token rejected (401) after previously working | Run oci_oidc_refresh tool or /connect again |
| Plugin keeps retrying auth silently | Check the log for session.error entries — likely a new/changed client secret |
| Hanging after sending a message | Check log for Network timeout — indicates OCI IAM or the LLM endpoint is unreachable |
| No refresh token (has_refresh_token: false in log) | Add offline_access to scope and ensure Refresh Token grant is enabled in the OCI app |
| mobile_app flow not working | This flow has not been tested — only confidential_app is verified to work |
License
MIT — Asad Jahangir
