# How to Integrate a Custom Authentication Provider with Palmier Pro

> Integrate a custom authentication provider with Palmier Pro by implementing the ConvexAuthProvider protocol. Learn how to inject your implementation into ConvexClientWithAuth for seamless integration.

- Repository: [Palmier/palmier-pro](https://github.com/palmier-io/palmier-pro)
- Tags: how-to-guide
- Published: 2026-06-21

---

**You can integrate a custom authentication provider with Palmier Pro by implementing the `ConvexAuthProvider` protocol from the `convex-swift` package and injecting your implementation into the `ConvexClientWithAuth` initialization inside [`AccountService.swift`](https://github.com/palmier-io/palmier-pro/blob/main/AccountService.swift).**

Palmier Pro uses Convex as its backend to store project data and manage user sessions, delegating authentication to external providers through a clean Swift protocol. To integrate a custom authentication provider with Palmier Pro, you need to conform to the `ConvexAuthProvider` interface and swap the default `ClerkConvexAuthProvider` with your own implementation in the service configuration. This approach allows you to connect any identity system—whether OAuth, Firebase, or corporate SSO—without modifying the core application logic.

## Understanding the Authentication Architecture

Palmier Pro authenticates users through **Convex**, which stores user information, billing details, and project data. The bridge between the UI layer and Convex is the **`ConvexClientWithAuth`** class, which requires an **auth provider** capable of supplying a valid JWT whenever Convex requests it.

Out of the box, Palmier Pro uses the **Clerk** ecosystem. In [`Sources/PalmierPro/Account/AccountService.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Account/AccountService.swift), the `configure()` method instantiates the client with the default provider:

```swift
// AccountService.swift → configure()
convex = ConvexClientWithAuth(
    deploymentUrl: deploymentURL.absoluteString,
    authProvider: ClerkConvexAuthProvider()   // default provider
)

```

To replace this with your own system, you must implement the **`ConvexAuthProvider`** protocol defined in the `convex-swift` package.

## Implementing the ConvexAuthProvider Protocol

The **`ConvexAuthProvider`** protocol exposes a single asynchronous method that returns a fresh authentication token. This method is called automatically whenever Convex needs to refresh its session or validate a request.

### Creating the Custom Provider

Create a new Swift file that conforms to the protocol:

```swift
import ConvexMobile

struct MyCustomAuthProvider: ConvexAuthProvider {
    /// Returns a fresh JWT from your identity service.
    func getAuthToken() async throws -> String {
        let url = URL(string: "https://my-auth.example.com/api/token")!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        let (data, _) = try await URLSession.shared.data(for: request)
        let json = try JSONSerialization.jsonObject(with: data) as! [String: Any]
        
        guard let token = json["jwt"] as? String else {
            throw NSError(domain: "MyCustomAuth", code: 0,
                          userInfo: [NSLocalizedDescriptionKey: "Missing token"])
        }
        return token
    }
}

```

This implementation fetches a token from your backend and returns it as a string. The `convex-swift` package handles caching and refreshing automatically.

## Wiring the Provider into AccountService

Once your provider is defined, you must inject it into the **`ConvexClientWithAuth`** initialization.

### Modifying the Configuration

Navigate to [`Sources/PalmierPro/Account/AccountService.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Account/AccountService.swift) and locate the `configure()` method around line 165. Replace the default provider instantiation:

```swift
// AccountService.swift → configure()
convex = ConvexClientWithAuth(
    deploymentUrl: deploymentURL.absoluteString,
    authProvider: MyCustomAuthProvider()           // your custom provider
)

```

### Optional Configuration via BackendConfig

To keep your provider configurable without hardcoding, extend [`Sources/PalmierPro/Account/BackendConfig.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Account/BackendConfig.swift) (lines 3-9):

```swift
enum BackendConfig {
    // existing keys...
    
    static var customAuthProvider: ConvexAuthProvider {
        MyCustomAuthProvider()
    }
}

```

Then reference it in the initialization:

```swift
convex = ConvexClientWithAuth(
    deploymentUrl: deploymentURL.absoluteString,
    authProvider: BackendConfig.customAuthProvider
)

```

## Activating the Custom Flow in the UI

The UI layer requires no changes to the underlying Convex integration. Once the user authenticates through your custom flow, call `AccountService.shared.startAuthObservation()` to trigger token refresh.

Example implementation for a custom login button:

```swift
Button("Sign in with MyProvider") {
    Task {
        await MyLoginManager.shared.performLogin()
        await AccountService.shared.startAuthObservation()
    }
}

```

The `MyCustomAuthProvider.getAuthToken()` method will be invoked automatically whenever Convex needs a valid token for subsequent requests.

## Summary

- Palmier Pro uses `ConvexClientWithAuth` to manage backend authentication, expecting an object conforming to the `ConvexAuthProvider` protocol.
- Implement the **`getAuthToken()`** method in your custom struct to fetch JWTs from your identity service.
- Inject your provider into **`ConvexClientWithAuth`** inside [`Sources/PalmierPro/Account/AccountService.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Account/AccountService.swift) to replace the default Clerk integration.
- Optionally centralize provider selection in [`Sources/PalmierPro/Account/BackendConfig.swift`](https://github.com/palmier-io/palmier-pro/blob/main/Sources/PalmierPro/Account/BackendConfig.swift) for easier configuration management.
- Trigger authentication observation via `AccountService.shared.startAuthObservation()` after your custom login flow completes.

## Frequently Asked Questions

### Can I use Firebase Authentication or AWS Cognito with Palmier Pro?

Yes. Any identity provider that can issue JWTs or session tokens is compatible. Simply implement the `ConvexAuthProvider` protocol to fetch tokens from your chosen service—whether Firebase, Cognito, Auth0, or a custom OAuth server—and return them as strings from `getAuthToken()`.

### Do I need to modify the Convex backend configuration to accept custom providers?

Generally, no. As long as your Convex deployment is configured to validate the JWTs issued by your custom provider (using the appropriate issuer and audience settings), the Palmier Pro client side changes are sufficient. Ensure your Convex backend trusts the signing keys from your identity provider.

### How does token refresh work with a custom provider?

The `ConvexClientWithAuth` class automatically calls your provider's `getAuthToken()` method whenever the current token nears expiration or when a request returns an authentication error. Your implementation should handle token caching internally or fetch a fresh token from your backend each time, depending on your security requirements.

### Can I maintain multiple authentication providers simultaneously?

While `ConvexClientWithAuth` accepts only one provider at initialization, you can create a composite provider that implements the `ConvexAuthProvider` protocol and delegates to different underlying services based on user preference or configuration. Return the appropriate token from `getAuthToken()` based on the user's selected authentication method.