Userinfo endpoint is working
This commit is contained in:
parent
b867016a71
commit
819210ae86
@ -50,6 +50,10 @@ pub struct FindSessionByAuthorizationCode(pub String);
|
||||
#[rtype(result = "Option<Session>")]
|
||||
pub struct FindSessionByRefreshToken(pub String);
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "Option<Session>")]
|
||||
pub struct FindSessionByAccessToken(pub String);
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct MarkAuthorizationCodeUsed(pub String);
|
||||
@ -111,6 +115,17 @@ impl Handler<FindSessionByRefreshToken> for OpenIDSessionsActor {
|
||||
}
|
||||
}
|
||||
|
||||
impl Handler<FindSessionByAccessToken> for OpenIDSessionsActor {
|
||||
type Result = Option<Session>;
|
||||
|
||||
fn handle(&mut self, msg: FindSessionByAccessToken, _ctx: &mut Self::Context) -> Self::Result {
|
||||
self.session
|
||||
.iter()
|
||||
.find(|f| f.access_token.eq(&msg.0))
|
||||
.cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl Handler<MarkAuthorizationCodeUsed> for OpenIDSessionsActor {
|
||||
type Result = ();
|
||||
|
||||
|
@ -6,8 +6,9 @@ use actix_web::{HttpRequest, HttpResponse, Responder, web};
|
||||
use actix_web::error::ErrorUnauthorized;
|
||||
use askama::Template;
|
||||
|
||||
use crate::actors::openid_sessions_actor;
|
||||
use crate::actors::{openid_sessions_actor, users_actor};
|
||||
use crate::actors::openid_sessions_actor::{OpenIDSessionsActor, Session, SessionID};
|
||||
use crate::actors::users_actor::UsersActor;
|
||||
use crate::constants::{AUTHORIZE_URI, CERT_URI, OPEN_ID_ACCESS_TOKEN_LEN, OPEN_ID_ACCESS_TOKEN_TIMEOUT, OPEN_ID_AUTHORIZATION_CODE_LEN, OPEN_ID_AUTHORIZATION_CODE_TIMEOUT, OPEN_ID_REFRESH_TOKEN_LEN, OPEN_ID_REFRESH_TOKEN_TIMEOUT, OPEN_ID_SESSION_LEN, TOKEN_URI, USERINFO_URI};
|
||||
use crate::controllers::base_controller::FatalErrorPage;
|
||||
use crate::data::app_config::AppConfig;
|
||||
@ -16,8 +17,10 @@ use crate::data::code_challenge::CodeChallenge;
|
||||
use crate::data::current_user::CurrentUser;
|
||||
use crate::data::id_token::IdToken;
|
||||
use crate::data::jwt_signer::{JsonWebKey, JWTSigner};
|
||||
use crate::data::open_id_user_info::OpenIDUserInfo;
|
||||
use crate::data::openid_config::OpenIDConfig;
|
||||
use crate::data::session_identity::SessionIdentity;
|
||||
use crate::data::user::User;
|
||||
use crate::utils::string_utils::rand_str;
|
||||
use crate::utils::time::time;
|
||||
|
||||
@ -406,21 +409,29 @@ pub struct UserInfoQuery {
|
||||
|
||||
pub async fn user_info_post(req: HttpRequest,
|
||||
form: Option<web::Form<UserInfoQuery>>,
|
||||
query: web::Query<UserInfoQuery>) -> impl Responder {
|
||||
query: web::Query<UserInfoQuery>,
|
||||
sessions: web::Data<Addr<OpenIDSessionsActor>>,
|
||||
users: web::Data<Addr<UsersActor>>) -> impl Responder {
|
||||
user_info(req,
|
||||
form
|
||||
.map(|f| f.0.access_token)
|
||||
.unwrap_or_default()
|
||||
.or(query.0.access_token),
|
||||
sessions,
|
||||
users,
|
||||
).await
|
||||
}
|
||||
|
||||
pub async fn user_info_get(req: HttpRequest, query: web::Query<UserInfoQuery>) -> impl Responder {
|
||||
user_info(req, query.0.access_token).await
|
||||
pub async fn user_info_get(req: HttpRequest, query: web::Query<UserInfoQuery>,
|
||||
sessions: web::Data<Addr<OpenIDSessionsActor>>,
|
||||
users: web::Data<Addr<UsersActor>>) -> impl Responder {
|
||||
user_info(req, query.0.access_token, sessions, users).await
|
||||
}
|
||||
|
||||
/// Authenticate request using RFC6750 <https://datatracker.ietf.org/doc/html/rfc6750>///
|
||||
async fn user_info(req: HttpRequest, token: Option<String>) -> impl Responder {
|
||||
async fn user_info(req: HttpRequest, token: Option<String>,
|
||||
sessions: web::Data<Addr<OpenIDSessionsActor>>,
|
||||
users: web::Data<Addr<UsersActor>>) -> impl Responder {
|
||||
let token = match token {
|
||||
Some(t) => t,
|
||||
None => {
|
||||
@ -443,6 +454,35 @@ async fn user_info(req: HttpRequest, token: Option<String>) -> impl Responder {
|
||||
}
|
||||
};
|
||||
|
||||
// TODO : continue <https://openid.net/specs/openid-connect-core-1_0.html#RFC6749>
|
||||
HttpResponse::Ok().body(format!("token is {}", token))
|
||||
let session: Option<Session> = sessions
|
||||
.send(openid_sessions_actor::FindSessionByAccessToken(token)).await.unwrap();
|
||||
let session = match session {
|
||||
None => {
|
||||
return user_info_error("invalid_request", "Session not found!");
|
||||
}
|
||||
Some(s) => s,
|
||||
};
|
||||
|
||||
if session.access_token_expire_at < time() {
|
||||
return user_info_error("invalid_request", "Access token has expired!");
|
||||
}
|
||||
|
||||
let user: Option<User> = users.send(users_actor::GetUserRequest(session.user)).await.unwrap().0;
|
||||
let user = match user {
|
||||
None => {
|
||||
return user_info_error("invalid_request", "Failed to extract user information!");
|
||||
}
|
||||
Some(u) => u,
|
||||
};
|
||||
|
||||
HttpResponse::Ok()
|
||||
.json(OpenIDUserInfo {
|
||||
name: user.full_name(),
|
||||
sub: user.uid,
|
||||
given_name: user.first_name,
|
||||
family_name: user.last_name,
|
||||
preferred_username: user.username,
|
||||
email: user.email,
|
||||
email_verified: true,
|
||||
})
|
||||
}
|
@ -8,4 +8,5 @@ pub mod current_user;
|
||||
pub mod openid_config;
|
||||
pub mod jwt_signer;
|
||||
pub mod id_token;
|
||||
pub mod code_challenge;
|
||||
pub mod code_challenge;
|
||||
pub mod open_id_user_info;
|
24
src/data/open_id_user_info.rs
Normal file
24
src/data/open_id_user_info.rs
Normal file
@ -0,0 +1,24 @@
|
||||
/// Refer to <https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims> for more information
|
||||
#[derive(Debug, serde::Serialize)]
|
||||
pub struct OpenIDUserInfo {
|
||||
/// Subject - Identifier for the End-User at the Issuer
|
||||
pub sub: String,
|
||||
|
||||
/// End-User's full name in displayable form including all name parts, possibly including titles and suffixes, ordered according to the End-User's locale and preferences.
|
||||
pub name: String,
|
||||
|
||||
/// Given name(s) or first name(s) of the End-User. Note that in some cultures, people can have multiple given names; all can be present, with the names being separated by space characters.
|
||||
pub given_name: String,
|
||||
|
||||
/// Surname(s) or last name(s) of the End-User. Note that in some cultures, people can have multiple family names or no family name; all can be present, with the names being separated by space characters.
|
||||
pub family_name: String,
|
||||
|
||||
/// Shorthand name by which the End-User wishes to be referred to at the RP, such as janedoe or j.doe. This value MAY be any valid JSON string including special characters such as @, /, or whitespace. The RP MUST NOT rely upon this value being unique, as discussed in
|
||||
pub preferred_username: String,
|
||||
|
||||
/// End-User's preferred e-mail address. Its value MUST conform to the RFC 5322 RFC5322 addr-spec syntax. The RP MUST NOT rely upon this value being unique, as discussed in Section 5.7.
|
||||
pub email: String,
|
||||
|
||||
/// True if the End-User's e-mail address has been verified; otherwise false. When this Claim Value is true, this means that the OP took affirmative steps to ensure that this e-mail address was controlled by the End-User at the time the verification was performed. The means by which an e-mail address is verified is context-specific, and dependent upon the trust framework or contractual agreements within which the parties are operating.
|
||||
pub email_verified: bool,
|
||||
}
|
Loading…
Reference in New Issue
Block a user