-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAuthController.ts
113 lines (103 loc) · 4.58 KB
/
AuthController.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
* AuthController
*
* Provides endpoints to start/complete an auth method and retrieve the presentation key.
*/
import { Request, Response } from "express";
import { UserService } from "../services/UserService";
import { AuthMethod } from "../auth-methods/AuthMethod";
import { TwilioAuthMethod } from "../auth-methods/TwilioAuthMethod";
import { PersonaAuthMethod } from "../auth-methods/PersonaAuthMethod";
import { db } from "../db/knex";
/**
* Returns the appropriate AuthMethod instance given a methodType.
*/
function getAuthMethodInstance(methodType: string): AuthMethod {
switch (methodType) {
case "TwilioPhone":
return new TwilioAuthMethod({
accountSid: process.env.TWILIO_ACCOUNT_SID!,
authToken: process.env.TWILIO_AUTH_TOKEN!,
verifyServiceSid: process.env.TWILIO_VERIFY_SERVICE_SID!
});
case "PersonaID":
return new PersonaAuthMethod({ apiKey: "mockApiKey" });
default:
throw new Error(`Unsupported auth method: ${methodType}`);
}
}
export class AuthController {
/**
* Step 1: Start the auth process (e.g. send OTP, create session, etc.)
* Body must include:
* methodType: string
* presentationKey: string (the random 256-bit key from client)
* payload: any (whatever the chosen method needs)
*/
public static async startAuth(req: Request, res: Response) {
try {
const { methodType, presentationKey, payload } = req.body;
if (!methodType || !presentationKey || !payload) {
return res.status(400).json({ message: "methodType, presentationKey, and payload are required." });
}
const authMethod = getAuthMethodInstance(methodType);
const result = await authMethod.startAuth(presentationKey, payload);
res.json(result);
} catch (error: any) {
console.error(error);
res.status(500).json({ message: error.message });
}
}
/**
* Step 2: Complete the auth process. If successful:
* - If user doesn't exist, create them with the given presentationKey
* - If user exists, retrieve their stored presentationKey
* - Link the AuthMethod to that user if not already linked
* Return the final presentationKey to the client.
*/
public static async completeAuth(req: Request, res: Response) {
try {
const { methodType, presentationKey, payload } = req.body;
if (!methodType || !presentationKey || !payload) {
return res.status(400).json({ message: "methodType, presentationKey, and payload are required." });
}
const authMethod = getAuthMethodInstance(methodType);
const result = await authMethod.completeAuth(presentationKey, payload);
if (!result.success) {
return res.json(result);
}
// Auth successful, store or retrieve user
// FIND BY: Verified identifier or something unique to auth method and user
// let user = await UserService.getUserByPresentationKey(presentationKey);
// if (!user) {
// // create new user
// user = await UserService.createUser(presentationKey);
// }
const config = authMethod.buildConfigFromPayload(payload)
let user = await UserService.findUserByConfig(methodType, config)
if (!user) {
user = await UserService.createUser(presentationKey)
await UserService.linkAuthMethod(user.id, methodType, config);
}
// Link the method if not already linked
// const allMethods = await UserService.getAuthMethodsByUserId(user.id);
// const foundSameMethod = allMethods.find(
// (m) => m.methodType === methodType && authMethod.isAlreadyLinked(m.config, payload)
// );
// if (!foundSameMethod) {
// // store new method
// const config = authMethod.buildConfigFromPayload(payload);
// await UserService.linkAuthMethod(user.id, methodType, config);
// }
// Return the presentationKey from DB (ensures the user gets the stored key if user is existing)
res.json({
success: true,
presentationKey: user.presentationKey,
message: result.message
});
} catch (error: any) {
console.error(error);
res.status(500).json({ message: error.message });
}
}
}