@@ -15,7 +15,9 @@ use mas_axum_utils::{
1515 client_authorization:: { ClientAuthorization , CredentialsVerificationError } ,
1616 record_error,
1717} ;
18- use mas_data_model:: { BoxClock , Clock , Device , TokenFormatError , TokenType } ;
18+ use mas_data_model:: {
19+ BoxClock , Clock , Device , TokenFormatError , TokenType , personal:: session:: PersonalSessionOwner ,
20+ } ;
1921use mas_iana:: oauth:: { OAuthClientAuthenticationMethod , OAuthTokenTypeHint } ;
2022use mas_keystore:: Encrypter ;
2123use mas_matrix:: HomeserverConnection ;
@@ -641,8 +643,94 @@ pub(crate) async fn post(
641643 }
642644
643645 TokenType :: PersonalAccessToken => {
644- // TODO
645- return Err ( RouteError :: UnknownToken ( TokenType :: PersonalAccessToken ) ) ;
646+ let access_token = repo
647+ . personal_access_token ( )
648+ . find_by_token ( token)
649+ . await ?
650+ . ok_or ( RouteError :: UnknownToken ( TokenType :: AccessToken ) ) ?;
651+
652+ if !access_token. is_valid ( clock. now ( ) ) {
653+ return Err ( RouteError :: InvalidToken ( TokenType :: AccessToken ) ) ;
654+ }
655+
656+ let session = repo
657+ . personal_session ( )
658+ . lookup ( access_token. session_id )
659+ . await ?
660+ . ok_or ( RouteError :: CantLoadPersonalSession ( access_token. session_id ) ) ?;
661+
662+ if !session. is_valid ( ) {
663+ return Err ( RouteError :: InvalidPersonalSession ( session. id ) ) ;
664+ }
665+
666+ let actor_user = repo
667+ . user ( )
668+ . lookup ( session. actor_user_id )
669+ . await ?
670+ . ok_or ( RouteError :: CantLoadUser ( session. actor_user_id ) ) ?;
671+
672+ if !actor_user. is_valid ( ) {
673+ return Err ( RouteError :: InvalidUser ( actor_user. id ) ) ;
674+ }
675+
676+ let client_id = match session. owner {
677+ PersonalSessionOwner :: User ( owner_user_id) => {
678+ let owner_user = repo
679+ . user ( )
680+ . lookup ( owner_user_id)
681+ . await ?
682+ . ok_or ( RouteError :: CantLoadUser ( owner_user_id) ) ?;
683+
684+ if !owner_user. is_valid ( ) {
685+ return Err ( RouteError :: InvalidUser ( owner_user. id ) ) ;
686+ }
687+
688+ None
689+ }
690+ PersonalSessionOwner :: OAuth2Client ( owner_client_id) => {
691+ let owner_client = repo
692+ . oauth2_client ( )
693+ . lookup ( owner_client_id)
694+ . await ?
695+ . ok_or ( RouteError :: CantLoadOAuth2Client ( owner_client_id) ) ?;
696+
697+ // OAuth2 clients are always valid if they're in the database
698+ Some ( owner_client. client_id . clone ( ) )
699+ }
700+ } ;
701+
702+ activity_tracker
703+ . record_personal_access_token_session ( & clock, & session, ip)
704+ . await ;
705+
706+ INTROSPECTION_COUNTER . add (
707+ 1 ,
708+ & [
709+ KeyValue :: new ( KIND , "personal_access_token" ) ,
710+ KeyValue :: new ( ACTIVE , true ) ,
711+ ] ,
712+ ) ;
713+
714+ let scope = normalize_scope ( session. scope ) ;
715+
716+ IntrospectionResponse {
717+ active : true ,
718+ scope : Some ( scope) ,
719+ client_id,
720+ username : Some ( actor_user. username ) ,
721+ token_type : Some ( OAuthTokenTypeHint :: AccessToken ) ,
722+ exp : access_token. expires_at ,
723+ expires_in : access_token
724+ . expires_at
725+ . map ( |expires_at| expires_at. signed_duration_since ( clock. now ( ) ) ) ,
726+ iat : Some ( access_token. created_at ) ,
727+ nbf : Some ( access_token. created_at ) ,
728+ sub : Some ( actor_user. sub ) ,
729+ aud : None ,
730+ iss : None ,
731+ jti : None ,
732+ device_id : None ,
733+ }
646734 }
647735 } ;
648736
0 commit comments