Skip to content

feat(gateway): Check token claims and one-time IDs - #33

Draft
kprabhak wants to merge 1 commit into
feat/token-signaturesfrom
feat/token-claims
Draft

kprabhak wants to merge 1 commit into
feat/token-signaturesfrom
feat/token-claims

Conversation

@kprabhak

Copy link
Copy Markdown

Summary

A token with a valid signature must also be meant for this gateway's project, current, and within its issuer's limits.

This checks the audience, the token's times with 30 seconds of leeway, the issuer's maximum lifetime and required claim values, and accepts a token that carries an ID only once.

An ID can be released when the admission it was recorded for does not complete, so a device can retry with the same token. When the record of IDs is full, further tokens carrying one are refused until entries expire.

Depends on

Stacked on the signature verification pull request.

Test plan

  • Each failed check refuses the token with a fixed reason and no token content
  • A token ID is accepted once, and can be presented again after its admission is released
  • Format, lint and tests pass

Related to datum-cloud/enhancements#883 and datum-cloud/enhancements#916

A valid signature is not enough to admit a device. The token must
also be meant for this gateway's project, current, and within its
issuer's limits.

Check the audience (a string or a list) and the times, with 30
seconds of leeway: "exp" and "iat" are required whole numbers, "exp"
must come after "iat", "iat" may not be in the future, and "nbf" is
checked when present. The lifetime, from "iat" to "exp", must be
within the issuer's maximum, so a token without "iat" is refused.
Claims the issuer requires must be present as exact string values,
and "sub", when present, must be a string. The jsonwebtoken crate
requires only "exp" and checks neither "iat" nor the lifetime, so
these checks are the gateway's own. Each issuer needs an issuer, an
audience and a positive maximum lifetime. A token that names a key in
"cnf" is refused, because a bearer token cannot prove it holds that
key.

An issuer can require a token ID ("jti"), a string of 1 to 256 bytes.
A token that carries one is accepted once: its ID is recorded only
after every other check passes, and kept until the token expires.
The record holds at most 100,000 IDs. When it is full, expired IDs
are dropped, and if it is still full, a token carrying an ID is
refused. The ID is released when the admission it was recorded for
does not complete, so a device can retry with the same token. A
token without an ID can be presented again until it expires.
Refusals carry fixed reasons and never any token content.

Tests cover each refusal, including a token without "iat", one whose
"exp" does not come after "iat", and malformed "jti" and "sub"
values.
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.

1 participant