All Projects → jtroo → rust-spa-auth

jtroo / rust-spa-auth

Licence: MIT license
Example application using a Vue frontend with Rust backend that has authentication + authorization.

Programming Languages

rust
11053 projects
javascript
184084 projects - #8 most used programming language
Vue
7211 projects
shell
77523 projects
HTML
75241 projects

Projects that are alternatives of or similar to rust-spa-auth

casbin-knex-adapter
Knex adapter for Casbin
Stars: ✭ 16 (-64.44%)
Mutual labels:  authorization
tp5-rbac
一个tp5的RBAC库,使用composer来安装和更新你的项目对于RBAC的需求。同时支持jwt方式的验证。包含了RBAC需要的数据表的数据迁移,能够很方便的开始开发。
Stars: ✭ 69 (+53.33%)
Mutual labels:  authorization
fedramp-automation
FedRAMP Automation
Stars: ✭ 175 (+288.89%)
Mutual labels:  authorization
Kvantum
An intellectual (HTTP/HTTPS) web server with support for server side templating (Crush, Apache Velocity and JTwig)
Stars: ✭ 17 (-62.22%)
Mutual labels:  http-server
waycup
A minimal tool that hides your online assets from online security scanners, researchers and hackers.
Stars: ✭ 100 (+122.22%)
Mutual labels:  http-server
ficam-playbooks
The Federal Identity Credentials and Access Management program publishes guides and playbooks to help U.S. federal executive agencies implement, maintain, and modernize identity management systems.
Stars: ✭ 30 (-33.33%)
Mutual labels:  authorization
bunjil
A GraphQL bastion server with schema merging, authentication and authorization with Policy Based Access Control
Stars: ✭ 25 (-44.44%)
Mutual labels:  authorization
opa-kafka-plugin
Open Policy Agent (OPA) plug-in for Kafka authorization
Stars: ✭ 46 (+2.22%)
Mutual labels:  authorization
gofile
HTTP/1.1 directory listing and file server using TCP sockets for fun
Stars: ✭ 59 (+31.11%)
Mutual labels:  http-server
react-native-auth-example
🔑 React Native APP 身份验证模块示例
Stars: ✭ 53 (+17.78%)
Mutual labels:  authorization
pico
This is a very simple HTTP server for Unix, using fork(). It's very easy to use.
Stars: ✭ 83 (+84.44%)
Mutual labels:  http-server
dynamic-data-and-capabilities
[ARCHIVED] Dynamic Data and Capabilities in IPFS Working Group
Stars: ✭ 57 (+26.67%)
Mutual labels:  authorization
tipi
Tipi - the All-in-one Web Server for Ruby Apps
Stars: ✭ 214 (+375.56%)
Mutual labels:  http-server
blogging-app-with-Angular-CloudFirestore
A blogging application created with the help of Angular on front-end and Google Cloud Firestore on backend.
Stars: ✭ 45 (+0%)
Mutual labels:  authorization
pycameresp
Motion detection with image notification for Esp32CAM and Esp32 flasher with GUI based on esptool.py.
Stars: ✭ 40 (-11.11%)
Mutual labels:  http-server
ApiJwtWithTwoSts
Web API authorization, multi-IDP solutions in ASP.NET Core
Stars: ✭ 43 (-4.44%)
Mutual labels:  authorization
open-rest-es6-boilerplate
open-rest boilerplate project with es6
Stars: ✭ 24 (-46.67%)
Mutual labels:  http-server
http-server
A Java HTTP server in 35MB Docker image
Stars: ✭ 17 (-62.22%)
Mutual labels:  http-server
go-sse
Fully featured, spec-compliant HTML5 server-sent events library
Stars: ✭ 165 (+266.67%)
Mutual labels:  http-server
ts-ucan
Auth tokens for a distributed, user-controlled world
Stars: ✭ 66 (+46.67%)
Mutual labels:  authorization

Rust SPA + Auth

This project contains a Rust server that serves a single page application and has authentication + JWT-based authorization.

It was written as a learning exercise and can hopefully be a useful example for a Rust-backed website that uses authentication + authorization. It's a bit more complete and closer to prodution-ready than other example code I've seen online, e.g. JWT with warp.

Warning

Though I am somewhat informed, I am not a security expert. Don't deploy this code to production.

Demo video

2021-04-03.19-16-28.mp4

Dependencies

  • A recent version of Rust+Cargo (MSRV unknown)
  • A recent version of npm (minimum unknown)

Note regarding Warp

If you check Cargo.toml, you'll see that the warp dependency is my personal warp fork. This is due to waiting on my PR for more convenient rejection handling to be merged.

Notable content

Server

  • Rust with a Warp web server
  • Authentication using Argon2 password hashing to produce refresh token cookies
  • Authorization with 2 basic roles using JWT access tokens for claims
  • Optional CORS for more rapid client side development
  • Example for abstracting a data store with a trait
    • In-memory implementation exists

Client

  • Vue 2.X framework
  • Axios for API requests
  • Login
  • Logout
  • Conditionally visible UI components based on JWT claims
  • Automatic refreshing of access tokens on 403 error

I am not the most proficient client-side dev, so the structure of the client side code may not be what you want to emulate. The API requests using axios are probably the most useful to look at with regards to using the server APIs.

