首次完整推送,

V:1.20240808.006
This commit is contained in:
fm453
2024-08-13 18:32:37 +08:00
parent 15be3e9373
commit c62d15b288
939 changed files with 111777 additions and 0 deletions

View File

@ -0,0 +1,79 @@
const rsaPublicKeyPem = require('../rsa-public-key-pem')
const {
jwtVerify
} = require('../../../npm/index')
let authKeysCache = null
module.exports = class Auth {
constructor (options) {
this.options = Object.assign({
baseUrl: 'https://appleid.apple.com',
timeout: 10000
}, options)
}
async _fetch (url, options) {
const { baseUrl } = this.options
return uniCloud.httpclient.request(baseUrl + url, options)
}
async verifyIdentityToken (identityToken) {
// 解密出kid拿取key
const jwtHeader = identityToken.split('.')[0]
const { kid } = JSON.parse(Buffer.from(jwtHeader, 'base64').toString())
let authKeys
if (authKeysCache) {
authKeys = authKeysCache
} else {
authKeys = await this.getAuthKeys()
authKeysCache = authKeys
}
const usedKey = authKeys.find(item => item.kid === kid)
/**
* identityToken 格式
*
* {
* iss: 'https://appleid.apple.com',
* aud: 'io.dcloud.hellouniapp',
* exp: 1610626724,
* iat: 1610540324,
* sub: '000628.30119d332d9b45a3be4a297f9391fd5c.0403',
* c_hash: 'oFfgewoG36cJX00KUbj45A',
* email: 'x2awmap99s@privaterelay.appleid.com',
* email_verified: 'true',
* is_private_email: 'true',
* auth_time: 1610540324,
* nonce_supported: true
* }
*/
const payload = jwtVerify(
identityToken,
rsaPublicKeyPem(usedKey.n, usedKey.e),
{
algorithms: usedKey.alg
}
)
if (payload.iss !== 'https://appleid.apple.com' || payload.aud !== this.options.bundleId) {
throw new Error('Invalid identity token')
}
return {
openid: payload.sub,
email: payload.email,
emailVerified: payload.email_verified === 'true',
isPrivateEmail: payload.is_private_email === 'true'
}
}
async getAuthKeys () {
const { status, data } = await this._fetch('/auth/keys', {
method: 'GET',
dataType: 'json',
timeout: this.options.timeout
})
if (status !== 200) throw new Error('request https://appleid.apple.com/auth/keys fail')
return data.keys
}
}

View File

@ -0,0 +1,64 @@
// http://stackoverflow.com/questions/18835132/xml-to-pem-in-node-js
/* eslint-disable camelcase */
function rsaPublicKeyPem (modulus_b64, exponent_b64) {
const modulus = Buffer.from(modulus_b64, 'base64')
const exponent = Buffer.from(exponent_b64, 'base64')
let modulus_hex = modulus.toString('hex')
let exponent_hex = exponent.toString('hex')
modulus_hex = prepadSigned(modulus_hex)
exponent_hex = prepadSigned(exponent_hex)
const modlen = modulus_hex.length / 2
const explen = exponent_hex.length / 2
const encoded_modlen = encodeLengthHex(modlen)
const encoded_explen = encodeLengthHex(explen)
const encoded_pubkey = '30' +
encodeLengthHex(
modlen +
explen +
encoded_modlen.length / 2 +
encoded_explen.length / 2 + 2
) +
'02' + encoded_modlen + modulus_hex +
'02' + encoded_explen + exponent_hex
const der_b64 = Buffer.from(encoded_pubkey, 'hex').toString('base64')
const pem = '-----BEGIN RSA PUBLIC KEY-----\n' +
der_b64.match(/.{1,64}/g).join('\n') +
'\n-----END RSA PUBLIC KEY-----\n'
return pem
}
function prepadSigned (hexStr) {
const msb = hexStr[0]
if (msb < '0' || msb > '7') {
return '00' + hexStr
} else {
return hexStr
}
}
function toHex (number) {
const nstr = number.toString(16)
if (nstr.length % 2) return '0' + nstr
return nstr
}
// encode ASN.1 DER length field
// if <=127, short form
// if >=128, long form
function encodeLengthHex (n) {
if (n <= 127) return toHex(n)
else {
const n_hex = toHex(n)
const length_of_length_byte = 128 + n_hex.length / 2 // 0x80+numbytes
return toHex(length_of_length_byte) + n_hex
}
}
module.exports = rsaPublicKeyPem