ezidam: added access_token guard, oauth/userinfo endpoint

This commit is contained in:
Philippe Loctaux 2023-04-04 23:16:34 +02:00
parent d14c3da06a
commit 92a08db8fe
5 changed files with 88 additions and 11 deletions

View file

@ -1,3 +1,4 @@
mod access_token;
mod basic_auth;
mod completed_setup;
mod jwt;
@ -5,7 +6,8 @@ mod need_setup;
mod refresh_token;
pub use self::jwt::*;
pub use access_token::AccessToken;
pub use basic_auth::BasicAuth;
pub use completed_setup::CompletedSetup;
pub use need_setup::NeedSetup;
pub use refresh_token::RefreshToken;
pub use basic_auth::BasicAuth;

View 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)),
}
}
}

View file

@ -1,22 +1,21 @@
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::tokens::{
JWT_COOKIE_NAME, JWT_DURATION_MINUTES, REFRESH_TOKEN_COOKIE_NAME, REFRESH_TOKEN_DURATION_DAYS,
};
pub use admin::JwtAdmin;
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;
mod admin;
mod user;
#[derive(Debug)]
pub enum Error {
GetDatabase,

View file

@ -2,10 +2,12 @@ use authorize::*;
use redirect::*;
use rocket::{routes, Route};
use token::*;
use userinfo::*;
pub mod authorize;
pub mod redirect;
pub mod token;
pub mod userinfo;
pub fn routes() -> Vec<Route> {
routes![
@ -14,6 +16,7 @@ pub fn routes() -> Vec<Route> {
authorize_ezidam,
redirect_page,
request_token,
get_userinfo,
]
}

View 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)
}