+3
-2
netlify/functions/client-metadata.ts
+3
-2
netlify/functions/client-metadata.ts
···
1
1
import { Handler, HandlerEvent, HandlerResponse } from "@netlify/functions";
2
+
import { CONFIG } from "./core/config/constants";
2
3
3
4
export const handler: Handler = async (
4
5
event: HandlerEvent,
···
42
43
client_name: "ATlast (Local Dev)",
43
44
client_uri: appUrl,
44
45
redirect_uris: [redirectUri],
45
-
scope: "atproto repo:app.bsky.graph.follow",
46
+
scope: CONFIG.OAUTH_SCOPES,
46
47
grant_types: ["authorization_code", "refresh_token"],
47
48
response_types: ["code"],
48
49
application_type: "web",
···
65
66
client_uri: appUrl,
66
67
redirect_uris: [redirectUri],
67
68
logo_uri: logoUri,
68
-
scope: "atproto transition:generic",
69
+
scope: CONFIG.OAUTH_SCOPES,
69
70
grant_types: ["authorization_code", "refresh_token"],
70
71
response_types: ["code"],
71
72
application_type: "web",
+3
-1
netlify/functions/core/config/constants.ts
+3
-1
netlify/functions/core/config/constants.ts
···
2
2
PROFILE_CACHE_TTL: 5 * 60 * 1000, // 5 minutes
3
3
SESSION_EXPIRY: 30 * 24 * 60 * 60 * 1000, // 30 days
4
4
STATE_EXPIRY: 10 * 60 * 1000, // 10 minutes
5
-
COOKIE_MAX_AGE: 2592000, // 30 days in seconds
5
+
COOKIE_MAX_AGE: 2592000, // 30 days in seconds,
6
+
OAUTH_KEY_ID: "main-key", // jwks kid
7
+
OAUTH_SCOPES: "atproto transition:generic", // future?: atproto repo:app.bsky.graph.follow?action=create repo:so.sprk.graph.follow?action=create repo:sh.tangled.graph.follow?action=create
6
8
} as const;
+6
-2
netlify/functions/infrastructure/oauth/OAuthClientFactory.ts
+6
-2
netlify/functions/infrastructure/oauth/OAuthClientFactory.ts
···
6
6
import { ApiError } from "../../core/errors";
7
7
import { stateStore, sessionStore } from "./stores";
8
8
import { getOAuthConfig } from "./config";
9
+
import { CONFIG } from "../../core/config/constants";
9
10
10
11
function normalizePrivateKey(key: string): string {
11
12
if (!key.includes("\n") && key.includes("\\n")) {
···
41
42
}
42
43
43
44
const normalizedKey = normalizePrivateKey(process.env.OAUTH_PRIVATE_KEY);
44
-
const privateKey = await JoseKey.fromImportable(normalizedKey, "main-key");
45
+
const privateKey = await JoseKey.fromImportable(
46
+
normalizedKey,
47
+
CONFIG.OAUTH_KEY_ID,
48
+
);
45
49
46
50
return new NodeOAuthClient({
47
51
clientMetadata: {
···
49
53
client_name: "ATlast",
50
54
client_uri: config.clientId.replace("/oauth-client-metadata.json", ""),
51
55
redirect_uris: [config.redirectUri],
52
-
scope: "atproto transition:generic",
56
+
scope: CONFIG.OAUTH_SCOPES,
53
57
grant_types: ["authorization_code", "refresh_token"],
54
58
response_types: ["code"],
55
59
application_type: "web",
+2
-1
netlify/functions/infrastructure/oauth/config.ts
+2
-1
netlify/functions/infrastructure/oauth/config.ts
···
1
1
import { OAuthConfig } from "../../core/types";
2
2
import { ApiError } from "../../core/errors";
3
3
import { configCache } from "../cache/CacheService";
4
+
import { CONFIG } from "../../core/config/constants";
4
5
5
6
export function getOAuthConfig(event?: {
6
7
headers: Record<string, string | undefined>;
···
51
52
"redirect_uri",
52
53
`http://127.0.0.1:${port}/.netlify/functions/oauth-callback`,
53
54
],
54
-
["scope", "atproto transition:generic"],
55
+
["scope", CONFIG.OAUTH_SCOPES],
55
56
])}`;
56
57
57
58
console.log("Using loopback OAuth for local development");
+2
-1
netlify/functions/jwks.ts
+2
-1
netlify/functions/jwks.ts
···
1
1
import { Handler } from "@netlify/functions";
2
+
import { CONFIG } from "./core/config/constants";
2
3
3
4
const PUBLIC_JWK = {
4
5
kty: "EC",
5
6
x: "3sVbr4xwN7UtmG1L19vL0x9iN-FRcl7p-Wja_xPbhhk",
6
7
y: "Y1XKDaAyDwijp8aEIGHmO46huKjajSQH2cbfpWaWpQ4",
7
8
crv: "P-256",
8
-
kid: "main-key",
9
+
kid: CONFIG.OAUTH_KEY_ID,
9
10
use: "sig",
10
11
alg: "ES256",
11
12
};
+2
-1
netlify/functions/oauth-start.ts
+2
-1
netlify/functions/oauth-start.ts
···
3
3
import { successResponse } from "./utils";
4
4
import { withErrorHandling } from "./core/middleware";
5
5
import { ValidationError } from "./core/errors";
6
+
import { CONFIG } from "./core/config/constants";
6
7
7
8
interface OAuthStartRequestBody {
8
9
login_hint?: string;
···
26
27
const client = await createOAuthClient(event);
27
28
28
29
const authUrl = await client.authorize(loginHint, {
29
-
scope: "atproto transition:generic",
30
+
scope: CONFIG.OAUTH_SCOPES,
30
31
});
31
32
32
33
console.log("[oauth-start] Generated auth URL for:", loginHint);