# How to Configure OIDC Authentication with frp for Single Sign-On

> Secure your frp connections with OIDC authentication for seamless single sign-on. Configure both client and server with your IdP details and audience settings.

- Repository: [fatedier/frp](https://github.com/fatedier/frp)
- Tags: how-to-guide
- Published: 2026-02-26

---

**To configure OIDC authentication with frp, set `auth.method = oidc` in both the client (`frpc`) and server (`frps`) configurations, populate the `[auth.oidc]` section with your identity provider endpoints and credentials, and ensure the audience values match between both sides.**

The frp (Fast Reverse Proxy) project supports OpenID Connect (OIDC) to enable single sign-on (SSO) for secure tunnel authentication. When you configure OIDC authentication with frp, you replace static privilege tokens with short-lived JWTs issued by any OIDC-compliant identity provider, centralizing access control and improving security posture over long-lived credentials.

## How OIDC Authentication Works in frp

The implementation in [`pkg/auth/oidc.go`](https://github.com/fatedier/frp/blob/main/pkg/auth/oidc.go) establishes a token-based flow where the client obtains a JWT from your IdP and the server validates it on every connection.

### The Authentication Flow

1. **Token Generation**: The `frpc` client reads `AuthOIDCClientConfig` from its configuration and creates an `oauth2/clientcredentials.Config`. The `NewOidcAuthSetter` function in [`pkg/auth/oidc.go`](https://github.com/fatedier/frp/blob/main/pkg/auth/oidc.go) (lines 84-100) calls `generateAccessToken` to fetch a JWT from the IdP's token endpoint.

2. **Token Attachment**: The client attaches the JWT to the `PrivilegeKey` field of `Login`, `Ping`, and `NewWorkConn` messages via `SetLogin`, `SetPing`, and `SetNewWorkConn` methods in the same file.

3. **Token Verification**: The `frps` server uses `AuthOIDCServerConfig` to create a `TokenVerifier` via `NewTokenVerifier` (lines 211-222 in [`pkg/auth/oidc.go`](https://github.com/fatedier/frp/blob/main/pkg/auth/oidc.go)). This uses the `go-oidc` library to validate the issuer, audience, and signature against the IdP's JWKS endpoint.

4. **Session Management**: Upon successful verification, the token's subject is stored and reused for subsequent `Ping` and `NewWorkConn` verification via `verifyPostLoginToken`, ensuring continuous authentication without re-fetching tokens.

## Server Configuration (frps)

Configure the `frps` server to validate OIDC tokens by setting `auth.method = oidc` and defining the `[auth.oidc]` section.

```toml

# frps.ini

[common]
bindPort = 7000

[auth]
method = "oidc"
additionalScopes = ["HeartBeats", "NewWorkConns"]

[auth.oidc]
issuer = "https://accounts.google.com"
audience = "my-frp-client-id"
skipExpiryCheck = false
skipIssuerCheck = false

```

The server unmarshals this into `AuthOIDCServerConfig` defined in [`pkg/config/v1/server.go`](https://github.com/fatedier/frp/blob/main/pkg/config/v1/server.go) (lines 28-45). Validation logic in [`pkg/config/v1/validation/server.go`](https://github.com/fatedier/frp/blob/main/pkg/config/v1/validation/server.go) ensures that OIDC parameters are mutually exclusive with other authentication methods.

## Client Configuration (frpc)

The `frpc` client must obtain tokens from your IdP using the client credentials flow.

```toml

# frpc.ini

[common]
serverAddr = "my-frp.example.com"
serverPort = 7000

[auth]
method = "oidc"
additionalScopes = ["HeartBeats"]

[auth.oidc]
clientID = "my-frp-client-id"
clientSecret = "MY_CLIENT_SECRET"
audience = "my-frp-client-id"
scope = "openid profile email"
tokenEndpointURL = "https://oauth2.googleapis.com/token"

# Optional: TLS and proxy settings for token requests

trustedCaFile = "/etc/ssl/certs/ca-certificates.crt"
insecureSkipVerify = false
proxyURL = "http://proxy:3128"

```

This configuration maps to `AuthOIDCClientConfig` in [`pkg/config/v1/client.go`](https://github.com/fatedier/frp/blob/main/pkg/config/v1/client.go) (lines 196-236). The `createOIDCHTTPClient` function in [`pkg/auth/oidc.go`](https://github.com/fatedier/frp/blob/main/pkg/auth/oidc.go) (lines 35-73) handles custom TLS and proxy settings for the token endpoint connection. Validation in [`pkg/config/v1/validation/client.go`](https://github.com/fatedier/frp/blob/main/pkg/config/v1/validation/client.go) (lines 88-104) checks for configuration conflicts.

## Programmatic Implementation

If embedding frp as a library, you can instantiate the OIDC authenticator directly:

```go
import (
    "github.com/fatedier/frp/pkg/auth"
    v1 "github.com/fatedier/frp/pkg/config/v1"
    "github.com/fatedier/frp/pkg/msg"
)

// Client-side token generation
clientCfg := v1.AuthOIDCClientConfig{
    ClientID:         "my-frp-client-id",
    ClientSecret:     "MY_CLIENT_SECRET",
    TokenEndpointURL: "https://oauth2.googleapis.com/token",
    Scope:            "openid profile email",
    Audience:         "my-frp-client-id",
}

setter, err := auth.NewOidcAuthSetter([]v1.AuthScope{v1.AuthScopeHeartBeats}, clientCfg)
if err != nil {
    panic(err)
}

login := &msg.Login{}
if err := setter.SetLogin(login); err != nil {
    panic(err)
}
// login.PrivilegeKey now contains the JWT

// Server-side token verification
serverCfg := v1.AuthOIDCServerConfig{
    Issuer:   "https://accounts.google.com",
    Audience: "my-frp-client-id",
}

verifier := auth.NewTokenVerifier(serverCfg)
consumer := auth.NewOidcAuthVerifier(nil, verifier)

if err := consumer.VerifyLogin(login); err != nil {
    // Reject connection: invalid token
}

```

This mirrors the internal implementation used by [`cmd/frpc/main.go`](https://github.com/fatedier/frp/blob/main/cmd/frpc/main.go) and [`cmd/frps/main.go`](https://github.com/fatedier/frp/blob/main/cmd/frps/main.go).

## Key Source Files

| File | Purpose |
|------|---------|
| [`pkg/auth/oidc.go`](https://github.com/fatedier/frp/blob/main/pkg/auth/oidc.go) | Core OIDC logic: `NewOidcAuthSetter`, `generateAccessToken`, `NewTokenVerifier`, and `OidcAuthConsumer` |
| [`pkg/config/v1/server.go`](https://github.com/fatedier/frp/blob/main/pkg/config/v1/server.go) | `AuthOIDCServerConfig` struct definition (lines 28-45) |
| [`pkg/config/v1/client.go`](https://github.com/fatedier/frp/blob/main/pkg/config/v1/client.go) | `AuthOIDCClientConfig` struct definition (lines 196-236) |
| [`pkg/config/v1/validation/server.go`](https://github.com/fatedier/frp/blob/main/pkg/config/v1/validation/server.go) | Server-side OIDC configuration validation |
| [`pkg/config/v1/validation/client.go`](https://github.com/fatedier/frp/blob/main/pkg/config/v1/validation/client.go) | Client-side OIDC validation (lines 88-104) |
| [`cmd/frps/main.go`](https://github.com/fatedier/frp/blob/main/cmd/frps/main.go) | Server entry point |
| [`cmd/frpc/main.go`](https://github.com/fatedier/frp/blob/main/cmd/frpc/main.go) | Client entry point |

## Summary

- **Configure OIDC authentication with frp** by setting `auth.method = oidc` in both `frpc` and `frps` configurations.
- The **client** (`frpc`) uses `AuthOIDCClientConfig` to fetch JWTs from your IdP via the token endpoint defined in [`pkg/auth/oidc.go`](https://github.com/fatedier/frp/blob/main/pkg/auth/oidc.go).
- The **server** (`frps`) uses `AuthOIDCServerConfig` to validate tokens against the issuer and audience using `NewTokenVerifier`.
- Ensure **audience values match** between client and server, or omit the audience check on the server for testing.
- Configure optional **TLS** or **proxy settings** in the client for corporate environments using `trustedCaFile` or `proxyURL`.
- Validation logic in `pkg/config/v1/validation/` prevents configuration conflicts before startup.

## Frequently Asked Questions

### What identity providers work with frp OIDC authentication?

Any OIDC-compliant identity provider works with frp, including Google Workspace, Azure Active Directory, Keycloak, Okta, Auth0, and AWS Cognito. The `issuer` URL in [`frps.ini`](https://github.com/fatedier/frp/blob/main/frps.ini) must match the IdP's discovery document endpoint, and the `tokenEndpointURL` in [`frpc.ini`](https://github.com/fatedier/frp/blob/main/frpc.ini) must point to the provider's OAuth2 token endpoint.

### How do I troubleshoot OIDC token validation failures in frps?

Check the `frps` logs for verification errors from `NewTokenVerifier` in [`pkg/auth/oidc.go`](https://github.com/fatedier/frp/blob/main/pkg/auth/oidc.go). Common issues include clock skew between the server and IdP (enable `skipExpiryCheck` temporarily to test), mismatched `audience` values between client and server, or incorrect `issuer` URLs. Ensure the IdP's JWKS endpoint is reachable from the frps host for signature verification.

### Can I use OIDC authentication with frp's built-in dashboard?

Yes, OIDC authentication applies to the control plane connection between `frpc` and `frps`, which secures the tunnel establishment. However, the frp dashboard (if enabled) uses separate authentication mechanisms. You should run the dashboard behind a reverse proxy that handles OIDC authentication for web access, while using the native OIDC support for client-server tunnel authentication.

### Is OIDC more secure than static token authentication in frp?

Yes, OIDC is significantly more secure than static token authentication because tokens are short-lived and automatically rotated. The `generateAccessToken` function in [`pkg/auth/oidc.go`](https://github.com/fatedier/frp/blob/main/pkg/auth/oidc.go) obtains tokens with limited lifetime from your IdP, whereas static tokens remain valid until manually revoked. Additionally, OIDC enables centralized authentication policy enforcement through your identity provider, supporting multi-factor authentication and conditional access policies.