Note on server framework and async runtime

Most of the code is hopefully not closely tied to Warp framework details — most of the Warp-specific code is in routes.rs with a sprinkle in main.rs and error.rs. As long as the server framework used is async capable, the rest of it should be a decent starting point for use with other server frameworks.

Since the webserver uses Warp, the code uses the tokio runtime. Apart from the Warp related code, the auth module has a few instances where it is reliant on tokio. These are pretty minimal so it should be simple to adapt for webservers with another runtime, e.g. Tide.

Instances of tokio reliance:

  • init_default_users: uses block_on to run async code in a sync function
  • store_user: spawns a blocking task to run password hashing
  • authenticate: spawns a blocking task to run password verification
  • pretend_password_processing: uses tokio sleep
  • #[tokio::test] is used for async tests

Serve the SPA with Rust

The command sequence below uses an in-memory data store. To use sqlite, different commands are needed.

cd $(git rev-parse --show-toplevel)
./build-debug.sh
cd build-output
./rust-spa-auth

Serve the SPA separately

To serve the SPA and the server separately for more rapid client side code development, you can use the following commands:

Note - you may have to navigate to https://localhost:9090 manually and accept the certificate warning before this works.

Serve client files:

cd $(git rev-parse --show-toplevel)/client
npm run serve

Run server:

cd $(git rev-parse --show-toplevel)/server
cargo run --features in_memory,dev_cors
# Can omit `in_memory` from above, but a database will need to be specified
# e.g.
export DATABASE_URL=sqlite:///tmp/db.sql
cargo run --features dev_cors -- --database $DATABASE_URL

Example API Usage

You can check the API functionality without your browser using cURL.

See an example sequence below.

curl -v https://localhost:9090/api/login \
  --cacert tls/server.rsa.crt \
  -d '{"email": "user@localhost", "pw": "userpassword"}' \
  -H 'Content-Type: application/json'

# result is in set-cookie header:
# set-cookie: refresh_token=QpOddMUkW9wk/S4B.s/a3k3JttPFH3v4j43gxx7KL+3y05Opm1rjiQBV+07z9NXacLv8PeQn6DRDoblFDerGQ9qeUp1TpaNAg5f1cYtLf3t3xnvGkHUDW2TK/mDJr4A=="; Max-Age=2592000; path=/api/auth/access; Secure; HttpOnly; SameSite=Lax;


curl https://localhost:9090/api/auth/access \
  --cacert tls/server.rsa.crt \
  --cookie "refresh_token=QpOddMUkW9wk/S4B.s/a3k3JttPFH3v4j43gxx7KL+3y05Opm1rjiQBV+07z9NXacLv8PeQn6DRDoblFDerGQ9qeUp1TpaNAg5f1cYtLf3t3xnvGkHUDW2TK/mDJr4A=="

# result:
# eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJlbWFpbCI6InVzZXJAbG9jYWxob3N0Iiwicm9sZSI6InVzZXIiLCJleHAiOjE2MTY5MjY2NTd9.kj9GR-FPUVmZh2BEvGmbqg6tAz4lsjvLxtcTXOjdDXLwD0KGZ2NrDueuuyJ1Y4z8z98q9VcpDNHYjS4veM2hYw

curl https://localhost:9090/api/user \
  --cacert tls/server.rsa.crt \
  -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJlbWFpbCI6InVzZXJAbG9jYWxob3N0Iiwicm9sZSI6InVzZXIiLCJleHAiOjE2MTcwNjUxMDJ9.imixaRk8YgoEv8Hh33qidty_jGBAo9ewIOd7vWqAjAHiN-MZJOFeSXg25nWx86SW9Pc_QFH_qlFYaSmPG_MfRA'

# result:
# user user@localhost

curl https://localhost:9090/api/admin \
  --cacert tls/server.rsa.crt \
  -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJlbWFpbCI6InVzZXJAbG9jYWxob3N0Iiwicm9sZSI6InVzZXIiLCJleHAiOjE2MTcwNjUxMDJ9.imixaRk8YgoEv8Hh33qidty_jGBAo9ewIOd7vWqAjAHiN-MZJOFeSXg25nWx86SW9Pc_QFH_qlFYaSmPG_MfRA'

# result:
# {"message":"no permission","status":"403 Forbidden"}⏎

curl https://localhost:9090/api/auth/logout \
  -X POST \
  --cacert tls/server.rsa.crt \
  --cookie "refresh_token=QpOddMUkW9wk/S4B.s/a3k3JttPFH3v4j43gxx7KL+3y05Opm1rjiQBV+07z9NXacLv8PeQn6DRDoblFDerGQ9qeUp1TpaNAg5f1cYtLf3t3xnvGkHUDW2TK/mDJr4A=="

Potential changes/additions

  • auth rate limit
  • http to https redirect
  • delete the cookie on the client on logout
    • not really necessary, but can do for cleanliness
  • lets-encrypt certificates
  • add APIs for add/delete user
  • casbin

Special mentions

These sources were useful starting points.

License

This project is licensed under the MIT license.

Contribution

Pull requests are welcome. The goal of this project is to serve as a useful example for building a website with a Rust backend that includes some security.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion by you shall be licensed as MIT without any additional terms or conditions.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].