-
Notifications
You must be signed in to change notification settings - Fork 96
Proposal: JWT-based authorization for notary server #812
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
Comments
@kubkon thanks for the detailed proposal! One key question I have: who's the issuer of the JWT token in the first place? AFAIK JWT auth requires user to 'log in' before the issuer issues the JWT to them. They can then use it to access resources in the server, in which the server performs validation against the JWT (as described in your proposal above). |
The issuer of JWT token would be some auxiliary server/service. For example, in our case, we have a standalone auth server that issues JWT tokens, and we then distribute the server's public key to our other servers so that they can validate said tokens. In case of the notary server, whoever is managing the entire system (the admin) would provide the signing public key at the config level while the auth server is left unspecified by design to allow as much flexibility as possible. Additionally, the admin would then also be able to configure the required user claims in |
Oh, and in #817 I've provided both private and public key as fixtures where the private key bit immitates the signing authority - whatever that may be - for testing only. |
This proposal follows up discussion about additional authorization modes during TLSN office hours and face-to-face meeting with @th4s. CCing @yuroitaki since you seem to be handling most if not all server-side things in TLSN.
Premise
Currently, authorization with TLS notary server is done via a whitelist mechanism. The whitelist has a simple format such that:
Next, authentication via the whitelist can be enabled by specifying in the server’s
config.yaml
Note that by default authorization is disabled. If enabled however, it protects all routes except
/notarize
which is automatically protected by a session random key which is generated by accessing/session
route.While the above mechanism is simple to use and most likely sufficient for server-based communications with the notary server, the problems appear once we move the sending end (the end that request a notarization) into the browser. Then, the browser has to somehow gain access to the secret API key, and do so in such a way as not to accidentally leak the secret to the outside world. This is finicky and error-prone.
In this issue, we would like to propose an alternative authorization mechanism that is based on JSON web token authorization. This mode of authorization would exist side-by-side as an alternative to the whitelist mechanism, and the user of the TLS notary server would be able to select the most appropriate mode of authorization for their setup.
User perspective
From the user perspective, ideally they would be able to enable JWT authorization in the config file, specify path to the decoding key (public key for validating JWTs’ signatures), and optionally specify a list of claims the JWT should carry for successful authorization. This config would co-exist with the existing whitelist config mechanism, however, only one should be possible at any one time.
Here’s the proposed format of JWT config in
config.yaml
:public_key_pem_path
- path to the decoding keyclaims
- list of required claims that each JWT has to carryIn this particular example, we require each JWT to carry
sub
andhost
claims such thatIf any of those claims is not present in the JWT, or has a different value, fails validation and ultimately ends with failure to correctly authorize with the server. Additionally, we would always validate JWT’s expiration.
The proposed format for describing the required claims is based upon a similar mechanism found in Envoy Gateway configuration.
The proposed scheme is best summarised by the following Rust target structs:
JwtClaimValueType
would initially include some basic primitives such as string and int but could of course be augmented to include more value types. Also, please note that the only required field ofJwtClaim
isname
, while the rest of the fields assume default values such thatvalues := Vec::new()
andvalue_type := JwtClaimValueType::String
. Finally,name
is expected to be nested with.
as a separator, thereforesub
would mean we expectsub
field at the root of the JWT claims objectwhile
my.new.sub
would mean we expect three indentation levels in the JWT claims objectSome examples of valid claims configurations are:
string
string
Implementation perspective
From the implementation perspective, we would re-use the implementation of the existing
AuthorizationMiddleware
with one gotcha - JWT claims would be validated at runtime (with the exception of expiration date). This can be achieved by extracting a rawserde_json::Value
as raw claims from the underlying JWT (viajsonwebtoken
crate), and then we would walk the user-specified claims set in the config file to perform validation by selectively accessing elements in the extract JSONValue
.I envision the logic for validating claims to reside in
crates/notary/server/src/auth.rs
(or thereabouts).Additionally, the server would always have access to user-specified claims as well as the decoding key in
NotaryGlobals
just like it now has access to the authorization whitelist (if present). This way, addition of JWT-based authorization mechanism would be least invasive on the notary server implementation.An example PoC implementation is available in my fork as dff299f commit.
Demo
Example
config.yaml
:sub
claim set astest
rather than the requiredtlsn
value:Concluding remarks
Since this feature is desired by us (the vlayer team), I would of course champion it and work with you (the maintainers) in landing it in the best shape possible.
The text was updated successfully, but these errors were encountered: