@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.
- package/README.md +47 -0
- package/package.json +67 -0
- package/src/AuthModule.d.ts +57 -0
- package/src/AuthModule.js +158 -0
- package/src/contracts/AuthSubjectPort.d.ts +33 -0
- package/src/contracts/AuthSubjectPort.js +15 -0
- package/src/contracts/IAuthSubject.d.ts +40 -0
- package/src/contracts/IAuthSubject.js +3 -0
- package/src/contracts/IMfaSubject.d.ts +48 -0
- package/src/contracts/IMfaSubject.js +3 -0
- package/src/contracts/IMfaSubjectUpdate.d.ts +16 -0
- package/src/contracts/IMfaSubjectUpdate.js +3 -0
- package/src/contracts/ISessionRecord.d.ts +22 -0
- package/src/contracts/ISessionRecord.js +3 -0
- package/src/contracts/ISocialProfile.d.ts +23 -0
- package/src/contracts/ISocialProfile.js +3 -0
- package/src/contracts/IStoreSessionArgs.d.ts +14 -0
- package/src/contracts/IStoreSessionArgs.js +4 -0
- package/src/contracts/IVerifiableSubject.d.ts +28 -0
- package/src/contracts/IVerifiableSubject.js +3 -0
- package/src/contracts/MfaSubjectPort.d.ts +26 -0
- package/src/contracts/MfaSubjectPort.js +15 -0
- package/src/contracts/SessionPersistencePort.d.ts +58 -0
- package/src/contracts/SessionPersistencePort.js +15 -0
- package/src/contracts/SocialAuthPort.d.ts +19 -0
- package/src/contracts/SocialAuthPort.js +15 -0
- package/src/contracts/TokenEnricherPort.d.ts +17 -0
- package/src/contracts/TokenEnricherPort.js +15 -0
- package/src/contracts/VerificationSubjectPort.d.ts +40 -0
- package/src/contracts/VerificationSubjectPort.js +15 -0
- package/src/contracts/index.d.ts +13 -0
- package/src/contracts/index.js +16 -0
- package/src/decorators/RolesDecorator.d.ts +12 -0
- package/src/decorators/RolesDecorator.js +23 -0
- package/src/decorators/TokenDecorator.d.ts +6 -0
- package/src/decorators/TokenDecorator.js +20 -0
- package/src/decorators/UserDecorator.d.ts +6 -0
- package/src/decorators/UserDecorator.js +16 -0
- package/src/decorators/index.d.ts +3 -0
- package/src/decorators/index.js +7 -0
- package/src/env.d.ts +57 -0
- package/src/env.js +179 -0
- package/src/guards/AnonymousAuthGuard.d.ts +9 -0
- package/src/guards/AnonymousAuthGuard.js +20 -0
- package/src/guards/GithubAuthGuard.d.ts +9 -0
- package/src/guards/GithubAuthGuard.js +20 -0
- package/src/guards/JwtAuthGuard.d.ts +9 -0
- package/src/guards/JwtAuthGuard.js +20 -0
- package/src/guards/LocalAuthGuard.d.ts +9 -0
- package/src/guards/LocalAuthGuard.js +20 -0
- package/src/guards/RolesGuard.d.ts +16 -0
- package/src/guards/RolesGuard.js +43 -0
- package/src/guards/SocialAuthGuard.d.ts +9 -0
- package/src/guards/SocialAuthGuard.js +35 -0
- package/src/guards/_RefreshTokenAuthGuard.d.ts +0 -0
- package/src/guards/_RefreshTokenAuthGuard.js +2 -0
- package/src/guards/_TwoFactorAuthGuard.d.ts +0 -0
- package/src/guards/_TwoFactorAuthGuard.js +2 -0
- package/src/guards/index.d.ts +6 -0
- package/src/guards/index.js +12 -0
- package/src/index.d.ts +9 -0
- package/src/index.js +13 -0
- package/src/mappers/SessionMappingProfile.d.ts +42 -0
- package/src/mappers/SessionMappingProfile.js +68 -0
- package/src/middlewares/LastActiveMiddleware.d.ts +29 -0
- package/src/middlewares/LastActiveMiddleware.js +55 -0
- package/src/middlewares/index.d.ts +1 -0
- package/src/middlewares/index.js +5 -0
- package/src/models/IMfaChallengePayload.d.ts +31 -0
- package/src/models/IMfaChallengePayload.js +3 -0
- package/src/models/IMfaConfirmation.d.ts +11 -0
- package/src/models/IMfaConfirmation.js +3 -0
- package/src/models/IMfaSetup.d.ts +23 -0
- package/src/models/IMfaSetup.js +3 -0
- package/src/models/ISignInResult.d.ts +31 -0
- package/src/models/ISignInResult.js +3 -0
- package/src/models/JwtPayloadBase.d.ts +44 -0
- package/src/models/JwtPayloadBase.js +55 -0
- package/src/models/index.d.ts +6 -0
- package/src/models/index.js +10 -0
- package/src/models/responses/SessionResponse.d.ts +20 -0
- package/src/models/responses/SessionResponse.js +164 -0
- package/src/models/responses/index.d.ts +1 -0
- package/src/models/responses/index.js +5 -0
- package/src/serializer/SessionSerializer.d.ts +5 -0
- package/src/serializer/SessionSerializer.js +23 -0
- package/src/services/AuthTokenService.d.ts +30 -0
- package/src/services/AuthTokenService.js +58 -0
- package/src/services/ChallengeService.d.ts +41 -0
- package/src/services/ChallengeService.js +89 -0
- package/src/services/MfaService.d.ts +60 -0
- package/src/services/MfaService.js +251 -0
- package/src/services/SessionService.d.ts +66 -0
- package/src/services/SessionService.js +108 -0
- package/src/services/VerificationService.d.ts +56 -0
- package/src/services/VerificationService.js +124 -0
- package/src/services/index.d.ts +5 -0
- package/src/services/index.js +9 -0
- package/src/services/mfa/IMfaChannel.d.ts +40 -0
- package/src/services/mfa/IMfaChannel.js +4 -0
- package/src/services/mfa/MfaEncryptionService.d.ts +23 -0
- package/src/services/mfa/MfaEncryptionService.js +59 -0
- package/src/services/mfa/MfaState.d.ts +38 -0
- package/src/services/mfa/MfaState.js +23 -0
- package/src/services/mfa/MfaTokens.d.ts +4 -0
- package/src/services/mfa/MfaTokens.js +8 -0
- package/src/services/mfa/channels/EmailOtpMfaChannel.d.ts +21 -0
- package/src/services/mfa/channels/EmailOtpMfaChannel.js +152 -0
- package/src/services/mfa/channels/PushMfaChannel.d.ts +25 -0
- package/src/services/mfa/channels/PushMfaChannel.js +150 -0
- package/src/services/mfa/channels/SmsMfaChannel.d.ts +21 -0
- package/src/services/mfa/channels/SmsMfaChannel.js +158 -0
- package/src/services/mfa/channels/TotpMfaChannel.d.ts +19 -0
- package/src/services/mfa/channels/TotpMfaChannel.js +100 -0
- package/src/strategies/AnonymousStrategy.d.ts +32 -0
- package/src/strategies/AnonymousStrategy.js +53 -0
- package/src/strategies/AppleStrategy.d.ts +38 -0
- package/src/strategies/AppleStrategy.js +79 -0
- package/src/strategies/GithubStrategy.d.ts +24 -0
- package/src/strategies/GithubStrategy.js +65 -0
- package/src/strategies/GoogleStrategy.d.ts +34 -0
- package/src/strategies/GoogleStrategy.js +74 -0
- package/src/strategies/JwtStrategy.d.ts +31 -0
- package/src/strategies/JwtStrategy.js +55 -0
- package/src/strategies/LocalStrategy.d.ts +31 -0
- package/src/strategies/LocalStrategy.js +56 -0
- package/src/strategies/MicrosoftStrategy.d.ts +35 -0
- 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 {};
|