# How to Add a New OAuth-Based Provider Using OmniRoute's resolvePublicCred() Pattern

> Learn to add new OAuth providers with OmniRoute's resolvePublicCred() pattern. Securely embed credentials and override with env variables for flexible provider registration.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-07-19

---

**OmniRoute's `resolvePublicCred()` utility allows developers to embed default OAuth credentials directly in the codebase while maintaining the ability to override them via environment variables, ensuring new providers can be registered securely in [`src/lib/oauth/constants/oauth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/constants/oauth.ts) and exposed through the provider registry.**

Adding a new OAuth-based provider to the OmniRoute repository (diegosouzapw/OmniRoute) requires following a specific credential resolution pattern to maintain security compliance. The `resolvePublicCred()` function, defined in the Open-SSE utilities, provides a fallback mechanism that checks for environment variables before using hard-coded defaults, as mandated by Hard Rule #11 and the project's security documentation.

## Understanding the resolvePublicCred() Security Pattern

The `resolvePublicCred()` function is the central mechanism for handling public OAuth credentials in OmniRoute. Located in [`open-sse/utils/publicCreds.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/utils/publicCreds.ts) at line 213, this utility first checks for the presence of a specified environment variable, and if absent, returns a hard-coded default value that ships with the repository. This pattern ensures that the application works out-of-the-box for development while allowing production deployments to inject secure credentials via environment variables, as detailed in [`docs/security/PUBLIC_CREDS.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/docs/security/PUBLIC_CREDS.md).

## Step-by-Step Implementation Guide

### 1. Register the Provider Configuration in oauth.ts

Begin by defining a static configuration object in [`src/lib/oauth/constants/oauth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/constants/oauth.ts) that contains the OAuth endpoints, scopes, and credential resolutions. Each provider requires an exported constant (e.g., `MYPROVIDER_CONFIG`) that uses `resolvePublicCred()` to define the `clientId` and `clientSecret` fields.

```typescript
export const MYPROVIDER_CONFIG = {
  authorizeUrl: "https://auth.myprovider.com/oauth/authorize",
  tokenUrl: "https://auth.myprovider.com/oauth/token",
  scopes: ["openid", "profile", "email"],
  clientId: resolvePublicCred("myprovider_id", "MYPROVIDER_OAUTH_CLIENT_ID"),
  clientSecret: resolvePublicCred("myprovider_secret", "MYPROVIDER_OAUTH_CLIENT_SECRET"),
  redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/callback`,
};

```

### 2. Create the Provider Module

Create a new file at [`src/lib/oauth/providers/myprovider.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/providers/myprovider.ts) that imports the configuration and exports a provider descriptor compatible with the OAuth service layer. This module defines the provider's metadata and links it to the configuration constant.

```typescript
import { Provider } from "./types";
import { MYPROVIDER_CONFIG } from "../constants/oauth";

export const myprovider: Provider = {
  id: "myprovider",
  name: "MyProvider",
  type: "oauth",
  config: MYPROVIDER_CONFIG,
};

```

### 3. Export from the Registry Index

Expose the new provider by adding an export statement to [`src/lib/oauth/providers/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/providers/index.ts), which serves as the barrel file for the OAuth registry. This allows the service layer to discover the provider automatically.

```typescript
export * from "./myprovider";
export * from "./other-providers";

```

### 4. Verify Service Layer Integration

The generic OAuth handling logic in [`src/lib/oauth/providers.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/providers.ts) automatically discovers providers through the registry index and manages auth URL generation, token exchange, and refresh scheduling. No modifications are required unless the provider implements a non-standard OAuth flow, in which case custom logic should be added within the specific provider file.

### 5. Add Tests and Update Documentation

Create unit tests following the pattern established in [`tests/unit/zed-oauth-provider.test.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/tests/unit/zed-oauth-provider.test.ts) to verify that `resolvePublicCred()` returns the expected format and that the configuration object resolves correctly. Additionally, update [`docs/reference/PROVIDER_REFERENCE.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/docs/reference/PROVIDER_REFERENCE.md) to include the new provider in the OAuth providers table.

```typescript
import { resolvePublicCred } from "../../open-sse/utils/publicCreds";
import { MYPROVIDER_CONFIG } from "../../src/lib/oauth/constants/oauth";

test("myprovider config resolves public cred", () => {
  const clientId = resolvePublicCred("myprovider_id", "MYPROVIDER_OAUTH_CLIENT_ID");
  expect(MYPROVIDER_CONFIG.clientId).toBe(clientId);
});

```

## Key Files Reference

- **[`open-sse/utils/publicCreds.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/open-sse/utils/publicCreds.ts)**: Defines `resolvePublicCred()` (line 213) and `resolvePublicCredMulti()` for credential resolution.
- **[`src/lib/oauth/constants/oauth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/constants/oauth.ts)**: Contains provider-specific constants using the `resolvePublicCred()` pattern.
- **[`src/lib/oauth/providers/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/providers/index.ts)**: Barrel file that exports all provider modules for registry discovery.
- **[`src/lib/oauth/providers.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/providers.ts)**: Core service layer that consumes the registry and manages OAuth flows.
- **[`docs/security/PUBLIC_CREDS.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/docs/security/PUBLIC_CREDS.md)**: Security guidelines explaining the public credential pattern.
- **[`docs/reference/PROVIDER_REFERENCE.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/docs/reference/PROVIDER_REFERENCE.md)**: User-facing documentation listing available providers.

## Summary

- Define provider constants in [`src/lib/oauth/constants/oauth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/constants/oauth.ts) using `resolvePublicCred()` for all public credentials.
- Create individual provider modules in `src/lib/oauth/providers/` and export them through [`index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/index.ts).
- The service layer in [`src/lib/oauth/providers.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/providers.ts) automatically handles discovery and OAuth flow management.
- Environment variables take precedence over hard-coded defaults due to the `resolvePublicCred()` fallback logic.
- Always update unit tests and provider reference documentation when adding new OAuth integrations.

## Frequently Asked Questions

### What is the purpose of resolvePublicCred() in OmniRoute?

The `resolvePublicCred()` function ensures that public OAuth credentials can be embedded in the repository for development convenience while allowing secure override through environment variables in production. It checks the specified environment variable first, then falls back to a hard-coded default, maintaining compliance with the project's Hard Rule #11 security requirement.

### Where should I store the default OAuth client credentials?

Default credentials must be stored within the `resolvePublicCred()` function calls inside [`src/lib/oauth/constants/oauth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/constants/oauth.ts). Never hard-code secrets directly into provider objects; always wrap them using `resolvePublicCred("key", "ENV_VAR_NAME")` to ensure they follow the security pattern defined in [`docs/security/PUBLIC_CREDS.md`](https://github.com/diegosouzapw/OmniRoute/blob/main/docs/security/PUBLIC_CREDS.md).

### Do I need to modify the OAuth service layer for every new provider?

No. The service layer in [`src/lib/oauth/providers.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/providers.ts) automatically discovers new providers through the barrel export in [`src/lib/oauth/providers/index.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/oauth/providers/index.ts). You only need to modify the service layer if the provider requires a custom authentication flow that deviates from standard OAuth 2.0 specifications.

### How do I override the default credentials in production?

Set the corresponding environment variables defined in the second parameter of `resolvePublicCred()` (e.g., `MYPROVIDER_OAUTH_CLIENT_ID`). The utility function checks for these environment variables at runtime before falling back to the embedded defaults, allowing secure credential injection without code changes.