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

Switch to JWT token encapsulation #10

Closed
dividedmind opened this issue Aug 23, 2017 · 6 comments
Closed

Switch to JWT token encapsulation #10

dividedmind opened this issue Aug 23, 2017 · 6 comments
Assignees

Comments

@dividedmind
Copy link
Contributor

Currently tokens are Slosilo-specific, content-agnostic JSON blobs. Since they were first designed JOSE family of standards came into being which specifies formally a design for bearer tokens, as used with Conjur. Since we're considering expanding tokens to support eg. issuer-set expiration time, it's a good time to switch to standards-based format, which already has features like that built-in. It will also make the structure of the tokens themselves reflect the primary (only?) usage, which is to bear authentication certification by a service identified with a keypair.

Note this issue is not about making Slosilo a generic standards-conforming JWT implementation or allowing different crypto algorithms to be used. Instead this is about, in the interest of interoperability and transparency, leveraging immense design work done on JOSE and drift in that direction in lieu of a NIH, not formally specified token format while making it transparent to users (especially Conjur server and clients) where possible.

Note that for Conjur usage this will need further work in conjur-rack and conjur to take advantage of the changes.

Proposed token format

New access tokens mirror old-style Slosilo tokens and use the same algorithm, extending them with extra fields and formatting them in accordance with RFC 7519.

