使用 SubtleCrypto(或其他浏览器 API)签署 Google JWT

问题描述 投票:0回答:1

我目前正在编写一个 Chrome 扩展程序,它将通过服务帐户从 Google OAuth 获取访问令牌。我基本上已经准备好了一切,除了我坚持签署 JWT。我查看了无数其他答案,但没有一个适合我的需要,因为它们

  • 基于 NodeJS
  • 使用我无法导入到 Chrome 扩展中的库(例如基于模块或没有浏览器支持)
  • 不是关于签名,而是关于出于 OAuth 目的解码/验证 Google JWT
  • 显示用于签署其他 JWT 的代码示例,其密钥和格式与我的需求不完全匹配
  • 甚至不是 Javascript,而是 Python 或 Java 之类的。

经过一番挖掘,目前这是我的代码:

function base64ToArrayBuffer(b64) {
    var byteString = atob(b64)
    var byteArray = new Uint8Array(byteString.length)
    for (var i = 0; i < byteString.length; i++) {
        byteArray[i] = byteString.charCodeAt(i)
    }

    return byteArray
}

async function encodeJWT(email, scopes, key) {
    let iat = Math.floor(new Date().getTime() / 1000)
    let exp = iat + Math.floor((60 * 60 * 1000) / 1000)
    let claims = {
        iss: email,
        scope: scopes.join(' '),
        aud: 'https://accounts.google.com/o/oauth2/token',
        exp: exp,
        iat: iat
    }

    let JWT_header = btoa(JSON.stringify({ alg: 'RS256', typ: 'JWT' }))
    let JWT_claimset = btoa(JSON.stringify(claims))
    let unsignedJWT = [JWT_header, JWT_claimset].join('.')

    key = key.replace('-----BEGIN PUBLIC KEY-----', '').replace('-----END PUBLIC KEY-----', '').replace(/\n/g, '')
    let importedKey = await crypto.subtle.importKey('pkcs8', base64ToArrayBuffer(key), {
        name: 'RSA-OAEP',
        hash: {
            name: 'SHA-256'
        }
    }, true, ['sign'])
    let JWT_signature = await crypto.subtle.sign({
        name: 'RSASSA-PKCS1-v1_5',
        hash: {
            name: 'SHA-256'
        }
    }, importedKey, new TextEncoder().encode(unsignedJWT))

    return [unsignedJWT, new TextDecoder().decode(new Uint8Array(JWT_signature))].join('.')
}

问题出在签名部分。无论我做什么,我似乎都无法获得正确格式的密钥,有太多错误消息,如果我调整一件事,它会告诉我另一件事格式不正确或出现一些数据错误。大多数时候这些错误消息根本没有帮助。

邮箱就是服务账号的邮箱,密钥是账号自带的JSON里面的私钥,格式为

的字符串
-----BEGIN PUBLIC KEY-----\nXXXX...XXX\nXXXX..XXX\n...\n-----END PUBLIC KEY----- (middle is omitted)

有人可以告诉我吗

  1. 是否可以使用 SubtleCrypto 或任何其他非节点但可以在 Chrome 扩展环境中运行的浏览器 API 签署 Google JWT(基本上就像没有 DOM API 的 HTML 环境)?
  2. 如果是,有人可以指出我正确的方向吗?我应该如何签署 JWT?
google-chrome google-cloud-platform oauth jwt cryptography
1个回答
© www.soinside.com 2019 - 2024. All rights reserved.