@voltro/plugin-auth-social 0.86.0 → 0.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,11 +1,16 @@
1
- import { SocialAccountLinkError as e, SocialAuthError as t, SocialConfigError as n, SocialExchangeError as r, SocialIdTokenError as i, SocialStateMismatchError as a } from "./errors.js";
2
- import { SOCIAL_PROVIDERS as o, SOCIAL_PROVIDER_IDS as s, isSocialProviderId as c, socialProvider as l } from "./providers.js";
3
- import { socialBeginLogin as u } from "./login.js";
4
- import { APPLE_CLIENT_SECRET_DEFAULT_TTL_S as d, APPLE_CLIENT_SECRET_MAX_TTL_S as f, _resetAppleSecretCache as p, appleClientSecret as m, isApplePrivateRelayEmail as h, parseAppleUserPayload as g } from "./apple.js";
5
- import { fetchGithubIdentity as _ } from "./github.js";
6
- import { socialCompleteLogin as v } from "./callback.js";
7
- import { decideSocialLink as y } from "./linking.js";
8
- import { completeSocialSignIn as b } from "./signIn.js";
9
- import { SOCIAL_IDENTITY_TABLE as x, dataStoreSocialIdentityStore as S, linkSocialIdentity as C, memorySocialIdentityStore as w, socialAuthTables as T, socialIdentitiesTable as E } from "./identityStore.js";
10
- import { socialAuthPlugin as D } from "./plugin.js";
11
- export { d as APPLE_CLIENT_SECRET_DEFAULT_TTL_S, f as APPLE_CLIENT_SECRET_MAX_TTL_S, x as SOCIAL_IDENTITY_TABLE, o as SOCIAL_PROVIDERS, s as SOCIAL_PROVIDER_IDS, e as SocialAccountLinkError, t as SocialAuthError, n as SocialConfigError, r as SocialExchangeError, i as SocialIdTokenError, a as SocialStateMismatchError, p as _resetAppleSecretCache, m as appleClientSecret, b as completeSocialSignIn, S as dataStoreSocialIdentityStore, y as decideSocialLink, _ as fetchGithubIdentity, h as isApplePrivateRelayEmail, c as isSocialProviderId, C as linkSocialIdentity, w as memorySocialIdentityStore, g as parseAppleUserPayload, D as socialAuthPlugin, T as socialAuthTables, u as socialBeginLogin, v as socialCompleteLogin, E as socialIdentitiesTable, l as socialProvider };
1
+ import { PlatformTicketError as e, SocialAccountLinkError as t, SocialAuthError as n, SocialConfigError as r, SocialExchangeError as i, SocialIdTokenError as a, SocialStateMismatchError as o } from "./errors.js";
2
+ import { SOCIAL_PROVIDERS as s, SOCIAL_PROVIDER_IDS as c, isSocialProviderId as l, socialProvider as u } from "./providers.js";
3
+ import { socialBeginLogin as d } from "./login.js";
4
+ import { APPLE_CLIENT_SECRET_DEFAULT_TTL_S as f, APPLE_CLIENT_SECRET_MAX_TTL_S as p, _resetAppleSecretCache as m, appleClientSecret as h, isApplePrivateRelayEmail as g, parseAppleUserPayload as _ } from "./apple.js";
5
+ import { fetchGithubIdentity as v } from "./github.js";
6
+ import { fetchDiscordIdentity as y } from "./discord.js";
7
+ import { fetchEpicIdentity as b } from "./epic.js";
8
+ import { socialCompleteLogin as x } from "./callback.js";
9
+ import { decideSocialLink as S } from "./linking.js";
10
+ import { completeSocialSignIn as C } from "./signIn.js";
11
+ import { SOCIAL_IDENTITY_TABLE as w, SocialIdentityConflict as T, dataStoreSocialIdentityStore as E, linkSocialIdentity as D, memorySocialIdentityStore as O, socialAuthTables as k, socialIdentitiesTable as A } from "./identityStore.js";
12
+ import { completeGuestSocialUpgrade as j } from "./guestUpgrade.js";
13
+ import { steamBeginOpenId as M, steamCompleteOpenId as N, verifySteamWebApiTicket as P } from "./steam.js";
14
+ import { definePlatformLogin as F, eosPlatformLogin as I, steamPlatformLogin as L, verifyPlatformTicket as R } from "./platform.js";
15
+ import { socialAuthPlugin as z } from "./plugin.js";
16
+ export { f as APPLE_CLIENT_SECRET_DEFAULT_TTL_S, p as APPLE_CLIENT_SECRET_MAX_TTL_S, e as PlatformTicketError, w as SOCIAL_IDENTITY_TABLE, s as SOCIAL_PROVIDERS, c as SOCIAL_PROVIDER_IDS, t as SocialAccountLinkError, n as SocialAuthError, r as SocialConfigError, i as SocialExchangeError, a as SocialIdTokenError, T as SocialIdentityConflict, o as SocialStateMismatchError, m as _resetAppleSecretCache, h as appleClientSecret, j as completeGuestSocialUpgrade, C as completeSocialSignIn, E as dataStoreSocialIdentityStore, S as decideSocialLink, F as definePlatformLogin, I as eosPlatformLogin, y as fetchDiscordIdentity, b as fetchEpicIdentity, v as fetchGithubIdentity, g as isApplePrivateRelayEmail, l as isSocialProviderId, D as linkSocialIdentity, O as memorySocialIdentityStore, _ as parseAppleUserPayload, z as socialAuthPlugin, k as socialAuthTables, d as socialBeginLogin, x as socialCompleteLogin, A as socialIdentitiesTable, u as socialProvider, M as steamBeginOpenId, N as steamCompleteOpenId, L as steamPlatformLogin, R as verifyPlatformTicket, P as verifySteamWebApiTicket };
package/dist/linking.js CHANGED
@@ -2,10 +2,7 @@ import { SocialAccountLinkError as e } from "./errors.js";
2
2
  //#region src/linking.ts
