Add authentication and authorization to your application.
This library is meant to be used with a PropelAuth account. You can sign up and get started for free.
First, you'll need to initialize the library. You can either call PropelAuth::init
or PropelAuth::fetch_and_init
(which will fetch any unspecified metadata).
let auth = PropelAuth::fetch_and_init(AuthOptions {
auth_url: "REPLACE_ME".to_string(),
api_key: "REPLACE_ME".to_string(),
}).await.expect("Unable to initialize authentication");
Want us to add support for another framework? Reach out at support@propelauth.com
To use Axum, make sure to enable the axum
feature in your Cargo.toml.
Then, add PropelAuthLayer to your Router:
let auth_layer = PropelAuthLayer::new(auth);
let app = Router::new()
.route("/whoami", get(whoami))
.route("/org/:org_name/whoami", get(org_whoami))
.layer(auth_layer); // <-- here
You can then take User
in as an argument, which will look for an access token in the Authorization header.
// User will automatically return a 401 (Unauthorized) if a valid access token wasn't provided
async fn whoami(user: User) -> String {
user.user_id
}
You can also check which organizations the user is in, and which roles and permissions they have.
// If the user isn't in the provided organization, a 403 is returned
async fn org_whoami(user: User,
Path(org_name): Path<String>) -> Result<String, UnauthorizedOrForbiddenError> {
let org = user.validate_org_membership(RequiredOrg::OrgName(&org_name),
UserRequirementsInOrg::IsRole("Admin"))?;
Ok(format!("You are a {} in {}", org.user_role, org.org_name))
}
You can also get the full auth
struct and make API calls with it:
// Extension(auth) is useful for making API requests
async fn make_req(Extension(auth): Extension<Arc<PropelAuth>>) -> String {
let magic_link = auth.user().create_magic_link(CreateMagicLinkRequest {
email: "user@customer.com".to_string(),
..Default::default()
}).await.expect("Couldn't create magic link");
magic_link.url
}
To use Actix, make sure to enable the actix4
feature in your Cargo.toml.
Add your PropelAuth to your Router:
let auth = PropelAuth::fetch_and_init(/*...*/)
//...
HttpServer::new(move || {
App::new()
.service(whoami)
.service(org_whoami)
.app_data(web::Data::new(auth.clone())) // <-- here
})
You can then take User
in as an argument, which will look for an access token in the Authorization header.
// User will automatically return a 401 (Unauthorized) if a valid access token wasn't provided
#[get("/whoami")]
async fn whoami(user: User) -> impl Responder {
HttpResponse::Ok().json(user)
}
You can also check which organizations the user is in, and which roles and permissions they have.
// If the user isn't in the provided organization, a 403 is returned
#[get("/org/{org_name}/whoami")]
async fn whoami(user: User, org_name: web::Path<String>) -> Result<impl Responder, UnauthorizedOrForbiddenError> {
let org = user.validate_org_membership(RequiredOrg::OrgName(&org_name.into_inner()),
UserRequirementsInOrg::IsRole("Admin"))?;
Ok(HttpResponse::Ok()
.body(format!("You are a {} in {}", org.user_role, org.org_name)))
}
You can also get the full auth
struct and make API calls with it:
#[post("/magic_link")]
async fn make_req(auth: web::Data<PropelAuth>) -> impl Responder {
let magic_link = auth.user().create_magic_link(CreateMagicLinkRequest {
email: "user@customer.com".to_string(),
..Default::default()
}).await.expect("Couldn't create magic link");
HttpResponse::Ok().json(magic_link)
}
If you'd rather use a pure Rust TLS implementation rather than OpenSSL disable the default features and enable rustls as so:
propelauth = { version >= "0.12.1", features = ["rustls"], default-features = false }
After initializing auth
, you can verify access tokens by passing in the Authorization header (formatted Bearer TOKEN
):
let result = auth.verify().validate_authorization_header(&authorization_header);
match result {
Ok(user) => { /* valid access token in the header */ }
Err(_) => { /* invalid access token, typically we return a 401 Unauthorized here */ }
}
You can also check which organizations the user is in, and which roles and permissions they have.
let org = auth.validate_org_membership(
&authorization_header,
RequiredOrg::OrgName("acme"),
UserRequirementsInOrg::IsRole("Admin")
)?;
// Alternatively, if you already have a user from validate_authorization_header
let org = user.validate_org_membership(
RequiredOrg::OrgName("acme"),
UserRequirementsInOrg::IsRole("Admin")
)?;
And finally, you can make API calls directly from auth.user()
and auth.org()
They come from your frontend. You can read more about integrating your frontend here.