authorize: include "kid" in JWT header (#1049)

Fixes #1046
This commit is contained in:
Cuong Manh Le 2020-07-09 12:39:53 +07:00 committed by GitHub
parent 6f3817aee5
commit d40f294586
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 3 deletions

View file

@ -44,6 +44,7 @@ type Evaluator struct {
clientCA string
authenticateHost string
jwk interface{}
kid string
}
// New creates a new Evaluator.
@ -77,11 +78,16 @@ func New(options *config.Options) (*Evaluator, error) {
if err != nil {
return nil, fmt.Errorf("authorize: failed to decode certificate cert %v: %w", decodedCert, err)
}
keyBytes, err := cryptutil.DecodePrivateKey((decodedCert))
key, err := cryptutil.DecodePrivateKey(decodedCert)
if err != nil {
return nil, fmt.Errorf("authorize: couldn't generate signing key: %w", err)
}
e.jwk = keyBytes
e.jwk = key
jwk, err := cryptutil.PublicJWKFromBytes(decodedCert, jose.ES256)
if err != nil {
return nil, fmt.Errorf("authorize: failed to convert jwk: %w", err)
}
e.kid = jwk.KeyID
}
authzPolicy, err := readPolicy("/authz.rego")
@ -163,10 +169,11 @@ func (e *Evaluator) ParseSignedJWT(signature string) ([]byte, error) {
// SignedJWT returns the signature of given request.
func (e *Evaluator) SignedJWT(req *Request) (string, error) {
signerOpt := &jose.SignerOptions{}
signer, err := jose.NewSigner(jose.SigningKey{
Algorithm: jose.ES256,
Key: e.jwk,
}, nil)
}, signerOpt.WithHeader("kid", e.kid))
if err != nil {
return "", err
}

View file

@ -12,6 +12,7 @@ import (
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/square/go-jose.v2/jwt"
"github.com/pomerium/pomerium/config"
"github.com/pomerium/pomerium/pkg/grpc/databroker"
@ -88,6 +89,28 @@ func TestEvaluator_SignedJWT(t *testing.T) {
assert.NotEmpty(t, payload)
}
func TestEvaluator_JWTWithKID(t *testing.T) {
opt := config.NewDefaultOptions()
opt.AuthenticateURL = mustParseURL("https://authenticate.example.com")
opt.SigningKey = "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUpCMFZkbko1VjEvbVlpYUlIWHhnd2Q0Yzd5YWRTeXMxb3Y0bzA1b0F3ekdvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVUc1eENQMEpUVDFINklvbDhqS3VUSVBWTE0wNENnVzlQbEV5cE5SbVdsb29LRVhSOUhUMwpPYnp6aktZaWN6YjArMUt3VjJmTVRFMTh1dy82MXJVQ0JBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="
e, err := New(opt)
require.NoError(t, err)
req := &Request{
HTTP: RequestHTTP{
Method: http.MethodGet,
URL: "https://example.com",
},
}
signedJWT, err := e.SignedJWT(req)
require.NoError(t, err)
assert.NotEmpty(t, signedJWT)
tok, err := jwt.ParseSigned(signedJWT)
require.NoError(t, err)
require.Len(t, tok.Headers, 1)
assert.Equal(t, "5b419ade1895fec2d2def6cd33b1b9a018df60db231dc5ecb85cbed6d942813c", tok.Headers[0].KeyID)
}
func mustParseURL(str string) *url.URL {
u, err := url.Parse(str)
if err != nil {