Skip to content

Commit a785ab4

Browse files
example: add prisma adapter (#1213)
1 parent 2a9890c commit a785ab4

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* A simple fully typed adapter for oidc-provider that uses Prisma, you can
3+
* find more information about the adapter with an expressjs example here:
4+
* https://github.com/Mostafatalaat770/node-oidc-provider-prisma-adapter
5+
*
6+
*
7+
* In case of questions, you can contact me on:
8+
* - GitHub: https://github.com/Mostafatalaat770
9+
* - LinkedIn: https://linkedin.com/in/mostafatalaat770/
10+
* - Email: [email protected]
11+
*
12+
*
13+
* pnpm add @prisma/client || npm i @prisma/client || yarn add @prisma/client
14+
*/
15+
16+
import { PrismaClient, OidcModel, Prisma } from "@prisma/client";
17+
import { Adapter, AdapterPayload } from "oidc-provider";
18+
19+
const prisma = new PrismaClient();
20+
21+
const types = [
22+
"OidcModels",
23+
"AccessToken",
24+
"AuthorizationCode",
25+
"RefreshToken",
26+
"DeviceCode",
27+
"ClientCredentials",
28+
"Client",
29+
"InitialAccessToken",
30+
"RegistrationAccessToken",
31+
"Interaction",
32+
"ReplayDetection",
33+
"PushedAuthorizationRequest",
34+
"Grant",
35+
"BackchannelAuthenticationRequest",
36+
].reduce(
37+
(map, name, i) => ({ ...map, [name]: i + 1 }),
38+
{} as Record<string, number>
39+
);
40+
41+
const prepare = (doc: OidcModel) => {
42+
const isPayloadJson =
43+
doc.payload &&
44+
typeof doc.payload === "object" &&
45+
!Array.isArray(doc.payload);
46+
47+
const payload = isPayloadJson ? (doc.payload as Prisma.JsonObject) : {};
48+
49+
return {
50+
...payload,
51+
...(doc.consumedAt ? { consumed: true } : undefined),
52+
};
53+
};
54+
55+
const expiresAt = (expiresIn?: number) =>
56+
expiresIn ? new Date(Date.now() + expiresIn * 1000) : null;
57+
58+
export class PrismaAdapter implements Adapter {
59+
type: number;
60+
61+
constructor(name: string) {
62+
this.type = types[name];
63+
}
64+
65+
async upsert(
66+
id: string,
67+
payload: AdapterPayload,
68+
expiresIn?: number
69+
): Promise<void> {
70+
const data = {
71+
type: this.type,
72+
payload: payload as Prisma.JsonObject,
73+
grantId: payload.grantId,
74+
userCode: payload.userCode,
75+
uid: payload.uid,
76+
expiresAt: expiresAt(expiresIn),
77+
};
78+
79+
await prisma.oidcModel.upsert({
80+
where: {
81+
id_type: {
82+
id,
83+
type: this.type,
84+
},
85+
},
86+
update: {
87+
...data,
88+
},
89+
create: {
90+
id,
91+
...data,
92+
},
93+
});
94+
}
95+
96+
async find(id: string): Promise<AdapterPayload | undefined> {
97+
const doc = await prisma.oidcModel.findUnique({
98+
where: {
99+
id_type: {
100+
id,
101+
type: this.type,
102+
},
103+
},
104+
});
105+
106+
if (!doc || (doc.expiresAt && doc.expiresAt < new Date())) {
107+
return undefined;
108+
}
109+
110+
return prepare(doc);
111+
}
112+
113+
async findByUserCode(userCode: string): Promise<AdapterPayload | undefined> {
114+
const doc = await prisma.oidcModel.findFirst({
115+
where: {
116+
userCode,
117+
},
118+
});
119+
120+
if (!doc || (doc.expiresAt && doc.expiresAt < new Date())) {
121+
return undefined;
122+
}
123+
124+
return prepare(doc);
125+
}
126+
127+
async findByUid(uid: string): Promise<AdapterPayload | undefined> {
128+
const doc = await prisma.oidcModel.findUnique({
129+
where: {
130+
uid,
131+
},
132+
});
133+
134+
if (!doc || (doc.expiresAt && doc.expiresAt < new Date())) {
135+
return undefined;
136+
}
137+
138+
return prepare(doc);
139+
}
140+
141+
async consume(id: string): Promise<void> {
142+
await prisma.oidcModel.update({
143+
where: {
144+
id_type: {
145+
id,
146+
type: this.type,
147+
},
148+
},
149+
data: {
150+
consumedAt: new Date(),
151+
},
152+
});
153+
}
154+
155+
async destroy(id: string): Promise<void> {
156+
await prisma.oidcModel.delete({
157+
where: {
158+
id_type: {
159+
id,
160+
type: this.type,
161+
},
162+
},
163+
});
164+
}
165+
166+
async revokeByGrantId(grantId: string): Promise<void> {
167+
await prisma.oidcModel.deleteMany({
168+
where: {
169+
grantId,
170+
},
171+
});
172+
}
173+
}

0 commit comments

Comments
 (0)