When you write
person * myperson = malloc(sizeof(person));
it allocates memory for the myperson variable (pointer), i.e, for the myperson->name and myperson->age member variable themselves.
The memory location, pointed by myperson->name (being a pointer), is not valid, till time. In other words, myperson->name itself is a valid access, but the moment you try to use the content of the memory location pointed by myperson->name, it'll be UB as the pointer value is indeternminate. You need to allocate memory separately to the pointer.
Following that,
myperson->name = "John";
is valid, as you're storing the starting address of the string literal "John" to the pointer. After this you can use the pointer content. (Remember, as myperson->name point to a string literal, you may not change it.)
To extend this answer, let me state, if you want to copy a string into the memory location pointed by myperson->name, then, first, you need to allocate memory to myperson->name first. For example,
myperson->name = malloc(32); //allocate memory
strcpy(myperson->name, "Hello"); //write to that memory