refactor(polar): read the token through the shared OAuth lifecycle

This commit is contained in:
Marc-André Bombeck committed 2026-10-21 19:13:36 +02:00
1 parent a12174bcaa
commit f9ed07551f
2 files changed
+40 -9

No files matched your search

+9 -9
View File
@@ -11,7 +11,9 @@
*/
import { prisma } from "@/lib/db";
import { decrypt, encrypt } from "@/lib/crypto";
import { obtainAccessToken } from "@/lib/integrations/oauth-kit/token";
import { getPolarCredentials, type PolarCredentials } from "./client";
import { polarTokenDescriptor } from "./oauth-descriptor";
/**
* Resolve the user's Polar OAuth client id/secret, DB-first then env.
@@ -80,24 +82,22 @@ export interface PolarConnection {
}
/**
* Fetch + decrypt the user's stored Polar token. Returns null when the user has
* Fetch + decrypt the user's stored Polar token, read through the shared OAuth
* token lifecycle like every other provider's. Returns null when the user has
* not connected Polar (no access token) or the member id is missing.
*/
export async function getPolarConnection(
userId: string,
): Promise<PolarConnection | null> {
const grant = await obtainAccessToken(polarTokenDescriptor, userId);
if (grant.kind !== "token") return null;
const user = await prisma.user.findUnique({
where: { id: userId },
select: {
polarAccessTokenEncrypted: true,
polarUserIdEncrypted: true,
},
select: { polarUserIdEncrypted: true },
});
if (!user?.polarAccessTokenEncrypted || !user?.polarUserIdEncrypted) {
return null;
}
if (!user?.polarUserIdEncrypted) return null;
return {
accessToken: decrypt(user.polarAccessTokenEncrypted),
accessToken: grant.accessToken,
polarUserId: decrypt(user.polarUserIdEncrypted),
};
}
+31
View File
@@ -0,0 +1,31 @@
/**
* Where a Polar grant lives, for the shared token lifecycle
* (`src/lib/integrations/oauth-kit/token.ts`).
*
* Polar AccessLink tokens do not expire and come without a refresh token, so
* the kit only reads them: there is nothing to refresh and nothing to write
* back. A revoked grant surfaces as a refused read, and the person reconnects.
*/
import type { OAuthTokenDescriptor } from "@/lib/integrations/oauth-kit/token";
export const polarTokenDescriptor: OAuthTokenDescriptor<never> = {
provider: "polar",
tracksExpiry: false,
expiryBufferMs: 0,
async readGrant(db, userId) {
const row = await db.user.findUnique({
where: { id: userId },
select: { polarAccessTokenEncrypted: true },
});
if (!row?.polarAccessTokenEncrypted) return null;
return {
accessCiphertext: row.polarAccessTokenEncrypted,
refreshCiphertext: null,
expiresAt: null,
};
},
// Never reached: a grant without a refresh token is never refreshed.
writeGrant: async () => 0,
loadCredentials: async () => null,
refresh: null,
};