openid / sharedsignals

OpenID Shared Signals Working Group Repository
54 stars 14 forks source link

Allow Receiver to supply public key #140

Open FragLegs opened 9 months ago

FragLegs commented 9 months ago

In the current SSF spec, the Transmitter can make a jwks.json file available to its Receivers. This allows the Transmitter to sign the JWTs that it is sending the Receiver, so that the Receiver can verify that the security event tokens (SETs) are not forged by some third party. However, these security event tokens often contain personally identifying information (PII) and some vendors may wish to be able to encrypt the SET, not just sign it. In order to do that, the Transmitter would need the Receiver to share a public key. I propose that we add language to the spec to make it clear that a Receiver MAY provide well-known and jwks.json endpoints for this purpose.

The current spec treats Receivers as an afterthought - all of the language is around what Transmitters MAY and MUST do. This would give us an opportunity to make Receivers more of a first class citizen in the SSF spec.

appsdesh commented 9 months ago

I have raised similar asks around not having reciever's metadata doc in earlier working group calls here

SET encryption should also be baked in the SET - RFC8417 or outside SSF spec.

On the encryption - my thoughts are

  1. To encrypt the events object, but for that to work, we need to surface stream ID as a first-class claim in the SET JWT that could be used for routing. (Sounds like RFC8417 enhancement)
  2. We should define at what granularity we should support encryption, per stream unique keys, per receiver unique keys, etc.
TakahikoKawasaki commented 9 months ago

In a traditional way like the OpenID Connect Dynamic Client Registration 1.0 specification (OIDC DynReg), an entity that receives encrypted data does either (1) register its public key in advance to the entity that encrypts data (e.g. through the jwks client metadata in the case of OIDC DynReg) or (2) make its public key publicly available and convey the location of the key to the entity that encrypts data (e.g. through the jwks_uri client metadata in the case of OIDC DynReg).

A new flexible way adopted by the OpenID for Verifiable Credential Issuance specification (OID4VCI) is to include a public key for encryption in a request at runtime through a dedicated parameter. In the case of OID4VCI, the parameter is credential_response_encryption. The value of the parameter is a JSON object that contains the following properties.

property description
jwk A public key in the JWK (RFC 7517) format.
alg A JWE (RFC 7516) alg algorithm.
enc A JWE (RFC 7516) enc algorithm.

This new approach may be worth considering.

FragLegs commented 9 months ago

@TakahikoKawasaki That is a great way to solve this problem! We could add an optional, receiver-supplied field to the StreamConfiguration (to be set by the receiver on stream creation or stream update) that holds the JSON object you described above. I like this solution better because it is a lower burden on the Receiver, especially a poll-based Receiver who might not be hosting any endpoints.

@appsdesh I am imagining that the Transmitter would encrypt the entire SET. That is, instead of just signing the JWT (making it a JWS) the Transmitter would encrypt and sign the JWT (making it a JWE). Do you think there would be problems with that approach? Some of the PII is potentially in the top level of the SET (i.e. the sub_id claim) so I think we need to encrypt more than just the events.

awoie commented 8 months ago

+1 to enabling optional encryption.

windley commented 8 months ago

+1 to optional encryption and I also like. @TakahikoKawasaki's suggestion.

dhs-aws commented 8 months ago

This has also come up in the work on using SETs within SCIM. I agree that we need to support a mechanism for encryption of the SETs to protect data in transit, particularly where there is TLS termination at an endpoint prior to the receiver.

ysarig1 commented 7 months ago

Encrypting the entire SET using a public key can be expensive to the transmitter if there are a large number of security events that need to be encrypted. While I expect that the volume of security events will usually be fairly low there are edge cases (e.g., device compliance events when the definition of compliance changed and resulted with a large number of devices changing their status).

Another option that we can consider for encryption is for the receiver to send a symmetric encryption key to the transmitter when the stream is created.

BTW If I remember correctly, the JWE spec include the use of a symmetric key to do the plaintext encryption.

TakahikoKawasaki commented 7 months ago

The JWE spec (RFC 7516) has already implemented a logic to minimize the amount of data for asymmetric encryption. The following diagram is an excerpt from "4.1. Two-Step Encryption" in "Understanding ID Token". (DISCLAIMER: It's my blog post in November, 2017)

encrypted_key

dhs-aws commented 7 months ago

@ysarig1 wrote

Encrypting the entire SET using a public key can be expensive to the transmitter if there are a large number of security events that need to be encrypted. While I expect that the volume of security events will usually be fairly low there are edge cases (e.g., device compliance events when the definition of compliance changed and resulted with a large number of devices changing their status).

As discussed, this is an option, not a requirement, for transmitters. Cost is controllable by the transmitter if they wish to not support encrypting the SETs.

In many cases the risk of data leakage or being out of compliance outweighs the expense of encryption. Supporting this as a first class mechanism in SSF will expand the utility of SSF with no cost to those who choose not to implement it.

keylimesoda commented 1 month ago

@TakahikoKawasaki That is a great way to solve this problem! We could add an optional, receiver-supplied field to the StreamConfiguration (to be set by the receiver on stream creation or stream update) that holds the JSON object you described above. I like this solution better because it is a lower burden on the Receiver, especially a poll-based Receiver who might not be hosting any endpoints.

@appsdesh I am imagining that the Transmitter would encrypt the entire SET. That is, instead of just signing the JWT (making it a JWS) the Transmitter would encrypt and sign the JWT (making it a JWE). Do you think there would be problems with that approach? Some of the PII is potentially in the top level of the SET (i.e. the sub_id claim) so I think we need to encrypt more than just the events.

Regarding granularity, I could foresee a scenario where encryption is particularly desired for certain subjects within a stream, and that certain subjects may even have their own associated public keys.