11defmodule WikWeb.TelegramAuthController do
22 use WikWeb , :controller
3- alias Wik.User
4- @ login_ttl :timer . hours ( 24 )
3+ alias Wik.Telegram
54 require Logger
65
7- defp bot_token , do: Application . get_env ( :wik , :bot_token )
8-
9- def callback ( conn , params ) do
10- # params is a map with Telegram authentication data:
11- # e.g. %{"id" => "...", "first_name" => "...", "auth_date" => "...", "hash" => "..."}
12-
13- if valid_telegram_auth? ( params , false ) do
14- user =
15- User . get_or_create_from_telegram ( params , bot_token ( ) )
16- |> Map . delete ( "hash" )
17- |> Map . delete ( "auth_date" )
18-
19- Wik.Users . persist_session_user ( user )
6+ def callback ( conn , telegram_callback_response ) do
7+ if Telegram . valid_telegram_auth? ( telegram_callback_response , false ) do
8+ session_user = make_session_user ( telegram_callback_response )
209
2110 conn
22- |> put_session ( :user , user )
11+ |> put_session ( :user , session_user )
2312 |> configure_session ( renew: true )
2413 |> redirect ( to: get_session ( conn , :redirect_after_login ) || "/" )
2514 else
15+ Logger . error ( "Invalid Telegram login" )
16+
2617 conn
2718 |> put_flash ( :error , "Invalid Telegram login" )
2819 |> redirect ( to: "/" )
@@ -32,15 +23,17 @@ defmodule WikWeb.TelegramAuthController do
3223 def miniapp ( conn , _params ) do
3324 with [ "tma " <> init_data_raw ] <- get_req_header ( conn , "authorization" ) ,
3425 params <- URI . decode_query ( init_data_raw ) ,
35- true <- valid_telegram_auth? ( params , true ) do
36- { :ok , params } = JSON . decode ( params [ "user" ] )
26+ true <- Telegram . valid_telegram_auth? ( params , true ) do
27+ { :ok , telegram_callback_response } = JSON . decode ( params [ "user" ] )
3728
38- user = User . get_or_create_from_telegram ( params , bot_token ( ) )
39- Wik.Users . persist_session_user ( user )
29+ session_user = make_session_user ( telegram_callback_response )
4030
4131 conn
42- |> put_session ( :user , user )
43- |> put_flash ( :info , "Welcome #{ user . first_name } #{ user . last_name } (#{ user . username } )!" )
32+ |> put_session ( :user , session_user )
33+ |> put_flash (
34+ :info ,
35+ "Welcome #{ session_user . first_name } #{ session_user . last_name } (#{ session_user . username } )!"
36+ )
4437 |> json ( % { success: true } )
4538 else
4639 _ ->
@@ -52,53 +45,23 @@ defmodule WikWeb.TelegramAuthController do
5245 end
5346 end
5447
55- defp valid_telegram_auth? ( params , miniapp? ) do
56- # Get the received hash from params and remove it from the map.
57- check_hash = Map . get ( params , "hash" ) |> String . downcase ( )
58-
59- # Compute the secret key: SHA256(bot_token) in binary.
60- secret_key =
61- if miniapp? do
62- :crypto . mac ( :hmac , :sha256 , "WebAppData" , bot_token ( ) )
63- else
64- :crypto . hash ( :sha256 , bot_token ( ) )
65- end
66-
67- # Create the data-check string.
68- data_check_string =
69- params
70- |> Map . delete ( "hash" )
71- |> Enum . map ( fn { k , v } -> "#{ k } =#{ v } " end )
72- |> Enum . sort ( )
73- |> Enum . join ( "\n " )
48+ def make_session_user ( res ) do
49+ telegram_user_data = % {
50+ telegram_id: "#{ res [ "id" ] } " ,
51+ first_name: res [ "first_name" ] ,
52+ last_name: res [ "last_name" ] ,
53+ auth_date: res [ "auth_date" ] ,
54+ username: res [ "username" ] ,
55+ photo_url: res [ "photo_url" ]
56+ }
7457
75- # Compute the HMAC-SHA256 of the data-check string with the secret key.
76- computed_hash =
77- :crypto . mac ( :hmac , :sha256 , secret_key , data_check_string )
78- |> Base . encode16 ( case: :lower )
79- |> String . downcase ( )
58+ { :ok , dbuser } = Wik.Users . create_or_update_user_by_telegram_id ( telegram_user_data )
8059
81- # Optionally, check that the authentication is not older than 24 hours.
82- auth_date =
83- case Map . get ( params , "auth_date" ) do
84- nil -> 0
85- date when is_binary ( date ) -> String . to_integer ( date )
86- date when is_integer ( date ) -> date
87- end
60+ session_user =
61+ telegram_user_data
62+ |> Map . put ( :id , dbuser . id )
63+ |> Map . put ( :member_of , Telegram . fetch_user_groups ( res [ "id" ] ) )
8864
89- current_time = System . os_time ( :second )
90-
91- outdated? = current_time - auth_date > @ login_ttl
92-
93- cond do
94- computed_hash != check_hash ->
95- false
96-
97- outdated? ->
98- false
99-
100- true ->
101- true
102- end
65+ session_user
10366 end
10467end
0 commit comments