forked from dev-xo/remix-auth-totp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.ts
69 lines (58 loc) · 1.55 KB
/
utils.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
import type { CodeGenerationOptions, MagicLinkGenerationOptions } from './index'
import crypto from 'crypto-js'
import otpGenerator from 'otp-generator'
/**
* Encryption.
*/
export async function encrypt(value: string, secret: string): Promise<string> {
return crypto.AES.encrypt(value, secret).toString()
}
export async function decrypt(value: string, secret: string): Promise<string> {
const bytes = crypto.AES.decrypt(value, secret)
return bytes.toString(crypto.enc.Utf8)
}
/**
* OTP Generation.
*/
export function generateOtp(options: CodeGenerationOptions) {
const code = otpGenerator.generate(options.length, { ...options })
const createdAt = new Date().toISOString()
return {
code,
createdAt,
}
}
/**
* Magic Link Generation.
*/
export function generateMagicLink(
options: MagicLinkGenerationOptions & {
param: string
code: string
request: Request
},
) {
if (!options.enabled) {
return undefined
}
const url = new URL(
options.callbackPath ?? '/',
options.baseUrl ?? getBaseUrl(options.request),
)
url.searchParams.set(options.param, options.code)
return url.toString()
}
/**
* Helpers.
*/
export function getBaseUrl(request: Request) {
const host = request.headers.get('X-Forwarded-Host') ?? request.headers.get('host')
if (!host) {
throw new Error('Could not determine host.')
}
// If the host is localhost or ends with .local, use http.
const protocol = host.match(/(:?\.local|^localhost|^127\.\d+\.\d+\.\d+)(:?:\d+)?$/)
? 'http'
: 'https'
return `${protocol}://${host}`
}