Skip to content

Commit 2b783fa

Browse files
committed
mcpoauth => oauth
1 parent 4d6a7df commit 2b783fa

File tree

11 files changed

+661
-556
lines changed

11 files changed

+661
-556
lines changed

src/auth/oauthClient.server.ts

Lines changed: 447 additions & 0 deletions
Large diffs are not rendered by default.

src/db/schema.ts

Lines changed: 66 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,11 +1075,12 @@ export const mcpApiKeysRelations = relations(mcpApiKeys, ({ one }) => ({
10751075
}))
10761076

10771077
// ============================================================================
1078-
// OAuth MCP Tables
1078+
// OAuth Client Authorization Tables
10791079
// ============================================================================
10801080

1081-
// OAuth MCP Authorization Codes (short-lived, 10 min)
1082-
export const oauthMcpAuthorizationCodes = pgTable(
1081+
// OAuth Authorization Codes (short-lived, 10 min)
1082+
// Note: Uses existing oauth_mcp_* tables for backwards compatibility
1083+
export const oauthAuthorizationCodes = pgTable(
10831084
'oauth_mcp_authorization_codes',
10841085
{
10851086
id: uuid('id').primaryKey().defaultRandom(),
@@ -1093,7 +1094,7 @@ export const oauthMcpAuthorizationCodes = pgTable(
10931094
codeChallengeMethod: varchar('code_challenge_method', { length: 8 })
10941095
.notNull()
10951096
.default('S256'),
1096-
scope: text('scope').notNull().default('mcp'),
1097+
scope: text('scope').notNull().default('api'),
10971098
expiresAt: timestamp('expires_at', {
10981099
withTimezone: true,
10991100
mode: 'date',
@@ -1108,15 +1109,23 @@ export const oauthMcpAuthorizationCodes = pgTable(
11081109
}),
11091110
)
11101111

1111-
export type OAuthMcpAuthorizationCode = InferSelectModel<
1112-
typeof oauthMcpAuthorizationCodes
1112+
export type OAuthAuthorizationCode = InferSelectModel<
1113+
typeof oauthAuthorizationCodes
11131114
>
1114-
export type NewOAuthMcpAuthorizationCode = InferInsertModel<
1115-
typeof oauthMcpAuthorizationCodes
1115+
export type NewOAuthAuthorizationCode = InferInsertModel<
1116+
typeof oauthAuthorizationCodes
11161117
>
11171118

1118-
// OAuth MCP Access Tokens (1 hour TTL)
1119-
export const oauthMcpAccessTokens = pgTable(
1119+
// Backwards compatibility aliases
1120+
/** @deprecated Use oauthAuthorizationCodes instead */
1121+
export const oauthMcpAuthorizationCodes = oauthAuthorizationCodes
1122+
/** @deprecated Use OAuthAuthorizationCode instead */
1123+
export type OAuthMcpAuthorizationCode = OAuthAuthorizationCode
1124+
/** @deprecated Use NewOAuthAuthorizationCode instead */
1125+
export type NewOAuthMcpAuthorizationCode = NewOAuthAuthorizationCode
1126+
1127+
// OAuth Access Tokens (1 hour TTL)
1128+
export const oauthAccessTokens = pgTable(
11201129
'oauth_mcp_access_tokens',
11211130
{
11221131
id: uuid('id').primaryKey().defaultRandom(),
@@ -1125,7 +1134,7 @@ export const oauthMcpAccessTokens = pgTable(
11251134
.notNull()
11261135
.references(() => users.id, { onDelete: 'cascade' }),
11271136
clientId: varchar('client_id', { length: 255 }).notNull(),
1128-
scope: text('scope').notNull().default('mcp'),
1137+
scope: text('scope').notNull().default('api'),
11291138
expiresAt: timestamp('expires_at', {
11301139
withTimezone: true,
11311140
mode: 'date',
@@ -1144,13 +1153,19 @@ export const oauthMcpAccessTokens = pgTable(
11441153
}),
11451154
)
11461155

1147-
export type OAuthMcpAccessToken = InferSelectModel<typeof oauthMcpAccessTokens>
1148-
export type NewOAuthMcpAccessToken = InferInsertModel<
1149-
typeof oauthMcpAccessTokens
1150-
>
1156+
export type OAuthAccessToken = InferSelectModel<typeof oauthAccessTokens>
1157+
export type NewOAuthAccessToken = InferInsertModel<typeof oauthAccessTokens>
11511158

1152-
// OAuth MCP Refresh Tokens (30 day TTL)
1153-
export const oauthMcpRefreshTokens = pgTable(
1159+
// Backwards compatibility aliases
1160+
/** @deprecated Use oauthAccessTokens instead */
1161+
export const oauthMcpAccessTokens = oauthAccessTokens
1162+
/** @deprecated Use OAuthAccessToken instead */
1163+
export type OAuthMcpAccessToken = OAuthAccessToken
1164+
/** @deprecated Use NewOAuthAccessToken instead */
1165+
export type NewOAuthMcpAccessToken = NewOAuthAccessToken
1166+
1167+
// OAuth Refresh Tokens (30 day TTL)
1168+
export const oauthRefreshTokens = pgTable(
11541169
'oauth_mcp_refresh_tokens',
11551170
{
11561171
id: uuid('id').primaryKey().defaultRandom(),
@@ -1160,7 +1175,7 @@ export const oauthMcpRefreshTokens = pgTable(
11601175
.references(() => users.id, { onDelete: 'cascade' }),
11611176
clientId: varchar('client_id', { length: 255 }).notNull(),
11621177
accessTokenId: uuid('access_token_id').references(
1163-
() => oauthMcpAccessTokens.id,
1178+
() => oauthAccessTokens.id,
11641179
{ onDelete: 'set null' },
11651180
),
11661181
expiresAt: timestamp('expires_at', {
@@ -1179,45 +1194,58 @@ export const oauthMcpRefreshTokens = pgTable(
11791194
}),
11801195
)
11811196

1182-
export type OAuthMcpRefreshToken = InferSelectModel<
1183-
typeof oauthMcpRefreshTokens
1184-
>
1185-
export type NewOAuthMcpRefreshToken = InferInsertModel<
1186-
typeof oauthMcpRefreshTokens
1187-
>
1197+
export type OAuthRefreshToken = InferSelectModel<typeof oauthRefreshTokens>
1198+
export type NewOAuthRefreshToken = InferInsertModel<typeof oauthRefreshTokens>
1199+
1200+
// Backwards compatibility aliases
1201+
/** @deprecated Use oauthRefreshTokens instead */
1202+
export const oauthMcpRefreshTokens = oauthRefreshTokens
1203+
/** @deprecated Use OAuthRefreshToken instead */
1204+
export type OAuthMcpRefreshToken = OAuthRefreshToken
1205+
/** @deprecated Use NewOAuthRefreshToken instead */
1206+
export type NewOAuthMcpRefreshToken = NewOAuthRefreshToken
11881207

1189-
// OAuth MCP relations
1190-
export const oauthMcpAuthorizationCodesRelations = relations(
1191-
oauthMcpAuthorizationCodes,
1208+
// OAuth relations
1209+
export const oauthAuthorizationCodesRelations = relations(
1210+
oauthAuthorizationCodes,
11921211
({ one }) => ({
11931212
user: one(users, {
1194-
fields: [oauthMcpAuthorizationCodes.userId],
1213+
fields: [oauthAuthorizationCodes.userId],
11951214
references: [users.id],
11961215
}),
11971216
}),
11981217
)
11991218

1200-
export const oauthMcpAccessTokensRelations = relations(
1201-
oauthMcpAccessTokens,
1219+
export const oauthAccessTokensRelations = relations(
1220+
oauthAccessTokens,
12021221
({ one, many }) => ({
12031222
user: one(users, {
1204-
fields: [oauthMcpAccessTokens.userId],
1223+
fields: [oauthAccessTokens.userId],
12051224
references: [users.id],
12061225
}),
1207-
refreshTokens: many(oauthMcpRefreshTokens),
1226+
refreshTokens: many(oauthRefreshTokens),
12081227
}),
12091228
)
12101229

1211-
export const oauthMcpRefreshTokensRelations = relations(
1212-
oauthMcpRefreshTokens,
1230+
export const oauthRefreshTokensRelations = relations(
1231+
oauthRefreshTokens,
12131232
({ one }) => ({
12141233
user: one(users, {
1215-
fields: [oauthMcpRefreshTokens.userId],
1234+
fields: [oauthRefreshTokens.userId],
12161235
references: [users.id],
12171236
}),
1218-
accessToken: one(oauthMcpAccessTokens, {
1219-
fields: [oauthMcpRefreshTokens.accessTokenId],
1220-
references: [oauthMcpAccessTokens.id],
1237+
accessToken: one(oauthAccessTokens, {
1238+
fields: [oauthRefreshTokens.accessTokenId],
1239+
references: [oauthAccessTokens.id],
12211240
}),
12221241
}),
12231242
)
1243+
1244+
// Backwards compatibility relation aliases
1245+
/** @deprecated Use oauthAuthorizationCodesRelations instead */
1246+
export const oauthMcpAuthorizationCodesRelations =
1247+
oauthAuthorizationCodesRelations
1248+
/** @deprecated Use oauthAccessTokensRelations instead */
1249+
export const oauthMcpAccessTokensRelations = oauthAccessTokensRelations
1250+
/** @deprecated Use oauthRefreshTokensRelations instead */
1251+
export const oauthMcpRefreshTokensRelations = oauthRefreshTokensRelations

src/mcp/auth.server.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { db } from '~/db/client'
22
import { mcpApiKeys, mcpRateLimits } from '~/db/schema'
33
import { eq, sql } from 'drizzle-orm'
4-
import { validateOAuthToken } from './oauth.server'
4+
import {
5+
validateOAuthToken,
6+
isOAuthClientToken,
7+
} from '~/auth/oauthClient.server'
58

69
export type AuthResult =
710
| { success: true; keyId: string; userId: string; rateLimitPerMinute: number }
@@ -65,9 +68,18 @@ export async function validateMcpAuth(
6568

6669
const rawToken = match[1]
6770

68-
// OAuth access token: mcp_...
69-
if (rawToken.startsWith('mcp_')) {
70-
return validateOAuthToken(rawToken)
71+
// OAuth access token: oa_... or mcp_... (legacy)
72+
if (isOAuthClientToken(rawToken)) {
73+
const oauthResult = await validateOAuthToken(rawToken)
74+
if (!oauthResult.success) {
75+
return oauthResult
76+
}
77+
return {
78+
success: true,
79+
keyId: oauthResult.tokenId,
80+
userId: oauthResult.userId,
81+
rateLimitPerMinute: 200, // Default rate limit for OAuth tokens
82+
}
7183
}
7284

7385
// API key: ts_... (or legacy keys without prefix)

0 commit comments

Comments
 (0)