Normally, this would be a job for join. However, join requires sorted input and sort will put numbers before letters in all locales I am aware of (please correct me if that's not true). So join can only get you part of the way there:
$ join -t';' <(sort fileA) <(sort fileB)
1;"sam";"khon"
id;name;surname
You could get around this by joining the the first line of each file first and then the rest:
$ join -t';' <(head -n1 fileA) <(head -n1 fileB)
id;name;surname
$ join -t';' <(tail -n+2 fileA | sort) <(tail -n+2 fileB | sort)
1;"sam";"khon"
Then, grouping these in a subshell and redirecting the output gives you your desired output:
$ ( join -t';' <(head -n1 fileA) <(head -n1 fileB); join -t';' <(tail -n+2 fileA | sort) <(tail -n+2 fileB | sort))
id;name;surname
1;"sam";"khon"
So you could do this:
(
join -t';' <(head -n1 fileA) <(head -n1 fileB);
join -t';' <(tail -n+2 fileA | sort) <(tail -n+2 fileB | sort)
) > file3
Alternatively, you can indeed do it in awk:
$ awk -F';' '(NR==FNR){data[$1]=$1";"$2; next}
($1 in data){print data[$1]";"$2}' fileA fileB
id;name;surname
1;"sam";"khon"