3
3
  var t = (t) => {
4
4
  let { profile: n, linkedUserId: r, existingUserIdByEmail: i, policy: a } = t;
5
- return r === null ? n.email === null ? {
6
- kind: "refuse",
7
- error: new e("no_email", `${n.provider} did not return an email address for this account. Add and verify an email with the provider, or sign in another way.`, 400)
8
- } : i === null ? { kind: "create-user" } : a === "never" ? {
5
+ return r === null ? n.email === null || i === null ? { kind: "create-user" } : a === "never" ? {
9
6
  kind: "refuse",
10
7
  error: new e("account_exists_unlinked", `An account already exists for ${n.email}. Sign in with your existing method, then connect ${n.provider} from your account settings.`)
11
8
  } : n.emailVerified ? n.emailIsPrivateRelay ? {
package/dist/login.js CHANGED
@@ -14,7 +14,12 @@ var i = (i) => {
14
14
  code_challenge: t(s),
15
15
  code_challenge_method: "S256"
16
16
  });
17
- return c && u.set("nonce", c), a.responseMode === "form_post" && u.set("response_mode", "form_post"), i.prompt && u.set("prompt", i.prompt), i.loginHint && u.set(a.id === "github" ? "login" : "login_hint", i.loginHint), {
17
+ return c && u.set("nonce", c), a.id === "twitch" && u.set("claims", JSON.stringify({ id_token: {
18
+ email: null,
19
+ email_verified: null,
20
+ preferred_username: null,
21
+ picture: null
22
+ } })), a.responseMode === "form_post" && u.set("response_mode", "form_post"), i.prompt && u.set("prompt", i.prompt), i.loginHint && u.set(a.id === "github" ? "login" : "login_hint", i.loginHint), {
18
23
  provider: a.id,
19
24
  url: `${a.authorizeUrl}?${u.toString()}`,
20
25
  state: o,
@@ -0,0 +1,66 @@
1
+ import { guestIdentityOf as e } from "./guestHandoff.js";
2
+ import { signAuthClaims as t, verifyAuthClaims as n } from "@voltro/plugin-auth";
3
+ import { createCipheriv as r, createDecipheriv as i, createHash as a, hkdfSync as o, randomBytes as s, timingSafeEqual as c } from "node:crypto";
4
+ //#region src/nativeGuestUpgrade.ts
5
+ var l = /^[A-Za-z0-9_-]{43}$/, u = /^[A-Za-z0-9._~-]{43,128}$/, d = /^[A-Za-z0-9._~-]{1,256}$/, f = (e, t) => {
6
+ if (!e || typeof e != "object" || Array.isArray(e)) return null;
7
+ let n = e;
8
+ return Object.keys(n).some((e) => e !== "ch" && e !== "r" && e !== "ns") || typeof n.ch != "string" || !l.test(n.ch) || typeof n.r != "string" || !t.includes(n.r) || typeof n.ns != "string" || !d.test(n.ns) ? null : {
9
+ ch: n.ch,
10
+ r: n.r,
11
+ ns: n.ns
12
+ };
13
+ }, p = (e) => typeof e == "string" && u.test(e), m = (e, t) => {
14
+ let n = Buffer.from(a("sha256").update(e, "ascii").digest("base64url")), r = Buffer.from(t);
15
+ return n.length === r.length && c(n, r);
16
+ }, h = (e) => [e.current, e.previous].filter((e) => e !== void 0).map((e) => e.secret), g = (e, n) => t({
17
+ kind: "ticket",
18
+ g: e.guest,
19
+ p: e.provider,
20
+ ...e.native,
21
+ exp: e.exp,
22
+ audience: e.audience
23
+ }, n.current.secret, "social-native-upgrade"), _ = (t, r, i, a) => {
24
+ if (!t || t.length > 3e3) return null;
25
+ let o = h(r).map((e) => n(t, e, "social-native-upgrade")).find((e) => e !== null);
26
+ if (!o || o.kind !== "ticket" || o.audience !== i || typeof o.exp != "number" || o.exp <= Math.floor(Date.now() / 1e3) || typeof o.p != "string") return null;
27
+ let s = e(o.g), c = f({
28
+ ch: o.ch,
29
+ r: o.r,
30
+ ns: o.ns
31
+ }, a);
32
+ return s && c ? {
33
+ guest: s,
34
+ provider: o.p,
35
+ native: c
36
+ } : null;
37
+ }, v = (e, t) => Buffer.from(o("sha256", e, "voltro:social-native-upgrade:v1", t, 32)), y = (e, t, n) => {
38
+ let i = s(12), a = r("aes-256-gcm", v(t.current.secret, n), i), o = Buffer.concat([a.update(JSON.stringify({
39
+ h: e.handoff,
40
+ ch: e.ch,
41
+ g: e.guestId,
42
+ exp: e.exp
43
+ }), "utf8"), a.final()]);
44
+ return Buffer.concat([
45
+ i,
46
+ a.getAuthTag(),
47
+ o
48
+ ]).toString("base64url");
49
+ }, b = (e, t, n) => {
50
+ if (typeof e != "string" || e.length < 40 || e.length > 6e3 || !/^[A-Za-z0-9_-]+$/.test(e)) return null;
51
+ let r = Buffer.from(e, "base64url");
52
+ if (r.length < 29) return null;
53
+ for (let e of h(t)) try {
54
+ let t = i("aes-256-gcm", v(e, n), r.subarray(0, 12));
55
+ t.setAuthTag(r.subarray(12, 28));
56
+ let a = JSON.parse(Buffer.concat([t.update(r.subarray(28)), t.final()]).toString("utf8"));
57
+ return typeof a.h != "string" || typeof a.ch != "string" || typeof a.g != "string" || typeof a.exp != "number" || a.exp <= Math.floor(Date.now() / 1e3) ? null : {
58
+ handoff: a.h,
59
+ ch: a.ch,
60
+ guestId: a.g
61
+ };
62
+ } catch {}
63
+ return null;
64
+ };
65
+ //#endregion
66
+ export { p as isNativeVerifier, f as nativeUpgradeRequestOf, b as openNativeUpgradeCode, y as sealNativeUpgradeCode, g as signNativeUpgradeTicket, m as verifierMatches, _ as verifyNativeUpgradeTicket };
@@ -0,0 +1,115 @@
1
+ import { PlatformTicketError as e, SocialAuthError as t, SocialConfigError as n, SocialExchangeError as r } from "./errors.js";
2
+ import { isSocialProviderId as i } from "./providers.js";
3
+ import { verifySteamWebApiTicket as a } from "./steam.js";
4
+ import { JwtVerifyError as o, verifyJwt as s } from "@voltro/protocol/jwt";
5
+ //#region src/platform.ts
6
+ var c = /^[a-z][a-z0-9-]{1,31}$/, l = /^[\x21-\x7e]{1,255}$/, u = (e) => {
7
+ if (!c.test(e.id) || i(e.id)) throw new n("definePlatformLogin: id must be 2–32 lowercase letters, digits or hyphens and not a social provider id");
8
+ let t = e.verify;
9
+ return {
10
+ id: e.id,
11
+ declaredEnv: e.declaredEnv ?? [],
12
+ permissions: e.permissions ?? [],
13
+ check: e.check ?? (() => void 0),
14
+ verify: async (n) => {
15
+ let i = await t(n);
16
+ if (typeof i?.accountId != "string" || !l.test(i.accountId)) throw new r("malformed_token_response", `${e.id}: the verifier returned no usable account id`, 503);
17
+ return { accountId: i.accountId };
18
+ }
19
+ };
20
+ }, d = (e = {}) => {
21
+ let t = e.identity ?? "voltro";
22
+ if (!t || t.length > 255) throw new n("steamPlatformLogin: identity must be 1–255 characters");
23
+ let r = () => {
24
+ let t = e.appId ?? Number(process.env.VOLTRO_STEAM_APP_ID ?? ""), r = e.publisherKey ?? process.env.VOLTRO_STEAM_PUBLISHER_KEY ?? "";
25
+ if (!Number.isSafeInteger(t) || t < 1 || t > 4294967295) throw new n("steamPlatformLogin: no app id — pass `appId` or set VOLTRO_STEAM_APP_ID");
26
+ if (!r) throw new n("steamPlatformLogin: no publisher key — pass `publisherKey` or set VOLTRO_STEAM_PUBLISHER_KEY");
27
+ return {
28
+ appId: t,
29
+ publisherKey: r
30
+ };
31
+ };
32
+ return {
33
+ id: "steam",
34
+ declaredEnv: [{
35
+ name: "VOLTRO_STEAM_APP_ID",
36
+ required: e.appId === void 0,
37
+ secret: !1,
38
+ description: "Steam App ID the game runs as."
39
+ }, {
40
+ name: "VOLTRO_STEAM_PUBLISHER_KEY",
41
+ required: e.publisherKey === void 0,
42
+ secret: !0,
43
+ description: "Steamworks Web API publisher key; verifies game tickets on the server."
44
+ }],
45
+ permissions: ["network:outbound:partner.steam-api.com"],
46
+ check: () => {
47
+ r();
48
+ },
49
+ verify: async (n) => {
50
+ let { appId: i, publisherKey: o } = r();
51
+ return { accountId: (await a({
52
+ ticket: n,
53
+ appId: i,
54
+ identity: t,
55
+ publisherKey: o,
56
+ ...e.timeoutMs === void 0 ? {} : { timeoutMs: e.timeoutMs },
57
+ ...e.allowPublisherBanned === void 0 ? {} : { allowPublisherBanned: e.allowPublisherBanned },
58
+ ...e.verificationUrl === void 0 ? {} : { verificationUrl: e.verificationUrl },
59
+ ...e.fetchImpl === void 0 ? {} : { fetchImpl: e.fetchImpl }
60
+ })).providerAccountId };
61
+ }
62
+ };
63
+ }, f = "https://api.epicgames.dev/auth/v1/oauth/jwks", p = "https://api.epicgames.dev", m = /^[0-9a-fA-F]{32}$/, h = (t = {}) => {
64
+ let i = () => {
65
+ let e = t.clientId ?? process.env.VOLTRO_EOS_CLIENT_ID ?? "", r = t.deploymentId ?? process.env.VOLTRO_EOS_DEPLOYMENT_ID ?? "";
66
+ if (!e) throw new n("eosPlatformLogin: no client id — pass `clientId` or set VOLTRO_EOS_CLIENT_ID");
67
+ if (!r) throw new n("eosPlatformLogin: no deployment id — pass `deploymentId` or set VOLTRO_EOS_DEPLOYMENT_ID");
68
+ return {
69
+ clientId: e,
70
+ deploymentId: r
71
+ };
72
+ };
73
+ return {
74
+ id: "eos",
75
+ declaredEnv: [{
76
+ name: "VOLTRO_EOS_CLIENT_ID",
77
+ required: t.clientId === void 0,
78
+ secret: !1,
79
+ description: "EOS client id the game signs in with."
80
+ }, {
81
+ name: "VOLTRO_EOS_DEPLOYMENT_ID",
82
+ required: t.deploymentId === void 0,
83
+ secret: !1,
84
+ description: "EOS deployment id the game runs in."
85
+ }],
86
+ permissions: ["network:outbound:api.epicgames.dev"],
87
+ check: () => {
88
+ i();
89
+ },
90
+ verify: async (n) => {
91
+ let { clientId: a, deploymentId: c } = i();
92
+ if (n.length > 8192 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(n)) throw new e("eos: malformed ID token");
93
+ let l;
94
+ try {
95
+ l = await s(n, t.jwksUrl ?? f, {
96
+ audience: a,
97
+ algorithms: ["RS256"]
98
+ });
99
+ } catch (t) {
100
+ throw t instanceof o && t.code === "jwks_unreachable" ? new r("exchange_failed", "eos: signing keys unavailable", 503) : new e("eos: ID token failed verification");
101
+ }
102
+ let u = l.iss, d = l.iat;
103
+ if (typeof u != "string" || !(u === p || u.startsWith(p + "/")) || typeof d != "number" || d * 1e3 > Date.now() + 6e4 || l.pfdid !== c || typeof l.sub != "string" || !m.test(l.sub)) throw new e("eos: ID token is for another issuer, deployment or player");
104
+ return { accountId: l.sub };
105
+ }
106
+ };
107
+ }, g = async (e, n) => {
108
+ try {
109
+ return await e.verify(n);
110
+ } catch (n) {
111
+ throw n instanceof t ? n : new r("exchange_failed", `${e.id}: ticket verification failed`, 503);
112
+ }
113
+ };
114
+ //#endregion
115
+ export { u as definePlatformLogin, h as eosPlatformLogin, d as steamPlatformLogin, g as verifyPlatformTicket };