A JWT is three base64url-encoded pieces separated by dots: a header that names the signing algorithm, a payload of claims (who the user is, when the token expires, any custom data you've attached), and a signature that proves the token was issued by someone who holds the signing key. Anyone can read a JWT; only the issuer can produce one with a valid signature.
Firebase Authentication issues a JWT every time a user signs in and refreshes it roughly every hour. The token is what your backend reads to know which user made a request, and the signature is what stops a malicious client from forging an identity. The refresh token, which is longer-lived, sits separately and is only sent to Firebase itself to mint new JWTs.
The most common mistake with JWTs is treating them as an authorisation surface. The token confirms identity; what that user is allowed to do is a separate decision your code makes by reading the claims. Stuffing too many claims into a JWT is also a classic anti-pattern — the token gets large, every request pays the cost, and revoking a single permission requires reissuing every active token.