+33
-22
src/main.tsx
+33
-22
src/main.tsx
···
4
5
import { Client, ok, simpleFetchHandler } from '@atcute/client';
6
import type { Did } from '@atcute/lexicons';
7
-
import { configureOAuth } from '@atcute/oauth-browser-client';
8
9
import * as navigation from '~/globals/navigation';
10
import * as preferences from '~/globals/preferences';
···
36
37
// Configure OAuth
38
{
39
const host = new Client({
40
handler: simpleFetchHandler({ service: location.origin }),
41
});
42
43
configureOAuth({
44
metadata: {
45
-
client_id: `${location.origin}/oauth-client-metadata.json`,
46
-
redirect_uri: `${location.origin}/oauth/callback`,
47
},
48
49
identityResolver: {
···
59
return data;
60
},
61
},
62
-
async fetchClientAssertion({ aud, jkt, createDpopProof }) {
63
-
const dpop = await createDpopProof(`${location.origin}/xrpc/x.aglais.requestAssertion`);
64
65
-
const data = await ok(
66
-
host.post('x.aglais.requestAssertion', {
67
-
input: {
68
-
aud: aud,
69
-
jkt: jkt,
70
-
},
71
-
headers: {
72
-
dpop: dpop,
73
-
},
74
-
}),
75
-
);
76
-
77
-
return {
78
-
client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
79
-
client_assertion: data.assertion,
80
-
};
81
-
},
82
});
83
}
84
···
4
5
import { Client, ok, simpleFetchHandler } from '@atcute/client';
6
import type { Did } from '@atcute/lexicons';
7
+
import { type ClientAssertionFetcher, configureOAuth } from '@atcute/oauth-browser-client';
8
9
import * as navigation from '~/globals/navigation';
10
import * as preferences from '~/globals/preferences';
···
36
37
// Configure OAuth
38
{
39
+
// Development mode uses public client with http://localhost client ID
40
+
// Production mode uses confidential client with server-side JWT assertions
41
+
const isPublicClient = !!import.meta.env.VITE_OAUTH_CLIENT_ID;
42
+
43
const host = new Client({
44
handler: simpleFetchHandler({ service: location.origin }),
45
});
46
47
+
const fetchClientAssertion: ClientAssertionFetcher = async ({ aud, jkt, createDpopProof }) => {
48
+
const dpop = await createDpopProof(`${location.origin}/xrpc/x.aglais.requestAssertion`);
49
+
50
+
const data = await ok(
51
+
host.post('x.aglais.requestAssertion', {
52
+
input: {
53
+
aud: aud,
54
+
jkt: jkt,
55
+
},
56
+
headers: {
57
+
dpop: dpop,
58
+
},
59
+
}),
60
+
);
61
+
62
+
return {
63
+
client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
64
+
client_assertion: data.assertion,
65
+
};
66
+
};
67
+
68
configureOAuth({
69
metadata: {
70
+
client_id: isPublicClient
71
+
? import.meta.env.VITE_OAUTH_CLIENT_ID
72
+
: `${location.origin}/oauth-client-metadata.json`,
73
+
redirect_uri: isPublicClient
74
+
? import.meta.env.VITE_OAUTH_REDIRECT_URL
75
+
: `${location.origin}/oauth/callback`,
76
},
77
78
identityResolver: {
···
88
return data;
89
},
90
},
91
92
+
fetchClientAssertion: isPublicClient ? undefined : fetchClientAssertion,
93
});
94
}
95
+3
src/vite-env.d.ts
+3
src/vite-env.d.ts
+32
-1
vite.config.ts
+32
-1
vite.config.ts
···
5
import { VitePWA } from 'vite-plugin-pwa';
6
import solid from 'vite-plugin-solid';
7
8
export default defineConfig({
9
build: {
10
target: 'esnext',
···
54
},
55
},
56
server: {
57
-
allowedHosts: ['.trycloudflare.com'],
58
},
59
optimizeDeps: {
60
esbuildOptions: {
···
110
);
111
112
return { code: transformed, map: null };
113
},
114
},
115
],
···
5
import { VitePWA } from 'vite-plugin-pwa';
6
import solid from 'vite-plugin-solid';
7
8
+
const SERVER_HOST = '127.0.0.1';
9
+
const SERVER_PORT = 52222;
10
+
11
+
const OAUTH_SCOPE = 'atproto transition:generic transition:chat.bsky';
12
+
13
export default defineConfig({
14
build: {
15
target: 'esnext',
···
59
},
60
},
61
server: {
62
+
host: SERVER_HOST,
63
+
port: SERVER_PORT,
64
},
65
optimizeDeps: {
66
esbuildOptions: {
···
116
);
117
118
return { code: transformed, map: null };
119
+
},
120
+
},
121
+
122
+
// Injects OAuth-related variables for development mode
123
+
{
124
+
name: 'aglais-oauth-inject',
125
+
config(_conf, { command }) {
126
+
if (command === 'build') {
127
+
// Production uses confidential client
128
+
process.env.VITE_OAUTH_CLIENT_ID = '';
129
+
process.env.VITE_OAUTH_REDIRECT_URL = '';
130
+
} else {
131
+
// Development uses public client with http://localhost format
132
+
const redirectUri = `http://${SERVER_HOST}:${SERVER_PORT}/oauth/callback`;
133
+
134
+
const clientId =
135
+
`http://localhost` +
136
+
`?redirect_uri=${encodeURIComponent(redirectUri)}` +
137
+
`&scope=${encodeURIComponent(OAUTH_SCOPE)}`;
138
+
139
+
process.env.VITE_OAUTH_CLIENT_ID = clientId;
140
+
process.env.VITE_OAUTH_REDIRECT_URL = redirectUri;
141
+
}
142
+
143
+
process.env.VITE_OAUTH_SCOPE = OAUTH_SCOPE;
144
},
145
},
146
],