Skip to content

Conversation

@elct9620
Copy link

Related Issue or Design Document

I am working on an internal OAuth2 server that needs to sign JWTs using AWS KMS.

However, the jwt.DefaultSigner doesn't work correctly. It is caused by checking the public key against the private key type.

fosite/token/jwt/jwt.go

Lines 58 to 79 in 8052806

case jose.OpaqueSigner:
switch tt := t.Public().Key.(type) {
case *rsa.PrivateKey:
alg := jose.RS256
if len(t.Algs()) > 0 {
alg = t.Algs()[0]
}
return generateToken(claims, header, alg, t)
case *ecdsa.PrivateKey:
alg := jose.ES256
if len(t.Algs()) > 0 {
alg = t.Algs()[0]
}
return generateToken(claims, header, alg, t)
default:
return "", "", errors.Errorf("unsupported private / public key pairs: %T, %T", t, tt)
}
default:
return "", "", errors.Errorf("unsupported private key type: %T", t)
}

If I provide a jose.OpaqueSigner wrapper to the AWS KMS, it will get this error

Error creating access response: unsupported private / public key pairs: *example.KmsSigner, *rsa.PublicKey

To fix it, I change PrivateKey to PublicKey and add new test case to cover it.

Checklist

  • I have read the contributing guidelines and signed the CLA.
  • I have referenced an issue containing the design document if my change introduces a new feature.
  • I have read the security policy.
  • I confirm that this pull request does not address a security vulnerability.
    If this pull request addresses a security vulnerability,
    I confirm that I got approval (please contact [email protected]) from the maintainers to push the changes.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added the necessary documentation within the code base (if appropriate).

Further comments

@elct9620 elct9620 requested review from a team and aeneasr as code owners June 20, 2025 06:37
@mitar mitar mentioned this pull request Jun 26, 2025
6 tasks
@mitar
Copy link
Contributor

mitar commented Jul 1, 2025

Please rebase from latest master branch to fix CI issues.

@elct9620 elct9620 force-pushed the fix/invalid-opaque-signer branch from f93ad3f to 30359ec Compare July 1, 2025 12:53
@elct9620
Copy link
Author

elct9620 commented Jul 1, 2025

@mitar done 💪

Copy link
Member

@aeneasr aeneasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To create a JWT you need a private key to sign it

To verify a JWT you need the public key to verify the signature

This change will break that

@elct9620
Copy link
Author

elct9620 commented Jul 3, 2025

Hi, @aeneasr

Can you explain more details about it?

The jose.OpaqueSigner have following interface:

type OpaqueSigner interface {
	// Public returns the public key of the current signing key.
	Public() *JSONWebKey
	// Algs returns a list of supported signing algorithms.
	Algs() []SignatureAlgorithm
	// SignPayload signs a payload with the current signing key using the given
	// algorithm.
	SignPayload(payload []byte, alg SignatureAlgorithm) ([]byte, error)
}

It means we only know the public key but cannot access the private key (stored on HSM or remote service, e.g., AWS KMS)

I changed the type from PrivateKey to PublicKey because we do not have any private key in our memory, and the Generate method uses t.Public().Key.(type) to get its type.

It enables the correct detection of the key type and continues to generate the key. After the key is signed by HSM, we are still able to use t.Public() to get the public key to verify it.

This change only applies to Generate to allow it can choose the correct alg type, I think it does not break the Validate method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants