Skip to content

Commit 3d580bb

Browse files
committed
fix: accept active signing keys for oidc logout
1 parent 9800e80 commit 3d580bb

File tree

2 files changed

+48
-25
lines changed

2 files changed

+48
-25
lines changed

server/lib/oauth/keys.ts

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@ function getEncryptionKey(): string {
1515
return key;
1616
}
1717

18-
export async function ensureSigningKey(): Promise<void> {
19-
const [existingKey] = await db
18+
async function selectActiveSigningKeys() {
19+
return db
2020
.select()
2121
.from(oauthSigningKeys)
2222
.where(eq(oauthSigningKeys.active, true))
23-
.orderBy(desc(oauthSigningKeys.createdAt))
24-
.limit(1);
23+
.orderBy(desc(oauthSigningKeys.createdAt));
24+
}
25+
26+
export async function ensureSigningKey(): Promise<void> {
27+
const [existingKey] = await selectActiveSigningKeys();
2528

2629
if (existingKey) {
2730
return;
@@ -57,12 +60,7 @@ export async function getActiveSigningKey(): Promise<{
5760
publicKeyPem: string;
5861
privateKeyPem: string;
5962
}> {
60-
const [activeKey] = await db
61-
.select()
62-
.from(oauthSigningKeys)
63-
.where(eq(oauthSigningKeys.active, true))
64-
.orderBy(desc(oauthSigningKeys.createdAt))
65-
.limit(1);
63+
const [activeKey] = await selectActiveSigningKeys();
6664

6765
if (!activeKey) {
6866
throw new Error("No active OAuth signing key found");
@@ -76,12 +74,24 @@ export async function getActiveSigningKey(): Promise<{
7674
};
7775
}
7876

77+
export async function getActiveSigningPublicKeys(): Promise<
78+
{
79+
keyId: string;
80+
algorithm: string;
81+
publicKeyPem: string;
82+
}[]
83+
> {
84+
const activeKeys = await selectActiveSigningKeys();
85+
86+
return activeKeys.map((key) => ({
87+
keyId: key.keyId,
88+
algorithm: key.algorithm,
89+
publicKeyPem: key.publicKeyPem
90+
}));
91+
}
92+
7993
export async function getJWKS(): Promise<JsonWebKey[]> {
80-
const activeKeys = await db
81-
.select()
82-
.from(oauthSigningKeys)
83-
.where(eq(oauthSigningKeys.active, true))
84-
.orderBy(desc(oauthSigningKeys.createdAt));
94+
const activeKeys = await selectActiveSigningKeys();
8595

8696
return activeKeys.map((key) => {
8797
const exported = createPublicKey(key.publicKeyPem).export({

server/routers/oauth/endSession.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
oauthClients,
99
oauthRefreshTokens
1010
} from "@server/db";
11-
import { getActiveSigningKey } from "@server/lib/oauth/keys";
11+
import { getActiveSigningPublicKeys } from "@server/lib/oauth/keys";
1212
import { getIssuerUrl } from "@server/lib/oauth/issuer";
1313
import {
1414
createBlankSessionTokenCookie,
@@ -40,16 +40,29 @@ export async function handleEndSession(
4040

4141
if (idTokenHint) {
4242
try {
43-
const signingKey = await getActiveSigningKey();
44-
const decoded = jsonwebtoken.verify(
45-
idTokenHint,
46-
signingKey.publicKeyPem,
47-
{
48-
algorithms: ["RS256"],
49-
issuer: getIssuerUrl(),
50-
ignoreExpiration: true
43+
const signingKeys = await getActiveSigningPublicKeys();
44+
let decoded: string | jsonwebtoken.JwtPayload | undefined;
45+
46+
for (const signingKey of signingKeys) {
47+
try {
48+
decoded = jsonwebtoken.verify(
49+
idTokenHint,
50+
signingKey.publicKeyPem,
51+
{
52+
algorithms: ["RS256"],
53+
issuer: getIssuerUrl(),
54+
ignoreExpiration: true
55+
}
56+
);
57+
break;
58+
} catch {
59+
continue;
5160
}
52-
);
61+
}
62+
63+
if (!decoded) {
64+
throw new Error("Invalid id_token_hint");
65+
}
5366

5467
if (
5568
typeof decoded === "object" &&

0 commit comments

Comments
 (0)