Skip to content

A command-line tool to get information about JWTs (Json Web Tokens)

License

Notifications You must be signed in to change notification settings

lmammino/jwtinfo

Repository files navigation

jwtinfo

build badge codecov crates.io badge Documentation rustc badge Clippy Linting Result License: MIT OR Apache-2.0 Gitpod Ready-to-Code

A command line tool to get information about JWTs (Json Web Tokens).

Usage

jwtinfo is a command line interface that allows you to inspect a given JWT. The tool currently allows to see the body of the token in JSON format. It accepts a single command line argument which should be a valid JWT.

Here's an example:

jwtinfo eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Which will print:

{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }

If you want to visualize the token header (rather than the body), you can do that by passing the --header flag:

jwtinfo --header eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Which will print:

{ "alg": "HS256", "typ": "JWT" }

You can combine the tool with other command line utilities, for instance jq:

jwtinfo eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c | jq .

Install

You can install the binary in several ways:

Cargo

You can install the binary in your system with cargo:

cargo install jwtinfo

At this point jwtinfo will be available as a binary in your system.

Install script

The following script will download and install precompiled binaries from the latest GitHub release

curl https://raw.githubusercontent.com/lmammino/jwtinfo/main/install.sh | sh

By default, it will install the binary in /usr/local/bin. You can customize this by setting the INSTALL_DIRECTORY environment variable before running the script (e.g. INSTALL_DIRECTORY=$HOME will install the binary in $HOME/bin).

If you want to install a specific release you can set the RELEASE_TAG environment variable to point to your target version before running the script (e.g. RELESE_TAG=v0.1.7).

Precompiled binaries

Pre-compiled binaries for x64 (Windows, macOs and Unix) and ARMv7 are available in the Releases page.

Using Nix

If you are using Nix, you can install the jwtinfo binary with the following command:

nix profile install github:lmammino/jwtinfo

Or, if you prefer to use a configuration file, you can add the following to your flake:

jwtinfo = {
    url = "github:lmammino/jwtinfo";
    inputs.nixpkgs.follows = "nixpkgs"; 
};

# ... with home.nix
home.packages = [ inputs.jwtinfo.packages."x86_64-linux".default ];

# ... with configuration.nix
environment.systemPackages = [ inputs.jwtinfo.packages."x86_64-linux".default ];

Make sure to replace "x86_64-linux" with your target platform.

You can also just try it out in a Nix shell with:

nix shell github:lmammino/jwtinfo -c jwtinfo <some_jwt_token>

Finally, for development purposes, you can clone this repo and then run:

nix develop

Alternatives

If you don't want to install a binary for debugging JWT, a super simple bash alternative called jwtinfo.sh is available.

Programmatic usage

Install with cargo:

[dependencies]
jwtinfo = "*"

Then use it in your code

use jwtinfo::{jwt};
let token_str = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
let token = jwt::parse(token_str).unwrap();
assert_eq!(token.header.to_string(), "{\"alg\":\"HS256\",\"typ\":\"JWT\"}");
assert_eq!(token.body.to_string(), "{\"iat\":1516239022,\"name\":\"John Doe\",\"sub\":\"1234567890\"}");

Since jwt:Token implements str::FromStr, you can also do the following:

use jwtinfo::{jwt};
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c".parse::<jwt::Token>().unwrap();
assert_eq!(token.header.to_string(), "{\"alg\":\"HS256\",\"typ\":\"JWT\"}");
assert_eq!(token.body.to_string(), "{\"iat\":1516239022,\"name\":\"John Doe\",\"sub\":\"1234567890\"}");

Coverage reports

If you want to run coverage reports locally you can follow this recipe.

First of all you will need Rust Nightly that you can get with rustup

rustup install nightly

You will also need grcov that you can get with cargo:

cargo install grcov

Now you can run the tests in profile mode:

export CARGO_INCREMENTAL=0
export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Zno-landing-pads"
cargo +nightly test

This will run your tests and generate coverage info in ./target/debug/

Now we can run grcov:

grcov ./target/debug/ -s . -t html --llvm --branch --ignore-not-existing -o ./target/debug/coverage/

Finally you will have your browsable coverage report at ./target/debug/coverage/index.html.

Tarpaulin coverage

Since grcov tends to be somewhat inaccurate at times, you can also get a coverage report by running tarpaulin using docker:

docker run --security-opt seccomp=unconfined -v "${PWD}:/volume" xd009642/tarpaulin:develop-nightly bash -c 'cargo build && cargo tarpaulin -o Html'

Your coverage report will be available as tarpaulin-report.html in the root of the project.

Credits

A special thank you goes to the Rust Reddit community for providing a lot of useful suggestions on how to improve this project. A special thanks goes to: mardiros, matthieum, steveklabnik1, ESBDB, Dushistov, Doddzilla7. Another huge thank you goes to the Rust stackoverflow community, especially to Denys Séguret.

Big thanks also go to Tim McNamara for conducting a live code review of this codebase.

Contributing

Everyone is very welcome to contribute to this project. You can contribute just by submitting bugs or suggesting improvements by opening an issue on GitHub.

License

Licensed under MIT License. © Luciano Mammino & Stefano Abalsamo.