Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions backend/tss_api/src/middleware/discord_auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,17 @@ export async function discordAuthMiddleware(
return;
}

if (!result.data.email) {
if (!result.data.id) {
res.status(401).json({
error: "Can't get email from Discord token",
error: "Can't get id from Discord token",
});
return;
}

res.locals.oauth_user = {
type: "discord" as AuthType,
email: result.data.email,
// in discord, use discord id as email with prefix
email: `discord_${result.data.id}`,
name: result.data.username,
};

Expand Down
8 changes: 5 additions & 3 deletions backend/tss_api/src/middleware/google_auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,18 @@ export async function googleAuthMiddleware(
return;
}

if (!result.data.email || !result.data.sub || !result.data.name) {
if (!result.data.sub || !result.data.email) {
res.status(401).json({
error: "Unauthorized: Invalid token",
error: "Can't get sub or email from Google token",
});
return;
}

res.locals.oauth_user = {
type: "google" as AuthType,
email: result.data.email,
// in google, use google sub as email with prefix
email: `google_${result.data.sub}`,
name: result.data.email,
};

next();
Expand Down
6 changes: 6 additions & 0 deletions backend/tss_api/src/middleware/telegram_auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ export async function telegramAuthMiddleware(
}

const userInfo: TelegramUserInfo = result.data;
if (!userInfo.id) {
res.status(401).json({
error: "Can't get id from Telegram token",
});
return;
}

res.locals.oauth_user = {
type: "telegram" as AuthType,
Expand Down
4 changes: 2 additions & 2 deletions backend/tss_api/src/middleware/x_auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ export async function xAuthMiddleware(
return;
}

if (!result.data.id || !result.data.username) {
if (!result.data.id) {
res.status(401).json({
error: "Unauthorized: Invalid token",
error: "Can't get id from X token",
});
return;
}
Expand Down
6 changes: 6 additions & 0 deletions embed/oko_attached/src/window_msgs/oauth_info_pass/discord.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ export async function verifyIdTokenOfDiscord(
}

const result = await response.json();
if (!result.id) {
return {
success: false,
err: "Discord id not found",
};
}

const userInfo: DiscordUserInfo = {
id: result.id,
Expand Down
34 changes: 12 additions & 22 deletions embed/oko_attached/src/window_msgs/oauth_info_pass/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,7 @@ export async function verifyIdToken(
success: true,
data: {
provider: "auth0",
email: auth0TokenInfo.email,
email_verified: auth0TokenInfo.email_verified,
nonce: auth0TokenInfo.nonce,
name: auth0TokenInfo.name,
sub: auth0TokenInfo.sub,
user_identifier: auth0TokenInfo.email,
},
};
}
Expand All @@ -54,11 +50,8 @@ export async function verifyIdToken(
success: true,
data: {
provider: "google",
email: googleTokenInfo.email,
email_verified: googleTokenInfo.email_verified === "true",
nonce: googleTokenInfo.nonce,
name: googleTokenInfo.name,
sub: googleTokenInfo.sub,
// in google, use google sub as user identifier with prefix
user_identifier: `google_${googleTokenInfo.sub}`,
},
};
}
Expand All @@ -84,8 +77,8 @@ export async function verifyIdToken(
success: true,
data: {
provider: "discord",
email: discordTokenInfo.data.email,
name: discordTokenInfo.data.username,
// in discord, use discord id as user identifier with prefix
user_identifier: `discord_${discordTokenInfo.data.id}`,
},
};
}
Expand All @@ -100,20 +93,12 @@ export async function verifyIdToken(
};
}

if (!xTokenInfo.data.id) {
return {
success: false,
err: "X email not found",
};
}

return {
success: true,
data: {
provider: "x",
// in x, use x id as email
email: xTokenInfo.data.id,
name: xTokenInfo.data.name,
// in x, use x id as user identifier with prefix
user_identifier: `x_${xTokenInfo.data.id}`,
},
};
}
Expand Down Expand Up @@ -143,10 +128,15 @@ async function verifyGoogleIdToken(
}

const googleTokenInfo = (await response.json()) as GoogleTokenInfo;

if (googleTokenInfo.nonce !== nonce) {
throw new Error("Google token nonce mismatch");
}

if (!googleTokenInfo.sub) {
throw new Error("Google token sub not found");
}

return googleTokenInfo;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ async function validateOAuthPayloadOfX(
success: true,
data: {
idToken: tokenInfo,
userIdentifier: `x_${userInfo.email}`,
userIdentifier: userInfo.user_identifier,
},
};
}
Expand Down Expand Up @@ -136,20 +136,14 @@ async function validateOAuthPayloadOfDiscord(
}

const userInfo = verifyIdTokenRes.data;
if (!userInfo.email) {
return {
success: false,
err: { type: "unknown", error: "Discord email not found" },
};
}

appState.setCodeVerifier(hostOrigin, null);

return {
success: true,
data: {
idToken: tokenRes.data,
userIdentifier: userInfo.email,
userIdentifier: userInfo.user_identifier,
},
};
}
Expand Down Expand Up @@ -186,7 +180,7 @@ async function validateOAuthPayload(
success: true,
data: {
idToken: payload.id_token,
userIdentifier: tokenInfo.email,
userIdentifier: tokenInfo.user_identifier,
},
};
}
Expand Down
7 changes: 7 additions & 0 deletions embed/oko_attached/src/window_msgs/oauth_info_pass/x.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ export async function verifyIdTokenOfX(
}

const result = await response.json();
if (!result.data.id) {
return {
success: false,
err: "X id not found",
};
}

return { success: true, data: result.data };
} catch (err: any) {
return { success: false, err: err.toString() };
Expand Down
6 changes: 1 addition & 5 deletions embed/oko_attached/src/window_msgs/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,7 @@ export interface Auth0TokenInfo {

export interface TokenInfo {
provider: AuthType;
email: string;
email_verified?: boolean;
nonce?: string;
name?: string;
sub?: string;
user_identifier: string;
}

export interface UserSignInResult {
Expand Down
4 changes: 1 addition & 3 deletions key_share_node/server/src/auth/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import type { AuthType } from "@oko-wallet/oko-types/auth";

export interface OAuthUser {
type: AuthType;
email: string;
name?: string;
sub?: string;
user_identifier: string;
}

export type OAuthValidationFail =
Expand Down
49 changes: 29 additions & 20 deletions key_share_node/server/src/middlewares/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,11 @@ type VerifyResult =
data: Result<DiscordTokenInfo, OAuthValidationFail>;
};

export interface AuthenticatedRequest<T = any>
extends Request<any, any, T & OAuthBody> {}
export interface AuthenticatedRequest<T = any> extends Request<
any,
any,
T & OAuthBody
> {}

export async function bearerTokenMiddleware(
req: AuthenticatedRequest,
Expand Down Expand Up @@ -146,19 +149,18 @@ export async function bearerTokenMiddleware(

switch (result.auth_type) {
case "x": {
if (!result.data.data.id || !result.data.data.username) {
if (!result.data.data.id) {
const errorRes: KSNodeApiErrorResponse = {
success: false,
code: "UNAUTHORIZED",
msg: "Invalid token: missing required fields (id or username)",
msg: "Invalid token: missing required field (id)",
};
res.status(ErrorCodeMap[errorRes.code]).json(errorRes);
return;
}
res.locals.oauth_user = {
type: result.auth_type,
email: `x_${result.data.data.id}`,
name: result.data.data.username,
user_identifier: `x_${result.data.data.id}`,
};
break;
}
Expand All @@ -174,8 +176,7 @@ export async function bearerTokenMiddleware(
}
res.locals.oauth_user = {
type: result.auth_type,
email: `telegram_${result.data.data.id}`,
name: result.data.data.username,
user_identifier: `telegram_${result.data.data.id}`,
};
break;
}
Expand All @@ -191,31 +192,39 @@ export async function bearerTokenMiddleware(
}
res.locals.oauth_user = {
type: result.auth_type,
email: result.data.data.email,
name: result.data.data.username,
user_identifier: `discord_${result.data.data.id}`,
};
break;
}
case "google": {
if (!result.data.data.sub || !result.data.data.email) {
const errorRes: KSNodeApiErrorResponse = {
success: false,
code: "UNAUTHORIZED",
msg: "Invalid token: missing required field (sub or email)",
};
res.status(ErrorCodeMap[errorRes.code]).json(errorRes);
return;
}
res.locals.oauth_user = {
type: result.auth_type,
user_identifier: `google_${result.data.data.sub}`,
};
break;
}
case "google":
case "auth0": {
if (
!result.data.data.email ||
!result.data.data.sub ||
!result.data.data.name
) {
if (!result.data.data.email || !result.data.data.sub) {
const errorRes: KSNodeApiErrorResponse = {
success: false,
code: "UNAUTHORIZED",
msg: "Invalid token: missing required fields (email, sub, or name)",
msg: "Invalid token: missing required field (email or sub)",
};
res.status(ErrorCodeMap[errorRes.code]).json(errorRes);
return;
}
res.locals.oauth_user = {
type: result.auth_type,
email: result.data.data.email,
name: result.data.data.name,
sub: result.data.data.sub,
user_identifier: result.data.data.email,
};
break;
}
Expand Down
6 changes: 3 additions & 3 deletions key_share_node/server/src/routes/key_share/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export function makeKeyshareRouter() {
const registerKeyShareRes = await registerKeyShare(
state.db,
{
user_auth_id: oauthUser.email,
user_auth_id: oauthUser.user_identifier,
auth_type,
curve_type: body.curve_type,
public_key: publicKeyBytesRes.data,
Expand Down Expand Up @@ -302,7 +302,7 @@ export function makeKeyshareRouter() {
const getKeyShareRes = await getKeyShare(
state.db,
{
user_auth_id: oauthUser.email,
user_auth_id: oauthUser.user_identifier,
auth_type,
public_key: publicKeyBytesRes.data,
},
Expand Down Expand Up @@ -569,7 +569,7 @@ export function makeKeyshareRouter() {
const reshareKeyShareRes = await reshareKeyShare(
state.db,
{
user_auth_id: oauthUser.email,
user_auth_id: oauthUser.user_identifier,
auth_type,
curve_type: body.curve_type,
public_key: publicKeyBytesRes.data,
Expand Down