
Security News
CVE Volume Surges Past 48,000 in 2025 as WordPress Plugin Ecosystem Drives Growth
CVE disclosures hit a record 48,185 in 2025, driven largely by vulnerabilities in third-party WordPress plugins.
@gitlab/opencode-gitlab-auth
Advanced tools
A secure OAuth 2.0 and Personal Access Token authentication plugin for OpenCode that enables seamless integration with GitLab.com and self-hosted GitLab instances.
npm install @gitlab/opencode-gitlab-auth
# Clone the repository
git clone https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth.git
cd opencode-gitlab-auth
# Install dependencies
npm install
# Build the project
npm run build
# Link globally
npm link
# In your OpenCode installation, link the plugin
npm link @gitlab/opencode-gitlab-auth
Add the plugin to your OpenCode configuration:
{
"plugins": ["@gitlab/opencode-gitlab-auth"]
}
For OAuth authentication, you need to register an OAuth application on GitLab:
OpenCode GitLab Authhttp://127.0.0.1:8080/callbackapiexport GITLAB_OAUTH_CLIENT_ID=your_application_id_here
Or create a .env file:
GITLAB_OAUTH_CLIENT_ID=your_application_id_here
Start OpenCode and use the /connect command:
opencode
# In OpenCode:
/connect
Choose your authentication method:
OAuth provides the most secure authentication with automatic token refresh and no need to manage long-lived credentials.
~/.local/share/opencode/auth.json with 600 permissionssequenceDiagram
participant OpenCode
participant Browser
participant GitLab
participant LocalServer as Local Callback Server
participant Storage as Secure Storage
OpenCode->>Browser: 1. Open Authorization URL<br/>(with PKCE challenge)
Browser->>GitLab: 2. Authorization Request
GitLab->>Browser: 3. User Approves
Browser->>LocalServer: 4. Redirect with Auth Code
LocalServer->>GitLab: 5. Token Exchange<br/>(with PKCE verifier)
GitLab->>LocalServer: 6. Access + Refresh Tokens
LocalServer->>Storage: 7. Save Tokens
LocalServer->>OpenCode: 8. Authentication Complete
GITLAB_OAUTH_CLIENT_ID environment variable setPAT authentication is simpler but requires manual token management.
OpenCodeapiglpat-)| Variable | Description | Required | Default |
|---|---|---|---|
GITLAB_OAUTH_CLIENT_ID | OAuth application ID | For OAuth | Bundled ID (limited) |
XDG_DATA_HOME | Custom data directory | No | ~/.local/share |
Credentials are stored in platform-specific locations:
~/.local/share/opencode/auth.json~/.opencode/auth.json$XDG_DATA_HOME/opencode/auth.jsonFile permissions are automatically set to 600 (owner read/write only).
Debug logs are written to:
~/.local/share/opencode/log/gitlab-auth.log~/.opencode/log/gitlab-auth.logLogs include:
opencode-gitlab-auth/
├── src/
│ ├── index.ts # Main plugin entry point
│ ├── oauth-flow.ts # OAuth 2.0 flow implementation
│ ├── callback-server.ts # Local HTTP server for OAuth callbacks
│ └── pkce.ts # PKCE utilities (verifier & challenge)
├── dist/ # Compiled JavaScript (generated)
├── .husky/ # Git hooks for code quality
├── package.json
├── tsconfig.json
└── README.md
index.ts)The main plugin that integrates with OpenCode's authentication system.
Key Functions:
gitlabAuthPlugin() - Main plugin export implementing OpenCode's Plugin interfacedebugLog() - File-based logging that doesn't interfere with UIgetAuthPath() - Platform-aware auth file path resolutionsaveAuthData() - Secure credential storage with proper permissionsExports:
export const gitlabAuthPlugin: Plugin;
export default gitlabAuthPlugin;
Authentication Hook:
interface AuthHook {
provider: 'gitlab';
loader: (auth: () => Promise<AuthData>) => Promise<LoaderResult>;
methods: [OAuthMethod, PATMethod];
}
oauth-flow.ts)Implements the complete OAuth 2.0 authorization code flow with PKCE.
Class: GitLabOAuthFlow
class GitLabOAuthFlow {
constructor(options: OAuthFlowOptions);
// Start OAuth authorization
async authorize(): Promise<AuthorizationResult>;
// Exchange authorization code for tokens
async exchangeAuthorizationCode(
code: string,
codeVerifier: string,
redirectUri: string
): Promise<OAuthTokens>;
// Refresh access token
async exchangeRefreshToken(refreshToken: string): Promise<OAuthTokens>;
}
Interfaces:
interface OAuthFlowOptions {
instanceUrl: string; // GitLab instance URL
clientId: string; // OAuth client ID
scopes: string[]; // Requested scopes
method: 'auto' | 'code'; // Authorization method
timeout?: number; // Timeout in milliseconds
}
interface OAuthTokens {
access_token: string;
refresh_token: string;
expires_in: number;
token_type: string;
scope: string;
created_at: number;
}
interface AuthorizationResult {
code: string; // Authorization code
state: string; // CSRF protection state
codeVerifier: string; // PKCE verifier
}
Flow Steps:
callback-server.ts)Local HTTP server using Fastify to handle OAuth redirects.
Class: CallbackServer
class CallbackServer {
constructor(options?: CallbackServerOptions);
// Start the server
async start(): Promise<void>;
// Wait for OAuth callback
async waitForCallback(): Promise<CallbackResult>;
// Get the actual port being used
getPort(): number;
// Get the full callback URL
getCallbackUrl(): string;
// Close the server
async close(): Promise<void>;
}
Interfaces:
interface CallbackServerOptions {
port?: number; // Port to listen on (0 = random)
host?: string; // Host to bind to (default: 127.0.0.1)
timeout?: number; // Timeout in ms (default: 60000)
}
interface CallbackResult {
code: string; // Authorization code from GitLab
state: string; // State parameter for verification
}
Features:
Callback Route:
GET /callback?code=xxx&state=yyy
Response scenarios:
pkce.ts)Cryptographic functions for OAuth PKCE (Proof Key for Code Exchange).
Functions:
// Generate cryptographically secure random string
function generateSecret(length: number = 43): string;
// Generate SHA-256 code challenge from verifier
function generateCodeChallengeFromVerifier(verifier: string): string;
// Internal: Base64 URL encoding (RFC 4648 Section 5)
function base64UrlEncode(buffer: Buffer): string;
PKCE Flow:
Code Verifier: Random 43-character string
const verifier = generateSecret(43);
// Example: "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
Code Challenge: SHA-256 hash of verifier
const challenge = generateCodeChallengeFromVerifier(verifier);
// Example: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"
Authorization: Send challenge to GitLab
Token Exchange: Send verifier to prove ownership
Security:
crypto module for secure randomnessgraph TB
OpenCode[OpenCode Core]
Plugin[index.ts Plugin]
AuthHook[AuthHook<br/>- loader<br/>- methods OAuth & PAT]
OAuthFlow[oauth-flow.ts<br/>GitLabOAuthFlow]
PATFlow[Direct API Call<br/>/api/v4/user]
CallbackServer[callback-server.ts<br/>CallbackServer Fastify HTTP]
PKCE[pkce.ts<br/>PKCE Utilities Crypto functions]
OpenCode -->|Plugin API| Plugin
Plugin --> AuthHook
AuthHook -->|OAuth Flow| OAuthFlow
AuthHook -->|PAT Flow| PATFlow
OAuthFlow -->|Uses| CallbackServer
OAuthFlow -->|Uses| PKCE
flowchart TD
A[User initiates /connect] --> B[Plugin prompts for instance URL]
B --> C[Generate PKCE verifier & challenge]
C --> D[Start local callback server port 8080]
D --> E[Build authorization URL with:<br/>- client_id<br/>- redirect_uri<br/>- code_challenge SHA-256<br/>- state CSRF token<br/>- scope api]
E --> F[Open browser to authorization URL]
F --> G[User approves on GitLab]
G --> H[GitLab redirects to callback server]
H --> I[Callback server receives:<br/>- code authorization code<br/>- state for verification]
I --> J[Verify state matches]
J --> K[Exchange code for tokens:<br/>POST /oauth/token with:<br/>- code<br/>- code_verifier<br/>- redirect_uri]
K --> L[Receive tokens:<br/>- access_token<br/>- refresh_token<br/>- expires_in]
L --> M[Save to auth.json with 600 permissions]
M --> N[Close callback server]
N --> O[Return success to OpenCode]
flowchart TD
A[User initiates /connect] --> B[Plugin prompts for:<br/>- Instance URL<br/>- Personal Access Token]
B --> C[Validate token format<br/>starts with glpat-]
C --> D[Test token with API call:<br/>GET /api/v4/user<br/>Authorization: Bearer token]
D --> E{Successful?}
E -->|Yes| F[Save token to auth.json]
F --> G[Return success]
E -->|No| H[Return error]
H --> I[Prompt user to try again]
~/.local/share/opencode/auth.json
{
"gitlab": {
"type": "oauth",
"access": "ya29.a0AfH6SMBx...",
"refresh": "1//0gHZPQhYjIsN...",
"expires": 1735948800000,
"enterpriseUrl": "https://gitlab.com"
}
}
Security Measures:
600 (owner read/write only)Traditional OAuth requires a client secret, which can't be securely stored in desktop applications. PKCE solves this:
Without PKCE (Insecure):
sequenceDiagram
participant Client
participant AuthServer as Authorization Server
Client->>AuthServer: client_id + client_secret
Note over Client,AuthServer: Problem: Secret can be extracted from application
With PKCE (Secure):
sequenceDiagram
participant Client
participant AuthServer as Authorization Server
Note over Client: 1. Generate random verifier
Client->>AuthServer: 2. Send SHA-256(verifier) as challenge
Note over AuthServer: 3. Store challenge
Client->>AuthServer: 4. Send verifier to prove ownership
Note over AuthServer: 5. Verify SHA-256(verifier) == challenge
Benefits:
Prevents CSRF attacks where an attacker tricks a user into authorizing their malicious app:
sequenceDiagram
participant Client
participant GitLab
Note over Client: 1. Generate random state: "abc123xyz"
Note over Client: 2. Store state locally
Client->>GitLab: 3. Send state in authorization URL
GitLab->>Client: 4. Include state in redirect
Note over Client: 5. Verify returned state matches stored state
alt State mismatch
Note over Client: 6. Reject (possible attack)
else State matches
Note over Client: 6. Continue authentication
end
Callback server includes rate limiting to prevent abuse:
{
max: 30, // Maximum requests
timeWindow: 60000 // Per 60 seconds
}
Protects against:
import gitlabAuthPlugin from '@gitlab/opencode-gitlab-auth';
// Default export
export default gitlabAuthPlugin;
// Named export
export const gitlabAuthPlugin: Plugin;
// OAuth Flow Options
interface OAuthFlowOptions {
instanceUrl: string;
clientId: string;
scopes: string[];
method: 'auto' | 'code';
timeout?: number;
}
// OAuth Tokens Response
interface OAuthTokens {
access_token: string;
refresh_token: string;
expires_in: number;
token_type: string;
scope: string;
created_at: number;
}
// Callback Server Options
interface CallbackServerOptions {
port?: number;
host?: string;
timeout?: number;
}
// Callback Result
interface CallbackResult {
code: string;
state: string;
}
The plugin implements OpenCode's Plugin interface:
interface Plugin {
auth: AuthHook;
}
interface AuthHook {
provider: string;
loader: (auth: () => Promise<AuthData>) => Promise<LoaderResult>;
methods: AuthMethod[];
}
| Feature | Description | Benefit |
|---|---|---|
| PKCE | Proof Key for Code Exchange | Eliminates need for client secrets |
| State Parameter | Random CSRF token | Prevents cross-site request forgery |
| Secure Storage | 600 file permissions | Protects credentials from other users |
| Token Refresh | Automatic renewal | Reduces exposure window |
| Rate Limiting | 30 req/min on callback | Prevents abuse |
| HTTPS Only | Enforced for GitLab API | Prevents man-in-the-middle attacks |
Protected Against:
Not Protected Against:
Please report security vulnerabilities to the maintainers privately. Do not open public issues for security concerns.
Symptoms:
Solutions:
Check if open command is available:
# macOS
which open
# Linux
which xdg-open
# Windows
where start
Manually open the URL displayed in terminal
Check firewall settings for port 8080
Symptoms:
Solutions:
Check if port 8080 is available:
lsof -i :8080 # macOS/Linux
netstat -ano | findstr :8080 # Windows
Ensure no firewall blocking localhost:8080
Try increasing timeout in code (requires rebuild)
Check debug logs:
tail -f ~/.local/share/opencode/log/gitlab-auth.log
Symptoms:
Solutions:
Verify GITLAB_OAUTH_CLIENT_ID is set correctly:
echo $GITLAB_OAUTH_CLIENT_ID
Check OAuth app settings on GitLab:
http://127.0.0.1:8080/callbackEnsure OAuth app is not expired or revoked
Symptoms:
Solutions:
Verify token format:
glpat-Check token scopes:
api scopeVerify token is not expired
Test token manually:
curl -H "Authorization: Bearer glpat-xxx" \
https://gitlab.com/api/v4/user
Symptoms:
Solutions:
Verify instance URL format:
✅ https://gitlab.example.com
❌ https://gitlab.example.com/
❌ gitlab.example.com
Check SSL certificate:
curl -v https://gitlab.example.com/api/v4/version
For self-signed certificates (not recommended):
export NODE_TLS_REJECT_UNAUTHORIZED=0
Ensure instance is accessible:
ping gitlab.example.com
Enable detailed logging by checking the log file:
# View logs in real-time
tail -f ~/.local/share/opencode/log/gitlab-auth.log
# View last 50 lines
tail -n 50 ~/.local/share/opencode/log/gitlab-auth.log
# Search for errors
grep -i error ~/.local/share/opencode/log/gitlab-auth.log
Log entries include:
~/.local/share/opencode/log/gitlab-auth.log# Clone repository
git clone https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-auth.git
cd opencode-gitlab-auth
# Install dependencies
npm install
# Set up Git hooks
npm run prepare
# Build project
npm run build
| Script | Description |
|---|---|
npm run build | Compile TypeScript to JavaScript |
npm run clean | Remove dist/ directory |
npm run rebuild | Clean and build |
npm run lint | Check code style |
npm run lint:fix | Fix code style issues |
npm run format | Format code with Prettier |
npm run format:check | Check code formatting |
npm run prepare | Install Git hooks |
Create feature branch:
git checkout -b feat/your-feature
Make changes and commit:
git add .
git commit -m "feat: add new feature"
Push and create MR:
git push origin feat/your-feature
Follow Conventional Commits:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixdocs: Documentationstyle: Code style (formatting)refactor: Code refactoringperf: Performance improvementtest: Testsbuild: Build systemci: CI/CDchore: MaintenanceExamples:
feat(oauth): add support for custom redirect URIs
fix(server): resolve callback timeout issue
docs: update installation instructions
Currently, testing is manual. To test changes:
# Build
npm run build
# Link locally
npm link
# Test with OpenCode
opencode
# Use /connect command
Test Checklist:
Releases are automated using semantic-release:
main branchVersion bumps:
feat: → Minor version (1.0.0 → 1.1.0)fix: → Patch version (1.0.0 → 1.0.1)feat!: or BREAKING CHANGE: → Major version (1.0.0 → 2.0.0)Contributions are welcome! Please see our Contributing Guide for detailed guidelines on:
Quick Start for Contributors:
Commit Messages: Use conventional commits format
feat(scope): add new feature
fix(scope): fix bug
docs(scope): update documentation
Code Quality: Ensure all checks pass
npm run lint
npm run format:check
npm run build
Testing: Manual testing via npm link and OpenCode integration
A: For best experience
, yes. The bundled client ID has limitations. Register your own app at GitLab Applications.
A: Yes! Enter your instance URL when prompted (e.g., https://gitlab.company.com).
A:
A: In ~/.local/share/opencode/auth.json with 600 permissions (owner only).
A: Currently, only one account per instance is supported. You'll need to re-authenticate to switch accounts.
A: No, authentication requires internet access to GitLab. However, once authenticated, OpenCode may cache some data.
A: Tokens are stored with 600 file permissions and never transmitted except to GitLab's API over HTTPS. However, any process running as your user can access them.
A: Yes, use Personal Access Token authentication. OAuth requires browser interaction.
A: OAuth access tokens expire after 2 hours but are automatically refreshed. PATs last until their configured expiration date.
See CHANGELOG.md for version history and release notes.
MIT License - see LICENSE file for details.
Copyright (c) 2025 OpenCode GitLab Auth Contributors
This project is built for:
Made with ❤️ for the OpenCode community
FAQs
GitLab OAuth authentication plugin for OpenCode
The npm package @gitlab/opencode-gitlab-auth receives a total of 0 weekly downloads. As such, @gitlab/opencode-gitlab-auth popularity was classified as not popular.
We found that @gitlab/opencode-gitlab-auth demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
CVE disclosures hit a record 48,185 in 2025, driven largely by vulnerabilities in third-party WordPress plugins.

Security News
Socket CEO Feross Aboukhadijeh joins Insecure Agents to discuss CVE remediation and why supply chain attacks require a different security approach.

Security News
Tailwind Labs laid off 75% of its engineering team after revenue dropped 80%, as LLMs redirect traffic away from documentation where developers discover paid products.