github.com/golang-jwt/jwt/v5 разбирает, проверяет и подписывает JWT ключами из стандартной библиотеки: []byte для HMAC, *rsa.PublicKey, *ecdsa.PublicKey и ed25519.PublicKey. В версии 5.3.1 подпись и проверка работали для семейств HS, RS, PS и ES, а также для EdDSA; для ES256K и полностью определённых имён Ed25519 и Ed448 зарегистрированного метода подписи нет.
Проверка целиком зависит от функции keyfunc, которую вы передаёте в jwt.Parse. Каждый метод подписи проверяет тип Go полученного ключа, поэтому с keyfunc, возвращающей *ecdsa.PublicKey, токен RS256 отклонён с ошибкой RSA verify expects *rsa.PublicKey, а токен HS256, подписанный текстом PEM в качестве ключа, — с ошибкой HMAC verify expects []byte. Защита исчезает, если keyfunc возвращает сырые байты для любого токена: с keyfunc, которая загружает PEM-файл как []byte, этот поддельный токен HS256 в ходе проверки был принят. Передавайте jwt.WithValidMethods с конкретным алгоритмом и оставляйте keyfunc типизированной, как в примере.
Токен с alg: none проходит проверку, только если keyfunc возвращает сигнальное значение jwt.UnsafeAllowNoneSignatureType; с любым настоящим ключом возникает ошибка 'none' signature type is not allowed. ES256 отказывается подписывать ключом P-384 и выдаёт лишь краткое key is invalid. Подписи ES256 — это 64-байтовый формат raw r‖s, которого требует JWS; подпись DER не проходит проверку с ошибкой crypto/ecdsa: verification error, а найти причину помогут отладчик JWT и конвертер DER ⇄ raw.
В v5 проверка утверждений включена по умолчанию, но exp необязателен (токен без него действителен вечно), а допуска на расхождение часов нет. Эти пробелы закрывают jwt.WithExpirationRequired(), jwt.WithIssuer, jwt.WithAudience и jwt.WithLeeway; ошибки можно сопоставлять через errors.Is(err, jwt.ErrTokenExpired), а не сравнивать строки.
Чтобы проверять токены от поставщика удостоверений, используйте пакет вместе с клиентом JWKS, а что именно публикует поставщик, покажет проверка JWKS; если нужна работа с JWE или JWK, альтернатива — go-jose.