Skip to content

Commit c17612d

Browse files
committed
added schema checks
1 parent 005f661 commit c17612d

6 files changed

Lines changed: 40 additions & 14 deletions

File tree

app/composables/useAtproto.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
1-
type MiniDoc = {
2-
did: string
3-
handle: string
4-
pds: string
5-
}
1+
import type { UserSession } from '#shared/schemas/userSession'
62

73
/** @public */
84
export async function useAtproto() {
95
const {
106
data: user,
117
pending,
128
clear,
13-
} = await useAsyncData<MiniDoc | null>('user-state', async () => {
14-
const data = await useRequestFetch()<MiniDoc>('/api/auth/session', {
9+
} = await useAsyncData<UserSession | null>('user-state', async () => {
10+
return await useRequestFetch()<UserSession>('/api/auth/session', {
1511
headers: { accept: 'application/json' },
1612
})
17-
18-
return data
1913
})
2014

2115
const logout = async () => {
22-
await useRequestFetch()<MiniDoc>('/api/auth/session', {
16+
await useRequestFetch()<UserSession>('/api/auth/session', {
2317
method: 'delete',
2418
headers: { accept: 'application/json' },
2519
})

server/api/auth/atproto.get.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { NodeOAuthClient } from '@atproto/oauth-client-node'
33
import { createError, getQuery, sendRedirect } from 'h3'
44
import { useOAuthStorage } from '#server/utils/atproto/storage'
55
import { SLINGSHOT_ENDPOINT } from '#shared/utils/constants'
6+
import type { UserSession } from '#shared/schemas/userSession'
67

78
export default defineEventHandler(async event => {
89
const config = useRuntimeConfig(event)
@@ -55,7 +56,7 @@ export default defineEventHandler(async event => {
5556
`${SLINGSHOT_ENDPOINT}/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=${agent.did}`,
5657
{ headers: { 'User-Agent': 'npmx' } },
5758
)
58-
const miniDoc = (await response.json()) as { did: string; handle: string; pds: string }
59+
const miniDoc = (await response.json()) as UserSession
5960

6061
await session.update(miniDoc)
6162

server/api/auth/session.get.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { UserSession } from '#shared/schemas/userSession'
2+
13
export default eventHandlerWithOAuthSession(async (event, oAuthSession, serverSession) => {
2-
return serverSession.data
4+
return serverSession.data as UserSession
35
})

server/utils/atproto/oauth.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import type { OAuthClientMetadataInput } from '@atproto/oauth-client-node'
22
import type { EventHandlerRequest, H3Event } from 'h3'
33
import type { OAuthSession } from '@atproto/oauth-client-node'
44
import { NodeOAuthClient } from '@atproto/oauth-client-node'
5+
import { parse } from 'valibot'
56
import { useOAuthStorage } from '#server/utils/atproto/storage'
67
import { UNSET_NUXT_SESSION_PASSWORD } from '#shared/utils/constants'
8+
import { OAuthMetadataSchema } from '#shared/schemas/oauth'
79
import type { SessionManager } from 'h3'
810
// TODO: limit scope as features gets added. atproto just allows login so no scary login screen till we have scopes
911
export const scope = 'atproto'
@@ -19,7 +21,8 @@ export function getOauthClientMetadata() {
1921
? `http://localhost?redirect_uri=${encodeURIComponent(redirect_uri)}&scope=${encodeURIComponent(scope)}`
2022
: `${client_uri}/oauth-client-metadata.json`
2123

22-
return {
24+
// If anything changes here, please make sure to also update /shared/schemas/oauth.ts to match
25+
return parse(OAuthMetadataSchema, {
2326
client_name: 'npmx.dev',
2427
client_id,
2528
client_uri,
@@ -29,7 +32,7 @@ export function getOauthClientMetadata() {
2932
application_type: 'web',
3033
token_endpoint_auth_method: 'none',
3134
dpop_bound_access_tokens: true,
32-
} as OAuthClientMetadataInput
35+
}) as OAuthClientMetadataInput
3336
}
3437

3538
type EventHandlerWithOAuthSession<T extends EventHandlerRequest, D> = (

shared/schemas/oauth.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { object, string, pipe, url, array, minLength, boolean } from 'valibot'
2+
import type { InferOutput } from 'valibot'
3+
4+
export const OAuthMetadataSchema = object({
5+
client_id: pipe(string(), url()),
6+
client_name: string(),
7+
client_uri: pipe(string(), url()),
8+
redirect_uris: pipe(array(string()), minLength(1)),
9+
scope: string(),
10+
grant_types: array(string()),
11+
application_type: string(),
12+
token_endpoint_auth_method: string(),
13+
dpop_bound_access_tokens: boolean(),
14+
})
15+
16+
export type OAuthMetadata = InferOutput<typeof OAuthMetadataSchema>

shared/schemas/userSession.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { object, string, pipe, url } from 'valibot'
2+
import type { InferOutput } from 'valibot'
3+
4+
export const UserSessionSchema = object({
5+
did: string(),
6+
handle: string(),
7+
pds: pipe(string(), url()),
8+
})
9+
10+
export type UserSession = InferOutput<typeof UserSessionSchema>

0 commit comments

Comments
 (0)