RFC 7519 tokens are composed of three individually base64-encoded parts, which for Slosilo will be, in the first iteration, defined as follows:

  • JWS protected header, a JSON object with keys:
    • typ: document type, value: JWT
    • alg: signature algorithm, value: conjur.org/slosilo/v2
    • kid: key ID (corresponds to key field in old-style Slosilo tokens).
  • JWT (JSON) document payload, with following claims:
    • sub: subject name (aka “username”, “login”). Required. Corresponds to the contents of data field in old-style tokens.
    • iat: date and time of issue (aka “timestamp”) as numeric (“UNIX”) UTC timestamp. Required. Corresponds to the contents of timestamp field in old-style Slosilo tokens.
    • exp expiration date and time as numeric (“UNIX”) UTC timestamp. Optional. By default tokens expire in 8 minutes since iat.
    • cidr list of CIDR restrictions. The token is considered valid if and only if it is presented by an originating IP matching at least one of them. (This restriction should be implemented by Slosilo token consumers, such as conjur-rack. Optional.
  • Signature, using the same algorithm as in old-style tokens (identified by conjur.org/slosilo/v2 in the alg header field. The string to sign is generated as per RFC 7515. This corresponds to the signature field in old-style tokens.

Security considerations

The new tokens are expected to provide the same or stronger security than the old-style ones:

  • Signature algorithm is intentionally kept the same; Slosilo code has received extensive security and crypto review on two separate occasions and to change it would be to lose the assurance brought by that.
  • Intentionally no effort is made to support RFC-mandated algorithms, even REQUIRED. This ensures that security properties are unchanged.
  • String to sign still contains all the fields of the token (Slosilo tokens don't use unprotected JWT headers), but instead of the construction being defined only in code, it's formally specified to be per RFC 7515.
  • Note: for future extensibility care should be taken to define and handle critical fields correctly. This is TBD.

Interoperability considerations

Conjur

For compatibility with existing clients, token issuers may by default issue tokens in JWS JSON serialization (cf. RFC 7515). Tokens so serialized must be base64 encoded before using in a HTTP request header, as with old-style Slosilo tokens; this ensures that from the point of view of the client the format change is transparent, as long as the client treats tokens as opaque (as clients libraries are expected to). Alternatively, issuer can emit JWS compact serialization (perhaps on an endpoint that legacy clients cannot be expected to be able to use anyway, or as indicated by the client with Accept HTTP header), which can be used in requests without any further processing.

Third-party JOSE implementations

Slosilo is not claiming or intended to provide a general-purpose JWT implementation. However standards-conformant clients should be able to parse the tokens and understand common fields. Since non-standard algorithm is used, a generic implementation won't be able to verify the signature out-of-the-box; it can be accomplished by using Slosilo::Keystore#get_by_fingerprint to lookup the key by kid and Slosilo::Key#verify_signature to perform the verification on standard string-to-sign, bypassing Slosilo JWT parsing logic.

Motivation

Beyond moving to a standard token format, two improvements for Conjur should already be apparent from the proposed format:

  • Token expiration can be specified by the signer. This has long been a feature requested by customers in various contexts, not necessarily valid. However there is significant value in providing this functionality, as Conjur authenticators can now specify the expiration time to be proportional to the amount of work and trust put into the authentication process to explicitly express any performance-security tradeoff, which they're in the best position to estimate. (Note consumers can still make their own decisions about how old tokens they want to accept.)
  • CIDR restrictions can be specified as part of the token. This is especially important for environments where the network is (relatively) trusted, as it can provide an additional level of security without the need for a central service to coordinate these restrictions; moreover, they can differ per authentication event to reflect that environment and trust, again putting that control in the place which is best situated to know it.

Future work

  • Define and implement handling of critical fields (cf. Security considerations above).
  • Formally specify the signature algorithm to make it easier to develop third-party implementations.
@dividedmind dividedmind self-assigned this Aug 24, 2017
dividedmind added a commit that referenced this issue Sep 4, 2017
dividedmind added a commit to cyberark/conjur-rack that referenced this issue Sep 4, 2017
Please refer to cyberark/slosilo#10
for details.
dividedmind added a commit to cyberark/conjur that referenced this issue Sep 4, 2017
@dividedmind
Copy link
Contributor Author

Note I created pull requests above for convenience when reviewing. They should stay on feature branches until outstanding issues ( #12 and cyberark/conjur-rack#11 ) are resolved.

@dividedmind
Copy link
Contributor Author

Issues resolved. Pull requests above can be merged now.

@kgilpin
Copy link
Contributor

kgilpin commented Sep 19, 2017

Can we call this v3 because there is already a slosilo 2

@kgilpin
Copy link
Contributor

kgilpin commented Sep 19, 2017

Is it possible to change the username from e.g. host/foo.bar to host:foo.bar to match the rest of conjur fully qualified ids

@dividedmind
Copy link
Contributor Author

The signature algorithm is the same as in Slosilo v2. I suppose it could even be called v1 since there was only one version of the algorithm; or, maybe even better (shorter), to remove the version part altogether and just have conjur.org/slosilo.

@dividedmind
Copy link
Contributor Author

Regarding changing the usernames, Slosilo itself doesn't care about it, but it's definitely something that would be nice to change. If we keep the authorization protocol (ie. clients still submit host/foo) it should be transparent to the client. The changes would need to be done in conjur proper however (perhaps some in conjur-rack too, although AFAIR not).

jvanderhoof pushed a commit that referenced this issue Oct 12, 2017
* Add support for JWT-formatted tokens

See issue #10 for details

* Accept pre-parsed JWT tokens in Slosilo::token_signer

* Add some docstrings re JWT methods

In particular it indicates some useful claims and explains that
it's the caller's responsibility to verify claims this library
doesn't understand.

Closes #12

* Remove typ: 'JWT' header field

It's optional and not really useful.
Can always be provided by the client if required.
jvanderhoof pushed a commit to cyberark/conjur-rack that referenced this issue Oct 12, 2017
* Remove Conjur::Rack::User#new_association

It's not clear what was the intent behind this method, but there is
no documentation and no usage as far as I can tell.

* Some spec refactoring

Split Authenticator and .user spec, make -fdoc more readable.

* Use real Slosilo in specs

While this might move the tests a bit on the unit-integration
spectrum, it does make them more realistic and easier to implement.

Specific things can still be mocked and stubbed as needed for
test granularity.

* Correctly handle JWT tokens

Please refer to cyberark/slosilo#10
for details.

* Add changelog entry

* Apply CIDR restrictions

Closes #11.

* Reject tokens with unrecognized claims

JWT lacks a mechanism for specifying critical claims as JWS has
with header 'crit' field; JWT spec suggests to ignore unrecognized
claims and that is what a generic JWT library should do.

However, conjur-rack is a specific application; for security reasons
it's best to reject tokens which we don't totally understand, lest the
requester is allowed to do what she is not in fact authorized to.

If need be, this can be extended in the future with 'crit'-like
mechanism for specifying optional claims.

Related: cyberark/slosilo#12
dividedmind added a commit to cyberark/conjur that referenced this issue Oct 18, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants