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
15 changes: 14 additions & 1 deletion apps/consent/app/graphql/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ export type Scalars = {
SignedAmount: { input: number; output: number; }
/** A string amount (of a currency) that can be negative (e.g. in a transaction) */
SignedDisplayMajorAmount: { input: string; output: string; }
/** Nonce provided by Telegram Passport to validate the login/upgrade flow */
TelegramPassportNonce: { input: string; output: string; }
/** Timestamp field, serialized as Unix time (the number of seconds since the Unix epoch) */
Timestamp: { input: number; output: number; }
/** A time-based one-time password */
Expand Down Expand Up @@ -1045,6 +1047,7 @@ export type Mutation = {
readonly userEmailRegistrationValidate: UserEmailRegistrationValidatePayload;
readonly userLogin: AuthTokenPayload;
readonly userLoginUpgrade: UpgradePayload;
readonly userLoginUpgradeTelegram: UpgradePayload;
readonly userLogout: SuccessPayload;
readonly userPhoneDelete: UserPhoneDeletePayload;
readonly userPhoneRegistrationInitiate: SuccessPayload;
Expand Down Expand Up @@ -1283,6 +1286,11 @@ export type MutationUserLoginUpgradeArgs = {
};


export type MutationUserLoginUpgradeTelegramArgs = {
input: UserLoginUpgradeTelegramInput;
};


export type MutationUserLogoutArgs = {
input?: InputMaybe<UserLogoutInput>;
};
Expand Down Expand Up @@ -2078,6 +2086,11 @@ export type UserLoginUpgradeInput = {
readonly phone: Scalars['Phone']['input'];
};

export type UserLoginUpgradeTelegramInput = {
readonly nonce: Scalars['TelegramPassportNonce']['input'];
readonly phone: Scalars['Phone']['input'];
};

export type UserLogoutInput = {
readonly deviceToken: Scalars['String']['input'];
};
Expand Down Expand Up @@ -2346,4 +2359,4 @@ export function useGetUserIdSuspenseQuery(baseOptions?: Apollo.SkipToken | Apoll
export type GetUserIdQueryHookResult = ReturnType<typeof useGetUserIdQuery>;
export type GetUserIdLazyQueryHookResult = ReturnType<typeof useGetUserIdLazyQuery>;
export type GetUserIdSuspenseQueryHookResult = ReturnType<typeof useGetUserIdSuspenseQuery>;
export type GetUserIdQueryResult = Apollo.QueryResult<GetUserIdQuery, GetUserIdQueryVariables>;
export type GetUserIdQueryResult = Apollo.QueryResult<GetUserIdQuery, GetUserIdQueryVariables>;
1 change: 1 addition & 0 deletions apps/consent/codegen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,4 @@ generates:
ContactHandle: "string"
ContactType: "string"
ContactDisplayName: "string"
TelegramPassportNonce: "string"
1 change: 1 addition & 0 deletions apps/dashboard/codegen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,4 @@ generates:
ContactHandle: "string"
ContactType: "string"
ContactDisplayName: "string"
TelegramPassportNonce: "string"
23 changes: 23 additions & 0 deletions apps/dashboard/services/graphql/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ export type Scalars = {
SignedAmount: { input: number; output: number; }
/** A string amount (of a currency) that can be negative (e.g. in a transaction) */
SignedDisplayMajorAmount: { input: string; output: string; }
/** Nonce provided by Telegram Passport to validate the login/upgrade flow */
TelegramPassportNonce: { input: string; output: string; }
/** Timestamp field, serialized as Unix time (the number of seconds since the Unix epoch) */
Timestamp: { input: number; output: number; }
/** A time-based one-time password */
Expand Down Expand Up @@ -1143,6 +1145,7 @@ export type Mutation = {
readonly userEmailRegistrationValidate: UserEmailRegistrationValidatePayload;
readonly userLogin: AuthTokenPayload;
readonly userLoginUpgrade: UpgradePayload;
readonly userLoginUpgradeTelegram: UpgradePayload;
readonly userLogout: SuccessPayload;
readonly userPhoneDelete: UserPhoneDeletePayload;
readonly userPhoneRegistrationInitiate: SuccessPayload;
Expand Down Expand Up @@ -1396,6 +1399,11 @@ export type MutationUserLoginUpgradeArgs = {
};


export type MutationUserLoginUpgradeTelegramArgs = {
input: UserLoginUpgradeTelegramInput;
};


export type MutationUserLogoutArgs = {
input?: InputMaybe<UserLogoutInput>;
};
Expand Down Expand Up @@ -2267,6 +2275,11 @@ export type UserLoginUpgradeInput = {
readonly phone: Scalars['Phone']['input'];
};

export type UserLoginUpgradeTelegramInput = {
readonly nonce: Scalars['TelegramPassportNonce']['input'];
readonly phone: Scalars['Phone']['input'];
};

export type UserLogoutInput = {
readonly deviceToken: Scalars['String']['input'];
};
Expand Down Expand Up @@ -3761,6 +3774,7 @@ export type ResolversTypes = {
SupportChatMessageAddPayload: ResolverTypeWrapper<Omit<SupportChatMessageAddPayload, 'errors'> & { errors: ReadonlyArray<ResolversTypes['Error']> }>;
SupportMessage: ResolverTypeWrapper<SupportMessage>;
SupportRole: SupportRole;
TelegramPassportNonce: ResolverTypeWrapper<Scalars['TelegramPassportNonce']['output']>;
Timestamp: ResolverTypeWrapper<Scalars['Timestamp']['output']>;
TotpCode: ResolverTypeWrapper<Scalars['TotpCode']['output']>;
TotpRegistrationId: ResolverTypeWrapper<Scalars['TotpRegistrationId']['output']>;
Expand All @@ -3785,6 +3799,7 @@ export type ResolversTypes = {
UserEmailRegistrationValidatePayload: ResolverTypeWrapper<Omit<UserEmailRegistrationValidatePayload, 'errors' | 'me'> & { errors: ReadonlyArray<ResolversTypes['Error']>, me?: Maybe<ResolversTypes['User']> }>;
UserLoginInput: UserLoginInput;
UserLoginUpgradeInput: UserLoginUpgradeInput;
UserLoginUpgradeTelegramInput: UserLoginUpgradeTelegramInput;
UserLogoutInput: UserLogoutInput;
UserPhoneDeletePayload: ResolverTypeWrapper<Omit<UserPhoneDeletePayload, 'errors' | 'me'> & { errors: ReadonlyArray<ResolversTypes['Error']>, me?: Maybe<ResolversTypes['User']> }>;
UserPhoneRegistrationInitiateInput: UserPhoneRegistrationInitiateInput;
Expand Down Expand Up @@ -3988,6 +4003,7 @@ export type ResolversParentTypes = {
SupportChatMessageAddInput: SupportChatMessageAddInput;
SupportChatMessageAddPayload: Omit<SupportChatMessageAddPayload, 'errors'> & { errors: ReadonlyArray<ResolversParentTypes['Error']> };
SupportMessage: SupportMessage;
TelegramPassportNonce: Scalars['TelegramPassportNonce']['output'];
Timestamp: Scalars['Timestamp']['output'];
TotpCode: Scalars['TotpCode']['output'];
TotpRegistrationId: Scalars['TotpRegistrationId']['output'];
Expand All @@ -4009,6 +4025,7 @@ export type ResolversParentTypes = {
UserEmailRegistrationValidatePayload: Omit<UserEmailRegistrationValidatePayload, 'errors' | 'me'> & { errors: ReadonlyArray<ResolversParentTypes['Error']>, me?: Maybe<ResolversParentTypes['User']> };
UserLoginInput: UserLoginInput;
UserLoginUpgradeInput: UserLoginUpgradeInput;
UserLoginUpgradeTelegramInput: UserLoginUpgradeTelegramInput;
UserLogoutInput: UserLogoutInput;
UserPhoneDeletePayload: Omit<UserPhoneDeletePayload, 'errors' | 'me'> & { errors: ReadonlyArray<ResolversParentTypes['Error']>, me?: Maybe<ResolversParentTypes['User']> };
UserPhoneRegistrationInitiateInput: UserPhoneRegistrationInitiateInput;
Expand Down Expand Up @@ -4626,6 +4643,7 @@ export type MutationResolvers<ContextType = any, ParentType extends ResolversPar
userEmailRegistrationValidate?: Resolver<ResolversTypes['UserEmailRegistrationValidatePayload'], ParentType, ContextType, RequireFields<MutationUserEmailRegistrationValidateArgs, 'input'>>;
userLogin?: Resolver<ResolversTypes['AuthTokenPayload'], ParentType, ContextType, RequireFields<MutationUserLoginArgs, 'input'>>;
userLoginUpgrade?: Resolver<ResolversTypes['UpgradePayload'], ParentType, ContextType, RequireFields<MutationUserLoginUpgradeArgs, 'input'>>;
userLoginUpgradeTelegram?: Resolver<ResolversTypes['UpgradePayload'], ParentType, ContextType, RequireFields<MutationUserLoginUpgradeTelegramArgs, 'input'>>;
userLogout?: Resolver<ResolversTypes['SuccessPayload'], ParentType, ContextType, Partial<MutationUserLogoutArgs>>;
userPhoneDelete?: Resolver<ResolversTypes['UserPhoneDeletePayload'], ParentType, ContextType>;
userPhoneRegistrationInitiate?: Resolver<ResolversTypes['SuccessPayload'], ParentType, ContextType, RequireFields<MutationUserPhoneRegistrationInitiateArgs, 'input'>>;
Expand Down Expand Up @@ -4967,6 +4985,10 @@ export type SupportMessageResolvers<ContextType = any, ParentType extends Resolv
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};

export interface TelegramPassportNonceScalarConfig extends GraphQLScalarTypeConfig<ResolversTypes['TelegramPassportNonce'], any> {
name: 'TelegramPassportNonce';
}

export interface TimestampScalarConfig extends GraphQLScalarTypeConfig<ResolversTypes['Timestamp'], any> {
name: 'Timestamp';
}
Expand Down Expand Up @@ -5304,6 +5326,7 @@ export type Resolvers<ContextType = any> = {
SuccessPayload?: SuccessPayloadResolvers<ContextType>;
SupportChatMessageAddPayload?: SupportChatMessageAddPayloadResolvers<ContextType>;
SupportMessage?: SupportMessageResolvers<ContextType>;
TelegramPassportNonce?: GraphQLScalarType;
Timestamp?: GraphQLScalarType;
TotpCode?: GraphQLScalarType;
TotpRegistrationId?: GraphQLScalarType;
Expand Down
1 change: 1 addition & 0 deletions apps/map/codegen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,4 @@ generates:
ContactHandle: "string"
ContactType: "string"
ContactDisplayName: "string"
TelegramPassportNonce: "string"
15 changes: 14 additions & 1 deletion apps/map/services/galoy/graphql/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ export type Scalars = {
SignedAmount: { input: number; output: number; }
/** A string amount (of a currency) that can be negative (e.g. in a transaction) */
SignedDisplayMajorAmount: { input: string; output: string; }
/** Nonce provided by Telegram Passport to validate the login/upgrade flow */
TelegramPassportNonce: { input: string; output: string; }
/** Timestamp field, serialized as Unix time (the number of seconds since the Unix epoch) */
Timestamp: { input: number; output: number; }
/** A time-based one-time password */
Expand Down Expand Up @@ -1045,6 +1047,7 @@ export type Mutation = {
readonly userEmailRegistrationValidate: UserEmailRegistrationValidatePayload;
readonly userLogin: AuthTokenPayload;
readonly userLoginUpgrade: UpgradePayload;
readonly userLoginUpgradeTelegram: UpgradePayload;
readonly userLogout: SuccessPayload;
readonly userPhoneDelete: UserPhoneDeletePayload;
readonly userPhoneRegistrationInitiate: SuccessPayload;
Expand Down Expand Up @@ -1283,6 +1286,11 @@ export type MutationUserLoginUpgradeArgs = {
};


export type MutationUserLoginUpgradeTelegramArgs = {
input: UserLoginUpgradeTelegramInput;
};


export type MutationUserLogoutArgs = {
input?: InputMaybe<UserLogoutInput>;
};
Expand Down Expand Up @@ -2078,6 +2086,11 @@ export type UserLoginUpgradeInput = {
readonly phone: Scalars['Phone']['input'];
};

export type UserLoginUpgradeTelegramInput = {
readonly nonce: Scalars['TelegramPassportNonce']['input'];
readonly phone: Scalars['Phone']['input'];
};

export type UserLogoutInput = {
readonly deviceToken: Scalars['String']['input'];
};
Expand Down Expand Up @@ -2360,4 +2373,4 @@ export function useBusinessMapMarkersSuspenseQuery(baseOptions?: Apollo.SkipToke
export type BusinessMapMarkersQueryHookResult = ReturnType<typeof useBusinessMapMarkersQuery>;
export type BusinessMapMarkersLazyQueryHookResult = ReturnType<typeof useBusinessMapMarkersLazyQuery>;
export type BusinessMapMarkersSuspenseQueryHookResult = ReturnType<typeof useBusinessMapMarkersSuspenseQuery>;
export type BusinessMapMarkersQueryResult = Apollo.QueryResult<BusinessMapMarkersQuery, BusinessMapMarkersQueryVariables>;
export type BusinessMapMarkersQueryResult = Apollo.QueryResult<BusinessMapMarkersQuery, BusinessMapMarkersQueryVariables>;
1 change: 1 addition & 0 deletions apps/pay/codegen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,4 @@ generates:
ContactHandle: "string"
ContactType: "string"
ContactDisplayName: "string"
TelegramPassportNonce: "string"
15 changes: 14 additions & 1 deletion apps/pay/lib/graphql/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ export type Scalars = {
SignedAmount: { input: number; output: number; }
/** A string amount (of a currency) that can be negative (e.g. in a transaction) */
SignedDisplayMajorAmount: { input: string; output: string; }
/** Nonce provided by Telegram Passport to validate the login/upgrade flow */
TelegramPassportNonce: { input: string; output: string; }
/** Timestamp field, serialized as Unix time (the number of seconds since the Unix epoch) */
Timestamp: { input: number; output: number; }
/** A time-based one-time password */
Expand Down Expand Up @@ -1046,6 +1048,7 @@ export type Mutation = {
readonly userEmailRegistrationValidate: UserEmailRegistrationValidatePayload;
readonly userLogin: AuthTokenPayload;
readonly userLoginUpgrade: UpgradePayload;
readonly userLoginUpgradeTelegram: UpgradePayload;
readonly userLogout: SuccessPayload;
readonly userPhoneDelete: UserPhoneDeletePayload;
readonly userPhoneRegistrationInitiate: SuccessPayload;
Expand Down Expand Up @@ -1284,6 +1287,11 @@ export type MutationUserLoginUpgradeArgs = {
};


export type MutationUserLoginUpgradeTelegramArgs = {
input: UserLoginUpgradeTelegramInput;
};


export type MutationUserLogoutArgs = {
input?: InputMaybe<UserLogoutInput>;
};
Expand Down Expand Up @@ -2079,6 +2087,11 @@ export type UserLoginUpgradeInput = {
readonly phone: Scalars['Phone']['input'];
};

export type UserLoginUpgradeTelegramInput = {
readonly nonce: Scalars['TelegramPassportNonce']['input'];
readonly phone: Scalars['Phone']['input'];
};

export type UserLogoutInput = {
readonly deviceToken: Scalars['String']['input'];
};
Expand Down Expand Up @@ -3016,4 +3029,4 @@ export function usePriceSubscription(baseOptions: Apollo.SubscriptionHookOptions
return Apollo.useSubscription<PriceSubscription, PriceSubscriptionVariables>(PriceDocument, options);
}
export type PriceSubscriptionHookResult = ReturnType<typeof usePriceSubscription>;
export type PriceSubscriptionResult = Apollo.SubscriptionResult<PriceSubscription>;
export type PriceSubscriptionResult = Apollo.SubscriptionResult<PriceSubscription>;
19 changes: 19 additions & 0 deletions bats/core/api/auth.bats
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ generateTotpCode() {
curl_request "http://${GALOY_ENDPOINT}/auth/telegram-passport/request-params" "$variables"
nonce=$(curl_output '.nonce')
[ -n "$nonce" ] || exit 1
cache_value "telegram.nonce" "$nonce"

# Step 2: Try to login with the nonce before Telegram Passport webhook is called
variables="{\"nonce\": \"$nonce\", \"phone\": \"$phone\"}"
Expand Down Expand Up @@ -186,6 +187,24 @@ generateTotpCode() {
[[ "$error" =~ "Invalid nonce $nonce" ]] || exit 1
}

@test "auth: telegram upgrade fails with used nonce" {
local phone="$(read_value diana.phone)"
local nonce="$(read_value telegram.nonce)"

variables=$(
jq -n \
--arg phone "$phone" \
--arg nonce "$nonce" \
'{input: {phone: $phone, nonce: $nonce}}'
)

exec_graphql 'diana' 'user-login-upgrade-telegram' "$variables"

[[ "$(graphql_output '.data.userLoginUpgradeTelegram.success')" == "false" ]] || exit 1
[[ "$(graphql_output '.data.userLoginUpgradeTelegram.errors[0].code')" == "NOT_FOUND" ]] || exit 1
[[ "$(graphql_output '.data.userLoginUpgradeTelegram.errors[0].message')" == "Invalid nonce ${nonce}" ]] || exit 1
}

@test "auth: remove phone login" {
email=$(read_value 'charlie.email')

Expand Down
78 changes: 78 additions & 0 deletions bats/core/api/device-account.bats
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
load "../../helpers/_common.bash"
load "../../helpers/cli.bash"
load "../../helpers/user.bash"
load "../../helpers/telegram.bash"

setup_file() {
clear_cache
}

DEVICE_NAME="device-user"

Expand Down Expand Up @@ -46,6 +51,32 @@ jwt="eyJhbGciOiJSUzI1NiIsImtpZCI6IjFiOTdiMjIxLWNhMDgtNGViMi05ZDA5LWE1NzcwZmNjZWI
[[ "$refetched_account_id" == "$account_id" ]] || exit 1
}

@test "device-account: upgrade fails if phone already exists" {
token_name="$DEVICE_NAME"

create_user 'fran'
phone_number="$(read_value fran.phone)"

code="000000"
variables=$(
jq -n \
--arg phone "$phone_number" \
--arg code "$code" \
'{input: {phone: $phone, code: $code}}'
)
exec_graphql "$token_name" 'user-login-upgrade' "$variables"

err_code="$(graphql_output '.data.userLoginUpgrade.errors[0].code')"
if [[ "$err_code" != "PHONE_ALREADY_ATTACHED_ERROR" ]]; then
echo "Unexpected error code: $err_code"
exit 1
fi

exec_graphql "$token_name" 'account-details'
level="$(graphql_output '.data.me.defaultAccount.level')"
[[ "$level" == "ZERO" ]] || exit 1
}

@test "device-account: upgrade" {
token_name="$DEVICE_NAME"
code="000000"
Expand Down Expand Up @@ -78,3 +109,50 @@ jwt="eyJhbGciOiJSUzI1NiIsImtpZCI6IjFiOTdiMjIxLWNhMDgtNGViMi05ZDA5LWE1NzcwZmNjZWI
delete_success="$(graphql_output '.data.accountDelete.success')"
[[ "$delete_success" == "true" ]] || exit 1
}

@test "device-account: telegram upgrade success" {
#
# TODO: Remove skip method
#
skip
local token_name="device-user-telegram"
local appcheck_header="Appcheck: $jwt"

local username="$(random_uuid)"
local password="$(random_uuid)"
local basic_token="$(echo -n $username:$password | base64 -w 0)"
local auth_header="Authorization: Basic $basic_token"

curl_request "$url" "" "$auth_header" "$appcheck_header"
local new_token="$(echo $output | jq -r '.result')"
[[ "$new_token" != "null" && -n "$new_token" ]] || exit 1
cache_value "$token_name" "$new_token"

exec_graphql "$token_name" 'account-details'
[[ "$(graphql_output '.data.me.defaultAccount.level')" == "ZERO" ]] || exit 1

# Request nonce
local phone="$(random_phone)"
cache_value "$token_name.phone" "$phone"
curl_request "http://${GALOY_ENDPOINT}/auth/telegram-passport/request-params" "{\"phone\":\"$phone\"}"
local nonce="$(curl_output '.nonce')"
[ -n "$nonce" ] || exit 1

# Pending before webhook
local variables=$(
jq -n \
--arg phone "$phone" \
--arg nonce "$nonce" \
'{input: {phone: $phone, nonce: $nonce}}'
)
exec_graphql "$token_name" 'user-login-upgrade-telegram' "$variables"
[[ "$(graphql_output '.data.userLoginUpgradeTelegram.success')" == "false" ]] || exit 1

simulateTelegramPassportWebhook "$nonce" "${phone//+/}"

exec_graphql "$token_name" 'user-login-upgrade-telegram' "$variables"
[[ "$(graphql_output '.data.userLoginUpgradeTelegram.success')" == "true" ]] || exit 1

exec_graphql "$token_name" 'account-details'
[[ "$(graphql_output '.data.me.defaultAccount.level')" == "ONE" ]] || exit 1
}
Loading
Loading