How to Integrate a Custom Authentication Provider with Palmier Pro

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.

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, the configure() method instantiates the client with the default provider:

// 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:

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 and locate the configure() method around line 165. Replace the default provider instantiation:

// 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 (lines 3-9):

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

Then reference it in the initialization:

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:

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 to replace the default Clerk integration.
  • Optionally centralize provider selection in 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →