ezidam: added access_token guard, oauth/userinfo endpoint
This commit is contained in:
parent
d14c3da06a
commit
92a08db8fe
5 changed files with 88 additions and 11 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod access_token;
|
||||||
mod basic_auth;
|
mod basic_auth;
|
||||||
mod completed_setup;
|
mod completed_setup;
|
||||||
mod jwt;
|
mod jwt;
|
||||||
|
|
@ -5,7 +6,8 @@ mod need_setup;
|
||||||
mod refresh_token;
|
mod refresh_token;
|
||||||
|
|
||||||
pub use self::jwt::*;
|
pub use self::jwt::*;
|
||||||
|
pub use access_token::AccessToken;
|
||||||
|
pub use basic_auth::BasicAuth;
|
||||||
pub use completed_setup::CompletedSetup;
|
pub use completed_setup::CompletedSetup;
|
||||||
pub use need_setup::NeedSetup;
|
pub use need_setup::NeedSetup;
|
||||||
pub use refresh_token::RefreshToken;
|
pub use refresh_token::RefreshToken;
|
||||||
pub use basic_auth::BasicAuth;
|
|
||||||
|
|
|
||||||
64
crates/ezidam/src/guards/access_token.rs
Normal file
64
crates/ezidam/src/guards/access_token.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
use crate::guards::validate_jwt;
|
||||||
|
use jwt::JwtClaims;
|
||||||
|
use rocket::http::Status;
|
||||||
|
use rocket::request::{FromRequest, Outcome};
|
||||||
|
use rocket::Request;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum BearerAuthError {
|
||||||
|
BadCount,
|
||||||
|
Invalid,
|
||||||
|
Empty,
|
||||||
|
Jwt(super::jwt::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AccessToken(pub JwtClaims);
|
||||||
|
|
||||||
|
impl AccessToken {
|
||||||
|
async fn from_bearer(
|
||||||
|
raw: &str,
|
||||||
|
request: &Request<'_>,
|
||||||
|
) -> Result<Option<Self>, BearerAuthError> {
|
||||||
|
// Make sure format is `Bearer access_token`
|
||||||
|
if !raw.starts_with("Bearer ") {
|
||||||
|
return Err(BearerAuthError::Invalid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract access token
|
||||||
|
let (_, access_token) = raw.split_once(' ').ok_or(BearerAuthError::Empty)?;
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
match validate_jwt::<JwtClaims>(access_token.to_string(), request, None).await {
|
||||||
|
Ok(jwt_claims) => match jwt_claims {
|
||||||
|
Some(jwt_claims) => Ok(Some(Self(jwt_claims))),
|
||||||
|
None => Ok(None),
|
||||||
|
},
|
||||||
|
Err(e) => match e {
|
||||||
|
Outcome::Success(s) => Ok(Some(Self(s))),
|
||||||
|
Outcome::Failure(e) => Err(BearerAuthError::Jwt(e.1)),
|
||||||
|
Outcome::Forward(_) => Ok(None),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rocket::async_trait]
|
||||||
|
impl<'r> FromRequest<'r> for AccessToken {
|
||||||
|
type Error = BearerAuthError;
|
||||||
|
|
||||||
|
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
|
||||||
|
let keys: Vec<_> = request.headers().get("Authorization").collect();
|
||||||
|
|
||||||
|
match keys.len() {
|
||||||
|
0 => Outcome::Forward(()),
|
||||||
|
1 => match AccessToken::from_bearer(keys[0], request).await {
|
||||||
|
Ok(access_token) => match access_token {
|
||||||
|
Some(access_token) => Outcome::Success(access_token),
|
||||||
|
None => Outcome::Forward(()),
|
||||||
|
},
|
||||||
|
Err(e) => Outcome::Failure((Status::Unauthorized, e)),
|
||||||
|
},
|
||||||
|
_ => Outcome::Failure((Status::BadRequest, BearerAuthError::BadCount)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,22 +1,21 @@
|
||||||
use crate::database::Database;
|
use crate::database::Database;
|
||||||
use jwt::database::Key;
|
|
||||||
use jwt::{JwtClaims, PrivateKey};
|
|
||||||
use rocket::http::Status;
|
|
||||||
use rocket::request::Outcome;
|
|
||||||
use rocket::tokio::task;
|
|
||||||
use rocket::Request;
|
|
||||||
|
|
||||||
mod admin;
|
|
||||||
mod user;
|
|
||||||
|
|
||||||
use crate::guards::refresh_token::get_refresh_token_from_cookie;
|
use crate::guards::refresh_token::get_refresh_token_from_cookie;
|
||||||
use crate::tokens::{
|
use crate::tokens::{
|
||||||
JWT_COOKIE_NAME, JWT_DURATION_MINUTES, REFRESH_TOKEN_COOKIE_NAME, REFRESH_TOKEN_DURATION_DAYS,
|
JWT_COOKIE_NAME, JWT_DURATION_MINUTES, REFRESH_TOKEN_COOKIE_NAME, REFRESH_TOKEN_DURATION_DAYS,
|
||||||
};
|
};
|
||||||
pub use admin::JwtAdmin;
|
pub use admin::JwtAdmin;
|
||||||
use id::KeyID;
|
use id::KeyID;
|
||||||
|
use jwt::database::Key;
|
||||||
|
use jwt::{JwtClaims, PrivateKey};
|
||||||
|
use rocket::http::Status;
|
||||||
|
use rocket::request::Outcome;
|
||||||
|
use rocket::tokio::task;
|
||||||
|
use rocket::Request;
|
||||||
pub use user::JwtUser;
|
pub use user::JwtUser;
|
||||||
|
|
||||||
|
mod admin;
|
||||||
|
mod user;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
GetDatabase,
|
GetDatabase,
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@ use authorize::*;
|
||||||
use redirect::*;
|
use redirect::*;
|
||||||
use rocket::{routes, Route};
|
use rocket::{routes, Route};
|
||||||
use token::*;
|
use token::*;
|
||||||
|
use userinfo::*;
|
||||||
|
|
||||||
pub mod authorize;
|
pub mod authorize;
|
||||||
pub mod redirect;
|
pub mod redirect;
|
||||||
pub mod token;
|
pub mod token;
|
||||||
|
pub mod userinfo;
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
routes![
|
routes![
|
||||||
|
|
@ -14,6 +16,7 @@ pub fn routes() -> Vec<Route> {
|
||||||
authorize_ezidam,
|
authorize_ezidam,
|
||||||
redirect_page,
|
redirect_page,
|
||||||
request_token,
|
request_token,
|
||||||
|
get_userinfo,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
9
crates/ezidam/src/routes/oauth/userinfo.rs
Normal file
9
crates/ezidam/src/routes/oauth/userinfo.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
use crate::routes::prelude::*;
|
||||||
|
use jwt::JwtClaims;
|
||||||
|
use rocket::get;
|
||||||
|
use rocket::serde::json::Json;
|
||||||
|
|
||||||
|
#[get("/oauth/userinfo")]
|
||||||
|
pub async fn get_userinfo(access_token: AccessToken) -> Json<JwtClaims> {
|
||||||
|
Json(access_token.0)
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue