@breadstone/archipel-platform-authentication 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/README.md +47 -0
  2. package/package.json +67 -0
  3. package/src/AuthModule.d.ts +57 -0
  4. package/src/AuthModule.js +158 -0
  5. package/src/contracts/AuthSubjectPort.d.ts +33 -0
  6. package/src/contracts/AuthSubjectPort.js +15 -0
  7. package/src/contracts/IAuthSubject.d.ts +40 -0
  8. package/src/contracts/IAuthSubject.js +3 -0
  9. package/src/contracts/IMfaSubject.d.ts +48 -0
  10. package/src/contracts/IMfaSubject.js +3 -0
  11. package/src/contracts/IMfaSubjectUpdate.d.ts +16 -0
  12. package/src/contracts/IMfaSubjectUpdate.js +3 -0
  13. package/src/contracts/ISessionRecord.d.ts +22 -0
  14. package/src/contracts/ISessionRecord.js +3 -0
  15. package/src/contracts/ISocialProfile.d.ts +23 -0
  16. package/src/contracts/ISocialProfile.js +3 -0
  17. package/src/contracts/IStoreSessionArgs.d.ts +14 -0
  18. package/src/contracts/IStoreSessionArgs.js +4 -0
  19. package/src/contracts/IVerifiableSubject.d.ts +28 -0
  20. package/src/contracts/IVerifiableSubject.js +3 -0
  21. package/src/contracts/MfaSubjectPort.d.ts +26 -0
  22. package/src/contracts/MfaSubjectPort.js +15 -0
  23. package/src/contracts/SessionPersistencePort.d.ts +58 -0
  24. package/src/contracts/SessionPersistencePort.js +15 -0
  25. package/src/contracts/SocialAuthPort.d.ts +19 -0
  26. package/src/contracts/SocialAuthPort.js +15 -0
  27. package/src/contracts/TokenEnricherPort.d.ts +17 -0
  28. package/src/contracts/TokenEnricherPort.js +15 -0
  29. package/src/contracts/VerificationSubjectPort.d.ts +40 -0
  30. package/src/contracts/VerificationSubjectPort.js +15 -0
  31. package/src/contracts/index.d.ts +13 -0
  32. package/src/contracts/index.js +16 -0
  33. package/src/decorators/RolesDecorator.d.ts +12 -0
  34. package/src/decorators/RolesDecorator.js +23 -0
  35. package/src/decorators/TokenDecorator.d.ts +6 -0
  36. package/src/decorators/TokenDecorator.js +20 -0
  37. package/src/decorators/UserDecorator.d.ts +6 -0
  38. package/src/decorators/UserDecorator.js +16 -0
  39. package/src/decorators/index.d.ts +3 -0
  40. package/src/decorators/index.js +7 -0
  41. package/src/env.d.ts +57 -0
  42. package/src/env.js +179 -0
  43. package/src/guards/AnonymousAuthGuard.d.ts +9 -0
  44. package/src/guards/AnonymousAuthGuard.js +20 -0
  45. package/src/guards/GithubAuthGuard.d.ts +9 -0
  46. package/src/guards/GithubAuthGuard.js +20 -0
  47. package/src/guards/JwtAuthGuard.d.ts +9 -0
  48. package/src/guards/JwtAuthGuard.js +20 -0
  49. package/src/guards/LocalAuthGuard.d.ts +9 -0
  50. package/src/guards/LocalAuthGuard.js +20 -0
  51. package/src/guards/RolesGuard.d.ts +16 -0
  52. package/src/guards/RolesGuard.js +43 -0
  53. package/src/guards/SocialAuthGuard.d.ts +9 -0
  54. package/src/guards/SocialAuthGuard.js +35 -0
  55. package/src/guards/_RefreshTokenAuthGuard.d.ts +0 -0
  56. package/src/guards/_RefreshTokenAuthGuard.js +2 -0
  57. package/src/guards/_TwoFactorAuthGuard.d.ts +0 -0
  58. package/src/guards/_TwoFactorAuthGuard.js +2 -0
  59. package/src/guards/index.d.ts +6 -0
  60. package/src/guards/index.js +12 -0
  61. package/src/index.d.ts +9 -0
  62. package/src/index.js +13 -0
  63. package/src/mappers/SessionMappingProfile.d.ts +42 -0
  64. package/src/mappers/SessionMappingProfile.js +68 -0
  65. package/src/middlewares/LastActiveMiddleware.d.ts +29 -0
  66. package/src/middlewares/LastActiveMiddleware.js +55 -0
  67. package/src/middlewares/index.d.ts +1 -0
  68. package/src/middlewares/index.js +5 -0
  69. package/src/models/IMfaChallengePayload.d.ts +31 -0
  70. package/src/models/IMfaChallengePayload.js +3 -0
  71. package/src/models/IMfaConfirmation.d.ts +11 -0
  72. package/src/models/IMfaConfirmation.js +3 -0
  73. package/src/models/IMfaSetup.d.ts +23 -0
  74. package/src/models/IMfaSetup.js +3 -0
  75. package/src/models/ISignInResult.d.ts +31 -0
  76. package/src/models/ISignInResult.js +3 -0
  77. package/src/models/JwtPayloadBase.d.ts +44 -0
  78. package/src/models/JwtPayloadBase.js +55 -0
  79. package/src/models/index.d.ts +6 -0
  80. package/src/models/index.js +10 -0
  81. package/src/models/responses/SessionResponse.d.ts +20 -0
  82. package/src/models/responses/SessionResponse.js +164 -0
  83. package/src/models/responses/index.d.ts +1 -0
  84. package/src/models/responses/index.js +5 -0
  85. package/src/serializer/SessionSerializer.d.ts +5 -0
  86. package/src/serializer/SessionSerializer.js +23 -0
  87. package/src/services/AuthTokenService.d.ts +30 -0
  88. package/src/services/AuthTokenService.js +58 -0
  89. package/src/services/ChallengeService.d.ts +41 -0
  90. package/src/services/ChallengeService.js +89 -0
  91. package/src/services/MfaService.d.ts +60 -0
  92. package/src/services/MfaService.js +251 -0
  93. package/src/services/SessionService.d.ts +66 -0
  94. package/src/services/SessionService.js +108 -0
  95. package/src/services/VerificationService.d.ts +56 -0
  96. package/src/services/VerificationService.js +124 -0
  97. package/src/services/index.d.ts +5 -0
  98. package/src/services/index.js +9 -0
  99. package/src/services/mfa/IMfaChannel.d.ts +40 -0
  100. package/src/services/mfa/IMfaChannel.js +4 -0
  101. package/src/services/mfa/MfaEncryptionService.d.ts +23 -0
  102. package/src/services/mfa/MfaEncryptionService.js +59 -0
  103. package/src/services/mfa/MfaState.d.ts +38 -0
  104. package/src/services/mfa/MfaState.js +23 -0
  105. package/src/services/mfa/MfaTokens.d.ts +4 -0
  106. package/src/services/mfa/MfaTokens.js +8 -0
  107. package/src/services/mfa/channels/EmailOtpMfaChannel.d.ts +21 -0
  108. package/src/services/mfa/channels/EmailOtpMfaChannel.js +152 -0
  109. package/src/services/mfa/channels/PushMfaChannel.d.ts +25 -0
  110. package/src/services/mfa/channels/PushMfaChannel.js +150 -0
  111. package/src/services/mfa/channels/SmsMfaChannel.d.ts +21 -0
  112. package/src/services/mfa/channels/SmsMfaChannel.js +158 -0
  113. package/src/services/mfa/channels/TotpMfaChannel.d.ts +19 -0
  114. package/src/services/mfa/channels/TotpMfaChannel.js +100 -0
  115. package/src/strategies/AnonymousStrategy.d.ts +32 -0
  116. package/src/strategies/AnonymousStrategy.js +53 -0
  117. package/src/strategies/AppleStrategy.d.ts +38 -0
  118. package/src/strategies/AppleStrategy.js +79 -0
  119. package/src/strategies/GithubStrategy.d.ts +24 -0
  120. package/src/strategies/GithubStrategy.js +65 -0
  121. package/src/strategies/GoogleStrategy.d.ts +34 -0
  122. package/src/strategies/GoogleStrategy.js +74 -0
  123. package/src/strategies/JwtStrategy.d.ts +31 -0
  124. package/src/strategies/JwtStrategy.js +55 -0
  125. package/src/strategies/LocalStrategy.d.ts +31 -0
  126. package/src/strategies/LocalStrategy.js +56 -0
  127. package/src/strategies/MicrosoftStrategy.d.ts +35 -0
  128. package/src/strategies/MicrosoftStrategy.js +75 -0
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ // #region Imports
3
+ var SmsMfaChannel_1;
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.SmsMfaChannel = void 0;
6
+ const tslib_1 = require("tslib");
7
+ const archipel_platform_core_1 = require("@breadstone/archipel-platform-core");
8
+ const common_1 = require("@nestjs/common");
9
+ const node_crypto_1 = require("node:crypto");
10
+ const MfaSubjectPort_1 = require("../../../contracts/MfaSubjectPort");
11
+ const MfaState_1 = require("../MfaState");
12
+ // #endregion
13
+ let SmsMfaChannel = SmsMfaChannel_1 = class SmsMfaChannel {
14
+ // #endregion
15
+ // #region Ctor
16
+ constructor(mfaSubject, configService, bcryptService) {
17
+ // #region Fields
18
+ this.method = 'sms';
19
+ this._logger = new common_1.Logger(SmsMfaChannel_1.name);
20
+ this._mfaSubject = mfaSubject;
21
+ this._configService = configService;
22
+ this._bcryptService = bcryptService;
23
+ this._ttlMilliseconds = archipel_platform_core_1.DateTimeUtils.parse(this._configService.tryGet('AUTH_MFA_SMS_CODE_TTL', '10m'));
24
+ this._minResendMilliseconds = archipel_platform_core_1.DateTimeUtils.parse(this._configService.tryGet('AUTH_MFA_SMS_MIN_RESEND', '30s'));
25
+ }
26
+ // #endregion
27
+ // #region Methods
28
+ async initSetup(userId, context) {
29
+ const user = await this._mfaSubject.findById(userId);
30
+ if (!user) {
31
+ throw new common_1.BadRequestException('User not found');
32
+ }
33
+ const phone = context?.phoneNumber ?? user.phoneNumber;
34
+ if (!phone) {
35
+ throw new common_1.BadRequestException('Phone number is required for SMS MFA');
36
+ }
37
+ const state = (0, MfaState_1.resolveMfaState)(user.mfaChannels);
38
+ const channel = state.channels[this.method] ?? { enabled: false };
39
+ const now = Date.now();
40
+ if (channel.lastSentAt && now - Date.parse(channel.lastSentAt) < this._minResendMilliseconds) {
41
+ throw new common_1.BadRequestException('OTP recently sent. Please wait before requesting another code.');
42
+ }
43
+ const code = this.generateCode();
44
+ const hashed = await this._bcryptService.hash(code);
45
+ state.channels[this.method] = {
46
+ enabled: false,
47
+ phoneNumber: phone,
48
+ codeHash: hashed,
49
+ codeExpiresAt: new Date(now + this._ttlMilliseconds).toISOString(),
50
+ lastSentAt: new Date(now).toISOString(),
51
+ };
52
+ state.preferredMethod = state.preferredMethod ?? this.method;
53
+ await this._mfaSubject.updateMfaState(userId, {
54
+ phoneNumber: phone,
55
+ mfaChannels: state,
56
+ mfaPreferredMethod: state.preferredMethod,
57
+ mfaUpdatedAt: new Date(),
58
+ });
59
+ this._logger.log(`Sending SMS MFA code to ${phone} (mock): ${code}`);
60
+ return {
61
+ method: this.method,
62
+ };
63
+ }
64
+ async verifySetup(userId, code) {
65
+ return this.verifyCodeAndMaybeEnable(userId, code, true);
66
+ }
67
+ async verifyChallenge(userId, code) {
68
+ return this.verifyCodeAndMaybeEnable(userId, code, false);
69
+ }
70
+ async issueChallenge(userId) {
71
+ const user = await this._mfaSubject.findById(userId);
72
+ if (!user) {
73
+ throw new common_1.BadRequestException('User not found');
74
+ }
75
+ const state = (0, MfaState_1.resolveMfaState)(user.mfaChannels);
76
+ const channel = state.channels[this.method];
77
+ if (!channel?.enabled) {
78
+ throw new common_1.UnauthorizedException('SMS MFA is not enabled');
79
+ }
80
+ const phone = channel.phoneNumber ?? user.phoneNumber;
81
+ if (!phone) {
82
+ throw new common_1.BadRequestException('Phone number is required for SMS MFA');
83
+ }
84
+ const now = Date.now();
85
+ if (channel.lastSentAt && now - Date.parse(channel.lastSentAt) < this._minResendMilliseconds) {
86
+ throw new common_1.BadRequestException('OTP recently sent. Please wait before requesting another code.');
87
+ }
88
+ const code = this.generateCode();
89
+ const hashed = await this._bcryptService.hash(code);
90
+ state.channels[this.method] = {
91
+ ...channel,
92
+ phoneNumber: phone,
93
+ codeHash: hashed,
94
+ codeExpiresAt: new Date(now + this._ttlMilliseconds).toISOString(),
95
+ lastSentAt: new Date(now).toISOString(),
96
+ };
97
+ await this._mfaSubject.updateMfaState(userId, {
98
+ mfaChannels: state,
99
+ mfaUpdatedAt: new Date(),
100
+ });
101
+ this._logger.log(`Sending SMS MFA code to ${phone} (login): ${code}`);
102
+ }
103
+ async verifyCodeAndMaybeEnable(userId, code, enable) {
104
+ const user = await this._mfaSubject.findById(userId);
105
+ if (!user) {
106
+ throw new common_1.BadRequestException('User not found');
107
+ }
108
+ const state = (0, MfaState_1.resolveMfaState)(user.mfaChannels);
109
+ const channel = state.channels[this.method];
110
+ if (!channel?.codeHash || !channel.codeExpiresAt) {
111
+ throw new common_1.UnauthorizedException('SMS code not issued');
112
+ }
113
+ if (Date.parse(channel.codeExpiresAt) < Date.now()) {
114
+ throw new common_1.UnauthorizedException('SMS code expired');
115
+ }
116
+ const isValid = await this._bcryptService.compare(code, channel.codeHash);
117
+ if (!isValid) {
118
+ return false;
119
+ }
120
+ if (enable) {
121
+ state.channels[this.method] = {
122
+ ...channel,
123
+ enabled: true,
124
+ verifiedAt: new Date().toISOString(),
125
+ codeHash: undefined,
126
+ codeExpiresAt: undefined,
127
+ };
128
+ await this._mfaSubject.updateMfaState(userId, {
129
+ mfaChannels: state,
130
+ mfaEnabled: true,
131
+ mfaPreferredMethod: state.preferredMethod ?? this.method,
132
+ mfaVerifiedAt: new Date(),
133
+ mfaUpdatedAt: new Date(),
134
+ });
135
+ }
136
+ else {
137
+ state.channels[this.method] = {
138
+ ...channel,
139
+ codeHash: undefined,
140
+ codeExpiresAt: undefined,
141
+ };
142
+ await this._mfaSubject.updateMfaState(userId, {
143
+ mfaChannels: state,
144
+ mfaUpdatedAt: new Date(),
145
+ });
146
+ }
147
+ return true;
148
+ }
149
+ generateCode() {
150
+ return (0, node_crypto_1.randomInt)(100000, 999999).toString();
151
+ }
152
+ };
153
+ exports.SmsMfaChannel = SmsMfaChannel;
154
+ exports.SmsMfaChannel = SmsMfaChannel = SmsMfaChannel_1 = tslib_1.__decorate([
155
+ (0, common_1.Injectable)(),
156
+ tslib_1.__metadata("design:paramtypes", [MfaSubjectPort_1.MfaSubjectPort, archipel_platform_core_1.ConfigService, archipel_platform_core_1.BcryptService])
157
+ ], SmsMfaChannel);
158
+ //# sourceMappingURL=SmsMfaChannel.js.map
@@ -0,0 +1,19 @@
1
+ import { ConfigService, IOtpService } from '@breadstone/archipel-platform-core';
2
+ import { MfaSubjectPort } from '../../../contracts/MfaSubjectPort';
3
+ import { IMfaSetup } from '../../../models';
4
+ import { IMfaChannel } from '../IMfaChannel';
5
+ import { MfaEncryptionService } from '../MfaEncryptionService';
6
+ import { IMfaSetupContext } from '../MfaState';
7
+ export declare class TotpMfaChannel implements IMfaChannel {
8
+ readonly method = "totp";
9
+ private readonly _mfaSubject;
10
+ private readonly _configService;
11
+ private readonly _encryptionService;
12
+ private readonly _otpService;
13
+ private readonly _issuer;
14
+ constructor(mfaSubject: MfaSubjectPort, configService: ConfigService, encryptionService: MfaEncryptionService, otpService: IOtpService);
15
+ initSetup(userId: string, _context?: IMfaSetupContext): Promise<IMfaSetup>;
16
+ verifySetup(userId: string, code: string): Promise<boolean>;
17
+ verifyChallenge(userId: string, code: string): Promise<boolean>;
18
+ private loadState;
19
+ }
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ // #region Imports
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.TotpMfaChannel = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const archipel_platform_core_1 = require("@breadstone/archipel-platform-core");
7
+ const common_1 = require("@nestjs/common");
8
+ const MfaSubjectPort_1 = require("../../../contracts/MfaSubjectPort");
9
+ const MfaEncryptionService_1 = require("../MfaEncryptionService");
10
+ const MfaState_1 = require("../MfaState");
11
+ // #endregion
12
+ let TotpMfaChannel = class TotpMfaChannel {
13
+ // #endregion
14
+ // #region Ctor
15
+ constructor(mfaSubject, configService, encryptionService, otpService) {
16
+ // #region Fields
17
+ this.method = 'totp';
18
+ this._mfaSubject = mfaSubject;
19
+ this._configService = configService;
20
+ this._encryptionService = encryptionService;
21
+ this._otpService = otpService;
22
+ this._issuer = this._configService.tryGet('AUTH_MFA_ISSUER', 'Strivio');
23
+ }
24
+ // #endregion
25
+ // #region Methods
26
+ async initSetup(userId, _context) {
27
+ const user = await this._mfaSubject.findById(userId);
28
+ if (!user) {
29
+ throw new common_1.BadRequestException('User not found');
30
+ }
31
+ const accountLabel = user.email ?? user.userName ?? user.id;
32
+ const secret = this._otpService.generateSecret();
33
+ const encryptedSecret = this._encryptionService.encrypt(secret);
34
+ const state = (0, MfaState_1.resolveMfaState)(user.mfaChannels);
35
+ state.channels[this.method] = {
36
+ enabled: false,
37
+ secret: encryptedSecret,
38
+ };
39
+ state.preferredMethod = state.preferredMethod ?? this.method;
40
+ await this._mfaSubject.updateMfaState(userId, {
41
+ mfaChannels: state,
42
+ mfaEnabled: user.mfaEnabled ?? false,
43
+ mfaPreferredMethod: state.preferredMethod ?? this.method,
44
+ mfaUpdatedAt: new Date(),
45
+ });
46
+ const otpauthUrl = this._otpService.generateUri({ label: accountLabel, issuer: this._issuer, secret });
47
+ return {
48
+ method: this.method,
49
+ secret: secret,
50
+ otpauthUrl: otpauthUrl,
51
+ };
52
+ }
53
+ async verifySetup(userId, code) {
54
+ const state = await this.loadState(userId);
55
+ const channel = state.channels[this.method];
56
+ if (!channel?.secret) {
57
+ throw new common_1.BadRequestException('TOTP setup not initialized');
58
+ }
59
+ const secret = this._encryptionService.decrypt(channel.secret);
60
+ const isValid = this._otpService.verify(code, secret);
61
+ if (isValid) {
62
+ channel.enabled = true;
63
+ channel.verifiedAt = new Date().toISOString();
64
+ await this._mfaSubject.updateMfaState(userId, {
65
+ mfaChannels: state,
66
+ mfaEnabled: true,
67
+ mfaPreferredMethod: state.preferredMethod ?? this.method,
68
+ mfaVerifiedAt: new Date(),
69
+ mfaUpdatedAt: new Date(),
70
+ });
71
+ }
72
+ return isValid;
73
+ }
74
+ async verifyChallenge(userId, code) {
75
+ const state = await this.loadState(userId);
76
+ const channel = state.channels[this.method];
77
+ if (!channel?.enabled || !channel.secret) {
78
+ return false;
79
+ }
80
+ const secret = this._encryptionService.decrypt(channel.secret);
81
+ const isValid = this._otpService.verify(code, secret);
82
+ return isValid;
83
+ }
84
+ async loadState(userId) {
85
+ const user = await this._mfaSubject.findById(userId);
86
+ if (!user) {
87
+ throw new common_1.BadRequestException('User not found');
88
+ }
89
+ return (0, MfaState_1.resolveMfaState)(user.mfaChannels);
90
+ }
91
+ };
92
+ exports.TotpMfaChannel = TotpMfaChannel;
93
+ exports.TotpMfaChannel = TotpMfaChannel = tslib_1.__decorate([
94
+ (0, common_1.Injectable)(),
95
+ tslib_1.__param(3, (0, common_1.Inject)(archipel_platform_core_1.OTP_SERVICE_TOKEN)),
96
+ tslib_1.__metadata("design:paramtypes", [MfaSubjectPort_1.MfaSubjectPort,
97
+ archipel_platform_core_1.ConfigService,
98
+ MfaEncryptionService_1.MfaEncryptionService, Object])
99
+ ], TotpMfaChannel);
100
+ //# sourceMappingURL=TotpMfaChannel.js.map
@@ -0,0 +1,32 @@
1
+ import { ConfigService } from '@breadstone/archipel-platform-core';
2
+ import { Strategy } from 'passport-custom';
3
+ import { AuthSubjectPort } from '../contracts/AuthSubjectPort';
4
+ import type { IAuthSubject } from '../contracts/IAuthSubject';
5
+ declare const AnonymousStrategy_base: new () => Strategy & {
6
+ validate(...args: any[]): unknown;
7
+ };
8
+ /**
9
+ * Anonymous strategy for temporary user login.
10
+ *
11
+ * @public
12
+ */
13
+ export declare class AnonymousStrategy extends AnonymousStrategy_base {
14
+ private readonly _authSubject;
15
+ private readonly _configService;
16
+ /**
17
+ * Constructs a new instance of the `AnonymousStrategy` class.
18
+ *
19
+ * @public
20
+ * @param authSubject Auth subject port instance.
21
+ * @param configService Configuration service instance.
22
+ */
23
+ constructor(authSubject: AuthSubjectPort, configService: ConfigService);
24
+ /**
25
+ * Validates the authentication credentials.
26
+ *
27
+ * @public
28
+ * @returns The authenticated user and this is also later available in the request.user object
29
+ */
30
+ validate(): Promise<IAuthSubject>;
31
+ }
32
+ export {};
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ // #region Imports
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.AnonymousStrategy = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const archipel_platform_core_1 = require("@breadstone/archipel-platform-core");
7
+ const common_1 = require("@nestjs/common");
8
+ const passport_1 = require("@nestjs/passport");
9
+ const passport_custom_1 = require("passport-custom");
10
+ const AuthSubjectPort_1 = require("../contracts/AuthSubjectPort");
11
+ // #endregion
12
+ /**
13
+ * Anonymous strategy for temporary user login.
14
+ *
15
+ * @public
16
+ */
17
+ let AnonymousStrategy = class AnonymousStrategy extends (0, passport_1.PassportStrategy)(passport_custom_1.Strategy, 'anonymous') {
18
+ // #endregion
19
+ // #region Ctor
20
+ /**
21
+ * Constructs a new instance of the `AnonymousStrategy` class.
22
+ *
23
+ * @public
24
+ * @param authSubject Auth subject port instance.
25
+ * @param configService Configuration service instance.
26
+ */
27
+ constructor(authSubject, configService) {
28
+ super();
29
+ this._authSubject = authSubject;
30
+ this._configService = configService;
31
+ }
32
+ // #endregion
33
+ // #region Methods
34
+ /**
35
+ * Validates the authentication credentials.
36
+ *
37
+ * @public
38
+ * @returns The authenticated user and this is also later available in the request.user object
39
+ */
40
+ async validate() {
41
+ const user = await this._authSubject.findAnonymous(this._configService.get('SEED_ANONYMOUS_USERNAME'));
42
+ if (!user) {
43
+ throw new common_1.NotFoundException('User not found');
44
+ }
45
+ return user;
46
+ }
47
+ };
48
+ exports.AnonymousStrategy = AnonymousStrategy;
49
+ exports.AnonymousStrategy = AnonymousStrategy = tslib_1.__decorate([
50
+ (0, common_1.Injectable)(),
51
+ tslib_1.__metadata("design:paramtypes", [AuthSubjectPort_1.AuthSubjectPort, archipel_platform_core_1.ConfigService])
52
+ ], AnonymousStrategy);
53
+ //# sourceMappingURL=AnonymousStrategy.js.map
@@ -0,0 +1,38 @@
1
+ import { ConfigService } from '@breadstone/archipel-platform-core';
2
+ import type { Profile as PassportProfile } from 'passport';
3
+ import type { IAuthSubject } from '../contracts/IAuthSubject';
4
+ import { SocialAuthPort } from '../contracts/SocialAuthPort';
5
+ type IAppleProfile = PassportProfile & {
6
+ email?: string;
7
+ };
8
+ declare const AppleStrategy_base: new (...args: [options: import("passport-apple").AuthenticateOptionsWithRequest] | [options: import("passport-apple").AuthenticateOptions]) => import("passport-apple") & {
9
+ validate(...args: any[]): unknown;
10
+ };
11
+ /**
12
+ * The `AppleStrategy` integrates Apple Sign In authentication.
13
+ *
14
+ * @public
15
+ */
16
+ export declare class AppleStrategy extends AppleStrategy_base {
17
+ private readonly _socialAuth;
18
+ /**
19
+ * Initializes a new instance of the `AppleStrategy` class.
20
+ *
21
+ * @public
22
+ * @param socialAuth Social auth port instance.
23
+ * @param configService Configuration service instance.
24
+ */
25
+ constructor(socialAuth: SocialAuthPort, configService: ConfigService);
26
+ /**
27
+ * Validates the Apple authentication payload.
28
+ *
29
+ * @public
30
+ * @param accessToken OAuth access token.
31
+ * @param refreshToken OAuth refresh token.
32
+ * @param idToken Apple identity token.
33
+ * @param profile Apple profile data.
34
+ * @returns The authenticated user.
35
+ */
36
+ validate(accessToken: string, refreshToken: string, idToken: string, profile: IAppleProfile): Promise<IAuthSubject>;
37
+ }
38
+ export {};
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ // #region Imports
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.AppleStrategy = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const archipel_platform_core_1 = require("@breadstone/archipel-platform-core");
7
+ const common_1 = require("@nestjs/common");
8
+ const passport_1 = require("@nestjs/passport");
9
+ const passport_apple_1 = require("passport-apple");
10
+ const SocialAuthPort_1 = require("../contracts/SocialAuthPort");
11
+ /**
12
+ * The `AppleStrategy` integrates Apple Sign In authentication.
13
+ *
14
+ * @public
15
+ */
16
+ let AppleStrategy = class AppleStrategy extends (0, passport_1.PassportStrategy)(passport_apple_1.Strategy, 'apple') {
17
+ // #endregion
18
+ // #region Ctor
19
+ /**
20
+ * Initializes a new instance of the `AppleStrategy` class.
21
+ *
22
+ * @public
23
+ * @param socialAuth Social auth port instance.
24
+ * @param configService Configuration service instance.
25
+ */
26
+ constructor(socialAuth, configService) {
27
+ const rawPrivateKey = configService.get('AUTH_APPLE_PRIVATE_KEY');
28
+ const normalizedPrivateKey = rawPrivateKey.replace(/\r/g, '').replace(/\\n/g, '\n');
29
+ super({
30
+ clientID: configService.get('AUTH_APPLE_CLIENT_ID'),
31
+ teamID: configService.get('AUTH_APPLE_TEAM_ID'),
32
+ keyID: configService.get('AUTH_APPLE_KEY_ID'),
33
+ callbackURL: configService.tryGet('AUTH_APPLE_CALLBACK_URL', '/auth/apple/callback'),
34
+ privateKeyString: normalizedPrivateKey,
35
+ scope: ['name', 'email'],
36
+ state: true,
37
+ });
38
+ this._socialAuth = socialAuth;
39
+ }
40
+ // #endregion
41
+ // #region Methods
42
+ /**
43
+ * Validates the Apple authentication payload.
44
+ *
45
+ * @public
46
+ * @param accessToken OAuth access token.
47
+ * @param refreshToken OAuth refresh token.
48
+ * @param idToken Apple identity token.
49
+ * @param profile Apple profile data.
50
+ * @returns The authenticated user.
51
+ */
52
+ async validate(accessToken, refreshToken, idToken, profile) {
53
+ void accessToken;
54
+ void refreshToken;
55
+ void idToken;
56
+ const email = profile.emails?.[0]?.value ?? profile.email ?? null;
57
+ if (!email) {
58
+ throw new common_1.UnauthorizedException('No email provided from Apple');
59
+ }
60
+ const displayName = profile.displayName ?? profile.name?.givenName ?? profile.name?.familyName ?? email.split('@')[0];
61
+ if (!displayName) {
62
+ throw new common_1.UnauthorizedException('No display name provided from Apple');
63
+ }
64
+ const userName = profile.username ?? email.split('@')[0];
65
+ const user = await this._socialAuth.findOrCreateByProfile({
66
+ provider: 'apple',
67
+ email: email,
68
+ userName: userName,
69
+ displayName: displayName,
70
+ });
71
+ return user;
72
+ }
73
+ };
74
+ exports.AppleStrategy = AppleStrategy;
75
+ exports.AppleStrategy = AppleStrategy = tslib_1.__decorate([
76
+ (0, common_1.Injectable)(),
77
+ tslib_1.__metadata("design:paramtypes", [SocialAuthPort_1.SocialAuthPort, archipel_platform_core_1.ConfigService])
78
+ ], AppleStrategy);
79
+ //# sourceMappingURL=AppleStrategy.js.map
@@ -0,0 +1,24 @@
1
+ import { ConfigService } from '@breadstone/archipel-platform-core';
2
+ import { type Profile, Strategy } from 'passport-github2';
3
+ import type { IAuthSubject } from '../contracts/IAuthSubject';
4
+ import { SocialAuthPort } from '../contracts/SocialAuthPort';
5
+ declare const GithubStrategy_base: new (...args: [options: import("passport-github2").StrategyOptionsWithRequest] | [options: import("passport-github2").StrategyOptions]) => Strategy & {
6
+ validate(...args: any[]): unknown;
7
+ };
8
+ export declare class GithubStrategy extends GithubStrategy_base {
9
+ private readonly _socialAuth;
10
+ private readonly _configService;
11
+ /**
12
+ * Constructs a new instance of the `GithubStrategy` class.
13
+ *
14
+ * @public
15
+ * @param socialAuth Social auth port instance.
16
+ * @param configService Configuration service instance.
17
+ */
18
+ constructor(socialAuth: SocialAuthPort, configService: ConfigService);
19
+ /**
20
+ * @public
21
+ */
22
+ validate(_accessToken: string, _refreshToken: string, profile: Profile): Promise<IAuthSubject>;
23
+ }
24
+ export {};
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ // #region Imports
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.GithubStrategy = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const archipel_platform_core_1 = require("@breadstone/archipel-platform-core");
7
+ const common_1 = require("@nestjs/common");
8
+ const passport_1 = require("@nestjs/passport");
9
+ const passport_github2_1 = require("passport-github2");
10
+ const SocialAuthPort_1 = require("../contracts/SocialAuthPort");
11
+ // import type { authConfig } from '../../../configs/auth.config';
12
+ // import { AuthConfig } from '../../../configs/auth.config';
13
+ // import { UserService } from '../../user/user.service';
14
+ // import { OauthStoreService } from '../oauth/oauth.store';
15
+ // import { pickUserMe } from '../utils';
16
+ // #endregion
17
+ let GithubStrategy = class GithubStrategy extends (0, passport_1.PassportStrategy)(passport_github2_1.Strategy, 'github') {
18
+ // #endregion
19
+ // #region Ctor
20
+ /**
21
+ * Constructs a new instance of the `GithubStrategy` class.
22
+ *
23
+ * @public
24
+ * @param socialAuth Social auth port instance.
25
+ * @param configService Configuration service instance.
26
+ */
27
+ constructor(socialAuth, configService) {
28
+ super({
29
+ clientID: configService.get('AUTH_GITHUB_CLIENT_ID'),
30
+ clientSecret: configService.get('AUTH_GITHUB_CLIENT_SECRET'),
31
+ state: true,
32
+ callbackURL: '/auth/github/callback',
33
+ // store: oauthStoreService
34
+ });
35
+ this._socialAuth = socialAuth;
36
+ this._configService = configService;
37
+ }
38
+ // #endregion
39
+ // #region Methods
40
+ /**
41
+ * @public
42
+ */
43
+ async validate(_accessToken, _refreshToken, profile) {
44
+ const email = profile.emails?.[0].value;
45
+ if (!email) {
46
+ throw new common_1.UnauthorizedException('No email provided from GitHub');
47
+ }
48
+ if (!profile.displayName) {
49
+ throw new common_1.UnauthorizedException('No display name provided from GitHub');
50
+ }
51
+ const user = await this._socialAuth.findOrCreateByProfile({
52
+ provider: 'github',
53
+ email: email,
54
+ userName: profile.username ?? null,
55
+ displayName: profile.displayName ?? null,
56
+ });
57
+ return user;
58
+ }
59
+ };
60
+ exports.GithubStrategy = GithubStrategy;
61
+ exports.GithubStrategy = GithubStrategy = tslib_1.__decorate([
62
+ (0, common_1.Injectable)(),
63
+ tslib_1.__metadata("design:paramtypes", [SocialAuthPort_1.SocialAuthPort, archipel_platform_core_1.ConfigService])
64
+ ], GithubStrategy);
65
+ //# sourceMappingURL=GithubStrategy.js.map
@@ -0,0 +1,34 @@
1
+ import { ConfigService } from '@breadstone/archipel-platform-core';
2
+ import { Profile, Strategy } from 'passport-google-oauth20';
3
+ import type { IAuthSubject } from '../contracts/IAuthSubject';
4
+ import { SocialAuthPort } from '../contracts/SocialAuthPort';
5
+ declare const GoogleStrategy_base: new (...args: [options: import("passport-google-oauth20").StrategyOptionsWithRequest] | [options: import("passport-google-oauth20").StrategyOptions] | [options: import("passport-google-oauth20").StrategyOptions] | [options: import("passport-google-oauth20").StrategyOptionsWithRequest]) => Strategy & {
6
+ validate(...args: any[]): unknown;
7
+ };
8
+ /**
9
+ * The `GoogleStrategy` integrates Google OAuth authentication.
10
+ *
11
+ * @public
12
+ */
13
+ export declare class GoogleStrategy extends GoogleStrategy_base {
14
+ private readonly _socialAuth;
15
+ /**
16
+ * Initializes a new instance of the `GoogleStrategy` class.
17
+ *
18
+ * @public
19
+ * @param socialAuth Social auth port instance.
20
+ * @param configService Configuration service instance.
21
+ */
22
+ constructor(socialAuth: SocialAuthPort, configService: ConfigService);
23
+ /**
24
+ * Validates the Google authentication payload.
25
+ *
26
+ * @public
27
+ * @param accessToken OAuth access token.
28
+ * @param refreshToken OAuth refresh token.
29
+ * @param profile Google profile data.
30
+ * @returns The authenticated user.
31
+ */
32
+ validate(accessToken: string, refreshToken: string, profile: Profile): Promise<IAuthSubject>;
33
+ }
34
+ export {};