fix: harden login for MLPS requirements

This commit is contained in:
2026-05-14 11:05:20 +08:00
parent ecf3ee1ef0
commit 879677516f
39 changed files with 1230 additions and 71 deletions
+4
View File
@@ -80,6 +80,7 @@ import type {
MonitoringDashboardCompositeResponse,
MonitoringQuestionDetailResponse,
PlatformAccount,
PasswordPublicKeyResponse,
PromptRule,
PromptRuleGroup,
PromptRuleGroupRequest,
@@ -336,6 +337,9 @@ apiClient.raw.interceptors.response.use(
)
export const authApi = {
passwordPublicKey() {
return publicClient.get<PasswordPublicKeyResponse>('/api/auth/password-key')
},
login(payload: LoginRequest) {
return publicClient.post<LoginResponse, LoginRequest>('/api/auth/login', payload)
},
+59
View File
@@ -0,0 +1,59 @@
import type { PasswordPublicKeyResponse } from '@geo/shared-types'
const textEncoder = new TextEncoder()
export function browserSupportsPasswordCipher(): boolean {
return typeof window !== 'undefined' && Boolean(window.crypto?.subtle)
}
export async function encryptPasswordForLogin(
password: string,
key: PasswordPublicKeyResponse,
): Promise<{ encrypted_password: string; password_key_id: string }> {
const cryptoKey = await importRSAOAEPKey(key.public_key)
const encrypted = await window.crypto.subtle.encrypt(
{ name: 'RSA-OAEP' },
cryptoKey,
textEncoder.encode(password),
)
return {
encrypted_password: arrayBufferToBase64(encrypted),
password_key_id: key.key_id,
}
}
async function importRSAOAEPKey(publicKeyPEM: string): Promise<CryptoKey> {
const binaryDER = pemToArrayBuffer(publicKeyPEM)
return window.crypto.subtle.importKey(
'spki',
binaryDER,
{
name: 'RSA-OAEP',
hash: 'SHA-256',
},
false,
['encrypt'],
)
}
function pemToArrayBuffer(pem: string): ArrayBuffer {
const base64 = pem
.replace(/-----BEGIN PUBLIC KEY-----/g, '')
.replace(/-----END PUBLIC KEY-----/g, '')
.replace(/\s/g, '')
const binary = window.atob(base64)
const bytes = new Uint8Array(binary.length)
for (let i = 0; i < binary.length; i += 1) {
bytes[i] = binary.charCodeAt(i)
}
return bytes.buffer
}
function arrayBufferToBase64(buffer: ArrayBuffer): string {
const bytes = new Uint8Array(buffer)
let binary = ''
for (const byte of bytes) {
binary += String.fromCharCode(byte)
}
return window.btoa(binary)
}