@@ -6,7 +6,6 @@ import {inject} from '@loopback/context';
6
6
import { AnyObject , DataObject , Model , repository } from '@loopback/repository' ;
7
7
import {
8
8
HttpErrors ,
9
- RequestContext ,
10
9
get ,
11
10
getModelSchemaRef ,
12
11
oas ,
@@ -28,7 +27,6 @@ import {
28
27
UserStatus ,
29
28
X_TS_TYPE ,
30
29
} from '@sourceloop/core' ;
31
- import crypto from 'crypto' ;
32
30
import {
33
31
AuthErrorKeys ,
34
32
AuthenticationBindings ,
@@ -38,27 +36,15 @@ import {
38
36
authenticateClient ,
39
37
} from 'loopback4-authentication' ;
40
38
import { AuthorizeErrorKeys , authorize } from 'loopback4-authorization' ;
41
- import moment from 'moment-timezone' ;
42
39
import { LoginType } from '../../../enums' ;
43
- import { AuthServiceBindings } from '../../../keys' ;
44
- import {
45
- AuthClient ,
46
- LoginActivity ,
47
- RefreshToken ,
48
- User ,
49
- UserTenant ,
50
- } from '../../../models' ;
40
+ import { AuthClient , RefreshToken , User } from '../../../models' ;
51
41
import {
52
42
AuthCodeBindings ,
53
43
AuthCodeGeneratorFn ,
54
- JWTSignerFn ,
55
- JWTVerifierFn ,
56
- JwtPayloadFn ,
57
44
UserValidationServiceBindings ,
58
45
} from '../../../providers' ;
59
46
import {
60
47
AuthClientRepository ,
61
- LoginActivityRepository ,
62
48
OtpCacheRepository ,
63
49
RefreshTokenRepository ,
64
50
RevokedTokenRepository ,
@@ -71,12 +57,7 @@ import {
71
57
UserTenantRepository ,
72
58
} from '../../../repositories' ;
73
59
import { IdpLoginService , LoginHelperService } from '../../../services' ;
74
- import {
75
- ActorId ,
76
- ExternalTokens ,
77
- IUserActivity ,
78
- UserValidationFn ,
79
- } from '../../../types' ;
60
+ import { UserValidationFn } from '../../../types' ;
80
61
import {
81
62
AuthRefreshTokenRequest ,
82
63
AuthTokenRequest ,
@@ -116,27 +97,14 @@ export class LoginController {
116
97
@repository ( UserCredentialsRepository )
117
98
public userCredsRepository : UserCredentialsRepository ,
118
99
@inject ( LOGGER . LOGGER_INJECT ) public logger : ILogger ,
119
- @inject ( AuthServiceBindings . JWTPayloadProvider )
120
- private readonly getJwtPayload : JwtPayloadFn ,
121
100
@inject ( 'services.LoginHelperService' )
122
101
private readonly loginHelperService : LoginHelperService ,
123
102
@inject ( 'services.IdpLoginService' )
124
103
private readonly idpLoginService : IdpLoginService ,
125
104
@inject ( AuthCodeBindings . AUTH_CODE_GENERATOR_PROVIDER )
126
105
private readonly getAuthCode : AuthCodeGeneratorFn ,
127
- @inject ( AuthCodeBindings . JWT_SIGNER )
128
- private readonly jwtSigner : JWTSignerFn < object > ,
129
- @repository ( LoginActivityRepository )
130
- private readonly loginActivityRepo : LoginActivityRepository ,
131
- @inject ( AuthServiceBindings . ActorIdKey )
132
- private readonly actorKey : ActorId ,
133
- @inject . context ( ) private readonly ctx : RequestContext ,
134
106
@inject ( UserValidationServiceBindings . VALIDATE_USER )
135
107
private readonly userValidationProvider : UserValidationFn ,
136
- @inject ( AuthCodeBindings . JWT_VERIFIER . key )
137
- private readonly jwtVerifier : JWTVerifierFn < AnyObject > ,
138
- @inject ( AuthServiceBindings . MarkUserActivity , { optional : true } )
139
- private readonly userActivity ?: IUserActivity ,
140
108
) { }
141
109
142
110
@authenticateClient ( STRATEGY . CLIENT_PASSWORD )
@@ -232,7 +200,11 @@ export class LoginController {
232
200
await this . userRepo . updateLastLogin ( payload . user . id ) ;
233
201
}
234
202
235
- return await this . createJWT ( payload , this . client , LoginType . ACCESS ) ;
203
+ return await this . idpLoginService . createJWT (
204
+ payload ,
205
+ this . client ,
206
+ LoginType . ACCESS ,
207
+ ) ;
236
208
} catch ( error ) {
237
209
this . logger . error ( error ) ;
238
210
throw new HttpErrors . Unauthorized ( AuthErrorKeys . InvalidCredentials ) ;
@@ -297,7 +269,7 @@ export class LoginController {
297
269
) ;
298
270
299
271
if ( isAuthenticated ) {
300
- return this . createJWT (
272
+ return this . idpLoginService . createJWT (
301
273
{
302
274
clientId : payload . refreshPayload . clientId ,
303
275
userId : payload . refreshPayload . userId ,
@@ -546,7 +518,7 @@ export class LoginController {
546
518
}
547
519
548
520
const payload = await this . createTokenPayload ( req ) ;
549
- return this . createJWT (
521
+ return this . idpLoginService . createJWT (
550
522
{
551
523
clientId : payload . refreshPayload . clientId ,
552
524
user : this . user ,
@@ -590,159 +562,4 @@ export class LoginController {
590
562
authClient : authClient ,
591
563
} ;
592
564
}
593
- private async createJWT (
594
- payload : ClientAuthCode < User , typeof User . prototype . id > & ExternalTokens ,
595
- authClient : AuthClient ,
596
- loginType : LoginType ,
597
- tenantId ?: string ,
598
- ) : Promise < TokenResponse > {
599
- try {
600
- const size = 32 ;
601
- const ms = 1000 ;
602
- let user : User | undefined ;
603
- if ( payload . user ) {
604
- user = payload . user ;
605
- } else if ( payload . userId ) {
606
- user = await this . userRepo . findById ( payload . userId , {
607
- include : [
608
- {
609
- relation : 'defaultTenant' ,
610
- } ,
611
- ] ,
612
- } ) ;
613
- if ( payload . externalAuthToken && payload . externalRefreshToken ) {
614
- ( user as AuthUser ) . externalAuthToken = payload . externalAuthToken ;
615
- ( user as AuthUser ) . externalRefreshToken =
616
- payload . externalRefreshToken ;
617
- }
618
- } else {
619
- // Do nothing and move ahead
620
- }
621
- if ( ! user ) {
622
- throw new HttpErrors . Unauthorized (
623
- AuthenticateErrorKeys . UserDoesNotExist ,
624
- ) ;
625
- }
626
- const data : AnyObject = await this . getJwtPayload (
627
- user ,
628
- authClient ,
629
- tenantId ,
630
- ) ;
631
- const accessToken = await this . jwtSigner ( data , {
632
- expiresIn : authClient . accessTokenExpiration ,
633
- } ) ;
634
- const refreshToken : string = crypto . randomBytes ( size ) . toString ( 'hex' ) ;
635
- // Set refresh token into redis for later verification
636
- await this . refreshTokenRepo . set (
637
- refreshToken ,
638
- {
639
- clientId : authClient . clientId ,
640
- userId : user . id ,
641
- username : user . username ,
642
- accessToken,
643
- externalAuthToken : ( user as AuthUser ) . externalAuthToken ,
644
- externalRefreshToken : ( user as AuthUser ) . externalRefreshToken ,
645
- tenantId : data . tenantId ,
646
- } ,
647
- { ttl : authClient . refreshTokenExpiration * ms } ,
648
- ) ;
649
-
650
- const userTenant = await this . userTenantRepo . findOne ( {
651
- where : { userId : user . id } ,
652
- } ) ;
653
- if ( this . userActivity ?. markUserActivity )
654
- this . markUserActivity ( user , userTenant , { ...data } , loginType ) ;
655
-
656
- return new TokenResponse ( {
657
- accessToken,
658
- refreshToken,
659
- expires : moment ( )
660
- . add ( authClient . accessTokenExpiration , 's' )
661
- . toDate ( )
662
- . getTime ( ) ,
663
- } ) ;
664
- } catch ( error ) {
665
- this . logger . error ( error ) ;
666
- if ( HttpErrors . HttpError . prototype . isPrototypeOf ( error ) ) {
667
- throw error ;
668
- } else {
669
- throw new HttpErrors . Unauthorized ( AuthErrorKeys . InvalidCredentials ) ;
670
- }
671
- }
672
- }
673
-
674
- private markUserActivity (
675
- user : User ,
676
- userTenant : UserTenant | null ,
677
- payload : AnyObject ,
678
- loginType : LoginType ,
679
- ) {
680
- const size = 16 ;
681
- const encryptionKey = process . env . ENCRYPTION_KEY ;
682
-
683
- if ( encryptionKey ) {
684
- const iv = crypto . randomBytes ( size ) ;
685
-
686
- /* encryption of IP Address */
687
- const cipherIp = crypto . createCipheriv ( 'aes-256-gcm' , encryptionKey , iv ) ;
688
- const ip =
689
- this . ctx . request . headers [ 'x-forwarded-for' ] ?. toString ( ) ??
690
- this . ctx . request . socket . remoteAddress ?. toString ( ) ??
691
- '' ;
692
- const encyptIp = Buffer . concat ( [
693
- cipherIp . update ( ip , 'utf8' ) ,
694
- cipherIp . final ( ) ,
695
- ] ) ;
696
- const authTagIp = cipherIp . getAuthTag ( ) ;
697
- const ipAddress = JSON . stringify ( {
698
- iv : iv . toString ( 'hex' ) ,
699
- encryptedData : encyptIp . toString ( 'hex' ) ,
700
- authTag : authTagIp . toString ( 'hex' ) ,
701
- } ) ;
702
-
703
- /* encryption of Paylolad Address */
704
- const cipherPayload = crypto . createCipheriv (
705
- 'aes-256-gcm' ,
706
- encryptionKey ,
707
- iv ,
708
- ) ;
709
- const activityPayload = JSON . stringify ( payload ) ;
710
- const encyptPayload = Buffer . concat ( [
711
- cipherPayload . update ( activityPayload , 'utf8' ) ,
712
- cipherPayload . final ( ) ,
713
- ] ) ;
714
- const authTagPayload = cipherIp . getAuthTag ( ) ;
715
- const tokenPayload = JSON . stringify ( {
716
- iv : iv . toString ( 'hex' ) ,
717
- encryptedData : encyptPayload . toString ( 'hex' ) ,
718
- authTag : authTagPayload . toString ( 'hex' ) ,
719
- } ) ;
720
- // make an entry to mark the users login activity
721
- let actor : string ;
722
- let tenantId : string ;
723
- if ( userTenant ) {
724
- actor = userTenant [ this . actorKey ] ?. toString ( ) ?? '0' ;
725
- tenantId = userTenant . tenantId ;
726
- } else {
727
- actor = user [ 'id' ] ?. toString ( ) ?? '0' ;
728
- tenantId = user . defaultTenantId ;
729
- }
730
- const loginActivity = new LoginActivity ( {
731
- actor,
732
- tenantId,
733
- loginTime : new Date ( ) ,
734
- tokenPayload,
735
- loginType,
736
- deviceInfo : this . ctx . request . headers [ 'user-agent' ] ?. toString ( ) ,
737
- ipAddress,
738
- } ) ;
739
- this . loginActivityRepo . create ( loginActivity ) . catch ( ( ) => {
740
- this . logger . error (
741
- `Failed to add the login activity => ${ JSON . stringify (
742
- loginActivity ,
743
- ) } `,
744
- ) ;
745
- } ) ;
746
- }
747
- }
748
565
}
0 commit comments