Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable integration with third-party signing #93

Closed
udf2457 opened this issue Jun 1, 2016 · 23 comments
Closed

Enable integration with third-party signing #93

udf2457 opened this issue Jun 1, 2016 · 23 comments
Assignees

Comments

@udf2457
Copy link

udf2457 commented Jun 1, 2016

For those people who may use cloud-based security infrastructure (e.g. Azure Keyvault HSM, Amazon AWS HSM), there is no way to integrate signing with lcobucci/jwt because, for example, your code presently requires people to supply the path to the private key on the local filesystem.

For avoidance of doubt, I am not saying that you need to code all the API communications ! I am just saying, give me an easy way to (a) get the "string to sign" and (b) supply the signed value back to lcobucci/jwt .... the "black-box" magic in the middle can be done by people's code.

Hope this makes sense.

@geggleto
Copy link

geggleto commented Jun 1, 2016

@udf2457 so all we need to do is change the Key class to accept a string that you can generate yourself ?

@lcobucci lcobucci self-assigned this Jun 1, 2016
@udf2457
Copy link
Author

udf2457 commented Jun 1, 2016

@geggleto Sounds about right.

(I'm guessing the function to retrieve payload/string to sign is already marked public, if not it will need to be).

@lcobucci
Copy link
Owner

lcobucci commented Jun 1, 2016

As you can see on https://github.com/lcobucci/jwt/blob/3.1/src/Signer/Key.php#L45 we already allow strings on constructors, so you can do the "black-box" magic and create a new Key.

The file:// is not expected but was just added to don't break BC after the Key class was introduced.

@geggleto
Copy link

geggleto commented Jun 1, 2016

@udf2457

For branch 2.1

if you look at... https://github.com/lcobucci/jwt/blob/2.1/src/Builder.php#L213-L223
You can see the signature of sign accepts a (string) for the key...

Same thing for verifying...
https://github.com/lcobucci/jwt/blob/2.1/src/Token.php#L136-L143

@lcobucci
Copy link
Owner

lcobucci commented Jun 1, 2016

@geggleto v2 was discontinued and should not be used due to security reasons.

@lcobucci
Copy link
Owner

lcobucci commented Jun 1, 2016

@udf2457 for now you can fetch your string while creating the Key object and after we have #32 (on v4) you'll be able to user external URLs to create tokens.

@geggleto
Copy link

geggleto commented Jun 1, 2016

@lcobucci ah okay, noted.

@udf2457
Copy link
Author

udf2457 commented Jun 1, 2016

@lcobucci Am a little confused about your reference to https://github.com/lcobucci/jwt/blob/3.1/src/Signer/Key.php#L45, isn't that used for providing a Key not a signed string ?

@geggleto
Copy link

geggleto commented Jun 1, 2016

@udf2457 if your Content does not contain the string file:// it is treated as a string and will not load the file.

@lcobucci
Copy link
Owner

lcobucci commented Jun 1, 2016

@udf2457 exactly as @geggleto explained 😉

// You can create:
$key = new Key('file:///test/private_key.pem');
// or:
$key = new Key(file_get_contents('/test/private_key.pem'));
// or: (with the right line endings)
$key = new Key('-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDdlatRjRjogo3Wojg...');

If you need more power you could even do:

final class KeyVaultObject
{
     public function __toString():string
     {
         // Your black magic here
         return 'black magic result';
     }
}

$key = new Key(new KeyVaultObject('identifier'));

@udf2457
Copy link
Author

udf2457 commented Jun 1, 2016

@geggleto @lcobucci So, just to be sure, based on the example code on your homepage that this sort of thing will work as intended ?

$get_the_string_to_sign= $jwt_instance->getPayload(); // or whatever the function 
//
// send stuff to azure.....
//
$signer = $config->getSigner();
$azureResult = "the_result_signature_text_after_I_sent_stringtosign_to_azure_api" ;
$token = $config->createBuilder()
                ->setIssuer('http://example.com') // Configures the issuer (iss claim)
                // etc. etc.
                ->sign($signer,  $azureResult ) // creates a signature using your private key
                ->getToken(); // Retrieves the generated token

@udf2457
Copy link
Author

udf2457 commented Jun 1, 2016

// You can create: $key = new Key('file:///test/private_key.pem'); // or: $key = new Key(file_get_contents('/test/private_key.pem')); // or: (with the right line endings) $key = new Key('-----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQDdlatRjRjogo3Wojg...');

Yes, but surely this is exactly the problem I'm telling you ? ;-)

The cloudy stuff is HSM.... i.e. once in the HSM, the private key never emerges. You can only ever ask it to "sign,decrypt,verify,encrypt" .... the private key stays locked-up inside the HSM at all times, the only key you can view is the public key.

@geggleto
Copy link

geggleto commented Jun 1, 2016

I ended up writing my own wrapper around it... https://github.com/geggleto/securejwt required libsodium tho

@udf2457
Copy link
Author

udf2457 commented Jun 1, 2016

I ended up writing my own wrapper around it... required libsodium tho

Alright, this is getting silly now.

I've got nothing against the great libsodium, but surely I don't need it to be able to concatenate a ready-made signature onto a JWT token (I'm no JWT guru but I'm guessing that's how it works !)

@lcobucci
Copy link
Owner

lcobucci commented Jun 1, 2016

@udf2457 ok so your problem is not about with the Key creation at all. You actually need a customized Signer.

For that you just need to implement the Signer interface (https://github.com/lcobucci/jwt/blob/3.1/src/Signer.php) and do your black magic there. The BaseSigner (https://github.com/lcobucci/jwt/blob/3.1/src/Signer/BaseSigner.php) can be used to help you.

I have no intention on providing customized signers in this package but you can create one that has this lib as dependency and adds a HSM signer (which can be useful to others). I'll gladly put your package as suggestion of this lib.

@udf2457
Copy link
Author

udf2457 commented Jun 1, 2016

@lcobucci ok, I'll take a look at the interfaces suggested.

@lcobucci
Copy link
Owner

lcobucci commented Jun 1, 2016

@udf2457 don't forget to use the stable version as dependency as master is meant for the next major release and it's API WILL CHANGE.

@udf2457 udf2457 closed this as completed Jun 1, 2016
@lcobucci
Copy link
Owner

lcobucci commented Jun 1, 2016

Will mark this as wontfix since is out of scope of this package, but please create your signer on a new repository and mention me on a PR if need any help 😄

@omitobi
Copy link

omitobi commented Nov 15, 2023

Does anyone have a solution to this particular issue? I am currently in the same situation.

@lcobucci
Copy link
Owner

Does anyone have a solution to this particular issue? I am currently in the same situation.

@omitobi delegating the signing process to an external component can be achieved by implementing a custom algorithm (signer): https://lcobucci-jwt.readthedocs.io/en/stable/extending-the-library/#signer

If this doesn't clarify it enough, please open a discussion (not issue) asking a more detailed question 👍

@fredericgboutin-yapla
Copy link

fredericgboutin-yapla commented Apr 15, 2024

I mean, @omitobi is kind of right. The original issue is still valid: Enable integration with third-party signing

Yes, there is a workaround so you can hack you way. But I'm in a situation were I would like to leverage AWS KMS. Obviously I would have preferred if someone else had already developed and tested that support.

The point is, lcobucci/jwt needs something more integrated or supported or "pluggable" so we can sign JWT with different services were we don't have access to the private key by design but only an API.

@SvenRtbg
Copy link
Contributor

Reviving an issue created and closed in 2016, targeting a version that isn't valid today, is kinda "meh".

But anyways: We have the Signer interface:

interface Signer
{
    public function algorithmId(): string;
    public function sign(string $payload, Key $key): string;
    public function verify(string $expected, string $payload, Key $key): bool;
}

We have the Key interface:

interface Key
{
    public function contents(): string;
    public function passphrase(): string;
}

We have the InMemory implementation of Key as a provided way to send a key into the signing mechanism of your choice.

What exactly is missing that could be considered general-purpose (as to warrant implementing this here instead of a separate add-on library) that you would need for any cloud operation?

Have you considered implementing a bit of glue code to utilize the sign() method of the AWS client library?

@Ocramius
Copy link
Sponsor Collaborator

What @SvenRtbg said: locking.

Repository owner locked as resolved and limited conversation to collaborators Apr 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants