A Rust authentication server with GraphQL API, Diesel, PostgreSQL session authentication and JWT
This repository contains a GraphQL server with JWT up and running quickly.
It uses actix-web, Juniper, Diesel and jsonwebtoken
Your own pull requests are welcome!
▶ ./bombardier -c 125 -n 10000000 http://localhost:3000/graphql -k -f body --method=POST -H "Content-Type: application/json" -s
Bombarding http://localhost:3000/graphql with 10000000 request(s) using 125 connection(s)
10000000 / 10000000 [===========================================================================] 100.00% 28777/s 5m47s
Done!
Statistics Avg Stdev Max
Reqs/sec 28788.66 2183.47 34605.95
Latency 4.32ms 543.07us 110.95ms
HTTP codes:
1xx - 0, 2xx - 10000000, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 20.75MB/s
bombardier -c 125 -d 30s http://localhost:8000/user/me -k --method=GET -H "Content-Type: application/json" -H "Cookie: auth=<YOUR_TOKEN>"
Bombarding http://localhost:8000/user/me for 30s using 125 connection(s)
[=========================================================================================================================================================================================] 30s
Done!
Statistics Avg Stdev Max
Reqs/sec 7220.99 902.95 11296.18
Latency 17.31ms 2.66ms 90.21ms
HTTP codes:
1xx - 0, 2xx - 216685, 3xx - 0, 4xx - 0, 5xx - 0
others - 0
Throughput: 3.36MB/s
bombardier -c 125 -d 30s http://127.0.0.1:8000/user/login -k --timeout=2s -b '{ "email": "[email protected]", "password": "<YOURPASSWORD>" }' --method=POST -H "Content-Type: application/json"
wrk -t4 -c125 -d60s -s perf.lua http://127.0.0.1:8000/graphql
Running 1m test @ http://127.0.0.1:8000/graphql
4 threads and 125 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 328.88ms 56.04ms 555.59ms 81.67%
Req/Sec 96.15 49.97 272.00 63.67%
22577 requests in 1.00m, 5.94MB read
Requests/sec: 375.72
Transfer/sec: 101.27KB
- actix - link
- actix-web - link
- diesel - link
- juniper - link
- chrono - link
- serde_json - link
- argon2rs - link
- jsonwebtoken - link
- anyhow - link
- thiserror - link
- shrinkwraprs - link
- Rustup
- Stable Toolchain:
rustup default stable
- Diesel cli with postgres
cargo install diesel_cli --no-default-features --features "postgres"
- PostgreSQL database server or use our docker-compose.yml (require docker)
git clone https://github.com/clifinger/canduma.git
cd canduma
docker-compose up
cp .env.example .env
diesel setup --database-url='postgres://postgres:canduma@localhost/canduma'
diesel migration run
cargo run
// or
// cargo install cargo-watch
cargo watch -c -w src -x run
############ GraphQL Queries ############
query usersQuery {
users {
name
userUuid
email
createdAt
}
}
query tokenQuery {
token {
bearer
}
}
query decodeTokenQuery {
decode {
email
iss
iat
exp
sub
}
}
See / open TEST.http file in vscode.
cargo build --release
cd target/release
./canduma
We use session cookies for authentication.
Why not JWT authentication?
Stop Using JWT for sessions and why your solution doesn't work
The use of JWT remains secure only if you use adequate storage. This boilerplate is built for use in a micro-services architecture.
JWT can be use for representing claims to be transferred between two parties.
The private key should only be on this micro-service. public key can be used on all other parties to decode the token.
This boilerplate provides a complete example, so we included JWT also.
In development mode you can keep the one in /keys
folder.
// private key
$ openssl genrsa -out rs256-4096-private.rsa 4096
// public key
$ openssl rsa -in rs256-4096-private.rsa -pubout > rs256-4096-public.pem
Logging controlled by middleware::Logger actix.rs
To enable debug logging set RUST_LOG=debug
in .env
First run yarn
or npm install
to get all required packages
To run you can use npm run test
or yarn test
.
The testing system designed to automatically build canduma
offline and start in tests/jest.beforeall.js
We starting canduma
in order to capture output from both rust and js code using testci
target
$ npm run testci
> canduma@ testci /home/olexiyb/b100pro/canduma
> cross-env RUST_LOG=debug DEBUG=canduma:* NODE_ENV=test jest
Determining test suites to run...
$ killall canduma
canduma: no process found
$ cargo build
Finished dev [unoptimized + debuginfo] target(s) in 0.07s
canduma:jest.beforeall.js build = { status: 0, signal: null, output: [ null, null, null ], pid: 2447, stdout: null, stderr: null } +0ms
$ target/debug/canduma
[2020-04-02T18:17:19Z INFO actix_server::builder] Starting 24 workers
[2020-04-02T18:17:19Z INFO actix_server::builder] Starting server on 0.0.0.0:4000
Listening on 0.0.0.0:4000
started API
canduma:user.test.js /user/me body='Unauthorized' text="Unauthorized" +0ms
...
[2020-04-02T18:17:22Z DEBUG canduma::user::handler] user_string={"user_uuid":"f7cfa71e-096e-44d0-ae4f-7d16dd9e4baf","email":"[email protected]","role":"bad_role"}
canduma:user.test.js /graphql body={ data: null, errors: [ { message: 'Unauthorized', locations: [Array], path: [Array], extensions: [Object] } ] } +292ms
PASS tests/user.test.js
...
In example above you see output from jest tests as well as from rust code debug!("user_string={}", user_string);
I also highly recommend to use CLion as a dev tool. I allows to run all tests or individual with single click and analyze logs