Tutorial on How to Use Poem-casbin
Introduction
Casbin-rs is an authorization library that supports access control models like ACL, RBAC, ABAC written in Rust.
Poem is a full-featured and easy-to-use web framework with the Rust programming language.
In this tutorial, we will integrate poem with casbin-rs using poem-casbin.
Write a hello-world service with poem
First, create a cargo crate, then add following dependencies in Cargo.toml
:
1 | tokio = { version = "1.20.0", features = ["rt-multi-thread", "macros"] } |
Add following code to main.rs
1 | use poem::{get, handler, listener::TcpListener, web::Path, Route, Server}; |
There are 3 endpoints, /pen/1
, /pen/2
, and /book/:id
. It’s quite simple, right? Let’s run our service, enter cargo run
and our service will be available at 127.0.0.1:3000
.
Let’s use curl
to test our service:
Integrate with basic auth middleware
Note that casbin-poem is an authorization middleware, not an authentication middleware. Casbin only takes charge of permission control, so we need to implement an authentication middleware to identify user.
In this part, we will inegrate our service with a basic auth middleware.
To start with, add following dependency to Cargo.toml
:
1 | poem-casbin-auth = { git = "https://github.com/casbin-rs/poem-casbin.git" } |
Then create a file named auth.rs
and add following code to it:
1 | use poem::{ |
In this mod, we implement a basic auth middleware, for simplicity, here we don’t verify username and password, instead we just insert CasbinVals
with provided username into Extension
,so that poem-casbin middleware can extract identity information. If the request doesn’t have basic auth, then the middleware will return 401 Unauthorized.
Then let’s integrate our service with basic auth middleware. Firstly, add following code to main.rs
:
1 | mod auth; |
Then add a new handler to confirm that our auth middleware insert identity information correctly:
1 |
|
Lastly, rewrite main
function to add an endpoint /user
and wrap all endpoints with basic auth middleware, now it looks like:
1 | let app = Route::new() |
Now, let’s use curl
again to test our service.
Now as you can see, if we don’t provide basic auth when accessing our service, we will get 401 Unauthorized. Our request is aborted by basic auth middleware. Let’s send requests with basic auth:
1 | curl -u alice:123 localhost:3000/book/1 |
Now we can get response as normal. It seems that our basic auth middleware works well.
Integrate with poem-casbin middleware
In the last part, we will integrate our service with poem-casbin middleware.
First, we need to provide conf and policy files under the project root directory.
rbac_with_pattern_model.conf
looks like:
1 | [request_definition] |
rbac_with_pattern_policy.csv
looks like:
1 | p, alice, /pen/1, GET |
These policy means:
- For alice:
- can access
/pen/1
- is
book_admin
, thus can access/book/:id
- can access
- For bob:
- is
pen_admin
, thus can access/pen/:id
- is
Now let’s focus on main.rs
, first add following code to it:
1 | use poem_casbin_auth::casbin::function_map::key_match2; |
Then rewrite main
function to wrap our service with poem-casbin middleware:
1 | let m = DefaultModel::from_file("rbac_with_pattern_model.conf") |
Here we first read conf and policy, then create casbin_middleware
and change matching_fn
to key_match
to match wildcard path (like /:id
). Lastly, we wrap all endpoints with casbin_middleware
.
That’s all the work we have to do to integrate our service with poem-casbin middleware, quite simple, right?
Again, let’s use curl
to test our service:
If alice wants to access /pen/2
, she will get 403 Forbidden, because she is not allowed to access this endpoint.
Likewise, bob can’t access /book/2
:
Everything is fine when both users send requests to the endpoints that they can access:
Summary
In this tutorial, we write a hello-world web service using poem, then integrate it with basic auth and casbin-poem middleware. It’s a quite simple project with only ~100 LOC, its code can be found at this repository: https://github.com/greenhandatsjtu/poem-casbin-demo