@@ -42,68 +42,101 @@ export class PasswdService extends AbstractService {
4242 }
4343
4444 public async change ( passwdDto : ChangePasswordDto ) : Promise < [ Jobs , any ] > {
45- const identity = await this . identities . findOne ( { 'inetOrgPerson.uid' : passwdDto . uid } ) as Identities ;
46-
47- return await this . backends . executeJob ( ActionType . IDENTITY_PASSWORD_CHANGE , identity . _id , {
48- ...passwdDto ,
49- ...pick ( identity . toJSON ( ) , [ 'inetOrgPerson' ] ) ,
50- } , {
51- async : false ,
52- } ) ;
45+ try {
46+ const identity = await this . identities . findOne ( { 'inetOrgPerson.uid' : passwdDto . uid } ) as Identities ;
47+
48+ return await this . backends . executeJob ( ActionType . IDENTITY_PASSWORD_CHANGE , identity . _id , {
49+ ...passwdDto ,
50+ ...pick ( identity . toJSON ( ) , [ 'inetOrgPerson' ] ) ,
51+ } , {
52+ async : false ,
53+ timeoutDiscard : true ,
54+ disableLogs : true ,
55+ } ) ;
56+ } catch ( e ) {
57+ this . logger . error ( "Error while changing password. " + e + ` (uid=${ passwdDto ?. uid } )` ) ;
58+ throw new BadRequestException ( 'Une erreur est survenue : Mot de passe incorrect ou utilisateur inconnu' ) ;
59+ }
5360 }
5461
5562 public async askToken ( askToken : AskTokenDto ) : Promise < string > {
56- await this . identities . findOne ( { 'inetOrgPerson.uid' : askToken . uid } ) ;
57-
58- const k = crypto . randomBytes ( PasswdService . RANDOM_BYTES_K ) . toString ( 'hex' ) ;
59- const iv = crypto . randomBytes ( PasswdService . RANDOM_BYTES_IV ) . toString ( 'base64' ) ;
60- const cipher = crypto . createCipheriv ( PasswdService . TOKEN_ALGORITHM , k , iv ) ;
61-
62- let ciphertext = cipher . update (
63- JSON . stringify ( < CipherData > { uid : askToken . uid , mail : askToken . mail } ) ,
64- 'utf8' ,
65- 'base64' ,
66- ) ;
67- ciphertext += cipher . final ( 'base64' ) ;
68-
69- await this . redis . set (
70- ciphertext ,
71- JSON . stringify ( < TokenData > {
72- k,
73- iv,
74- tag : cipher . getAuthTag ( ) . toString ( 'base64' ) ,
75- } ) ,
76- ) ;
77- await this . redis . expire ( ciphertext , PasswdService . TOKEN_EXPIRATION ) ;
78- return ciphertext ;
63+ try {
64+ await this . identities . findOne ( { 'inetOrgPerson.uid' : askToken . uid } ) ;
65+
66+ const k = crypto . randomBytes ( PasswdService . RANDOM_BYTES_K ) . toString ( 'hex' ) ;
67+ const iv = crypto . randomBytes ( PasswdService . RANDOM_BYTES_IV ) . toString ( 'base64' ) ;
68+ const cipher = crypto . createCipheriv ( PasswdService . TOKEN_ALGORITHM , k , iv ) ;
69+
70+ let ciphertext = cipher . update (
71+ JSON . stringify ( < CipherData > { uid : askToken . uid , mail : askToken . mail } ) ,
72+ 'utf8' ,
73+ 'base64' ,
74+ ) ;
75+ ciphertext += cipher . final ( 'base64' ) ;
76+
77+ await this . redis . set (
78+ ciphertext ,
79+ JSON . stringify ( < TokenData > {
80+ k,
81+ iv,
82+ tag : cipher . getAuthTag ( ) . toString ( 'base64' ) ,
83+ } ) ,
84+ ) ;
85+ await this . redis . expire ( ciphertext , PasswdService . TOKEN_EXPIRATION ) ;
86+ return ciphertext ;
87+ } catch ( e ) {
88+ this . logger . error ( "Error while ask token. " + e + ` (uid=${ askToken ?. uid } )` ) ;
89+ throw new BadRequestException ( 'Impossible de générer un token, une erreur est survenue' ) ;
90+ }
7991 }
8092
8193 public async decryptToken ( token : string ) : Promise < CipherData > {
8294 try {
8395 const result = await this . redis . get ( token ) ;
8496 const cypherData : TokenData = JSON . parse ( result ) ;
8597
98+ if ( cypherData ?. iv === undefined || cypherData ?. k === undefined || cypherData ?. tag === undefined ) {
99+ throw new NotFoundException ( 'Invalid token' ) ;
100+ }
101+
86102 const decipher = crypto . createDecipheriv ( PasswdService . TOKEN_ALGORITHM , cypherData . k , cypherData . iv ) ;
87103 decipher . setAuthTag ( Buffer . from ( cypherData . tag , 'base64' ) ) ;
88104 const plaintext = decipher . update ( token , 'base64' , 'ascii' ) ;
89105
90106 return JSON . parse ( plaintext ) ;
91107 } catch ( error ) {
108+ this . logger . verbose ( "Error while decrypting token. " + error + ` (token=${ token } )` ) ;
92109 throw new BadRequestException ( 'Invalid token' ) ;
93110 }
94111 }
95112
96113 public async reset ( data : ResetPasswordDto ) : Promise < [ Jobs , any ] > {
97114 const tokenData = await this . decryptToken ( data . token ) ;
98- const identity = await this . identities . findOne ( { 'inetOrgPerson.uid' : tokenData . uid } ) as Identities ;
99115
100- return await this . backends . executeJob (
101- ActionType . IDENTITY_PASSWORD_RESET ,
102- identity . _id ,
103- { uid : tokenData . uid , newPassword : data . newPassword , ...pick ( identity , [ 'inetOrgPerson' ] ) } ,
104- {
105- async : false ,
106- } ,
107- ) ;
116+ try {
117+ const identity = await this . identities . findOne ( { 'inetOrgPerson.uid' : tokenData . uid } ) as Identities ;
118+
119+ const [ _ , response ] = await this . backends . executeJob (
120+ ActionType . IDENTITY_PASSWORD_RESET ,
121+ identity . _id ,
122+ { uid : tokenData . uid , newPassword : data . newPassword , ...pick ( identity , [ 'inetOrgPerson' ] ) } ,
123+ {
124+ async : false ,
125+ timeoutDiscard : true ,
126+ disableLogs : true ,
127+ } ,
128+ ) ;
129+
130+ if ( response ?. status === 0 ) {
131+ await this . redis . del ( data . token ) ;
132+ return [ _ , response ] ;
133+ }
134+
135+ throw new InternalServerErrorException ( 'Une erreur est survenue : Impossible de réinitialiser le mot de passe' ) ;
136+
137+ } catch ( e ) {
138+ this . logger . error ( "Error while reseting password. " + e + ` (token=${ data ?. token } )` ) ;
139+ throw new BadRequestException ( 'Une erreur est survenue : Tentative de réinitialisation de mot de passe impossible' ) ;
140+ }
108141 }
109142}
0 commit comments