Canduma rust Graphql
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!
Benchmarks with insert into PostgreSQL
▶ ./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
Collection of major crates used in Canduma
- actix - link
- actix-web - link
- diesel - link
- juniper - link
- chrono - link
- serde_json - link
- argon2rs - link
- jsonwebtoken - link
- anyhow - link
- thiserror - link
- shrinkwraprs - link
Required
- 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)
Getting Started
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
Test the GraphQL API with Insomnia
Register
Login
Get my account
Get JWT Token
Set Bearer JWT Token
Get decoded JWT by the server (for tests purpose)
Test authentication with session in GraphQL by getting all users (for tests purpose)
Logout
Raw code for Insomnia
############ GraphQL Queries ############
query usersQuery {
users {
name
userUuid
email
createdAt
}
}
query tokenQuery {
token {
bearer
}
}
query decodeTokenQuery {
decode {
email
iss
iat
exp
sub
}
}
Test the GraphQL API with VScode REST Client
See / open TEST.http file in vscode.
Build release
cargo build --release
cd target/release
./canduma
Security
Important security considerations
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.
Generate RSA keys for JWT
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
Logging controlled by middleware::Logger actix.rs
To enable debug logging set RUST_LOG=debug
in .env
Testing
Initialization
First run yarn
or npm install
to get all required packages
npm run test
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
$ 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);
CLion
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