- Опубликовано 27.07.2020 12:10
- Просмотров: 7738
Переписываем JWKS c PHP на GoLang, openssl_pkey_get_details
Не так давно по работе появилась необходимость переписать проект c PHP на GoLang. Одной из подзадач стало написание хендлера обслуживающего JWKS endpoint. И если для PHP всё было просто и понятно, то для Go пришлось повозиться.
Рассусоливать смысла не вижу, по этому далее приведу примеры кода хендлеров как они могли бы выглядеть. Разумеется в реальности они выглядят сложнее.
Итак, на PHP:
use Lcobucci\JWT\Parsing\Encoder;
public function handle(ServerRequestInterface $request): ResponseInterface
{
$publicKey = openssl_pkey_get_public(file_get_contents(getcwd() . '/data/public.key'));
$details = openssl_pkey_get_details($publicKey);
$encoder = new Encoder();
return new JsonResponse([
'keys' => [
[
'kty' => 'RSA',
'e' => $encoder->base64UrlEncode($details['rsa']['e']),
'kid' => 'rsa1',
'alg' => 'RS256',
'n' => $encoder->base64UrlEncode($details['rsa']['n']),
'use' => 'sig',
],
],
]);
}
И тоже самое на Golang
type JWKSStruct struct {
Keys []JWKSStructKey `json:"keys"`
}
type JWKSStructKey struct {
Kty string `json:"kty"`
E string `json:"e"`
Kid string `json:"kid"`
Alg string `json:"alg"`
N string `json:"n"`
Use string `json:"use"`
}
func JWKS(responseWriter http.ResponseWriter, request *http.Request, publicKey *rsa.PublicKey) {
if request.Method != http.MethodGet {
http.Error(responseWriter, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
return
}
responseWriter.Header().Set("Content-Type", "application/json; charset=utf-8")
eBytes := make([]byte, 4, 4)
binary.LittleEndian.PutUint32(eBytes, uint32(publicKey.E))
key := JWKSStructKey{
Kty: "RSA",
E: base64.RawURLEncoding.EncodeToString(eBytes[:3]),
Kid: "rsa1",
Alg: "RS256",
N: base64.RawURLEncoding.EncodeToString(publicKey.N.Bytes()),
Use: "sig",
}
err := json.NewEncoder(responseWriter).Encode(JWKSStruct{Keys: []JWKSStructKey{key}})
if err != nil {
http.Error(responseWriter, err.Error(), http.StatusInternalServerError)
}
}
На выходе получаем один и тот же JSON ответ.
С стандартом можно познакомиться, например здесь: tools.ietf.org/html/rfc7518
Надеюсь кому-то поможет.