如何使用 JWT for Google firebase 生成身份验证令牌?

Posted

技术标签:

【中文标题】如何使用 JWT for Google firebase 生成身份验证令牌?【英文标题】:How do I generate an auth token using JWT for Google firebase? 【发布时间】:2018-03-05 21:25:50 【问题描述】:

所以我想authenticate the Firebase REST API. 我将Vapor framework 用于服务器端swift,并安装了JWT package。

我正在尝试使用 serviceAccountKey.json 文件和 JWT 中的数据来生成身份验证令牌。

这是我尝试过的代码:

let payload = try JSON(node: [
        "iat": Date().timeIntervalSince1970,
        "exp": Date().timeIntervalSince1970 + 3600,
        "iss": "client_email from serviceAccountKey.json",
        "aud": "https://accounts.google.com/o/oauth2/token",
        "scope": [
            "https://www.googleapis.com/auth/firebase.database",
            "https://www.googleapis.com/auth/userinfo.email"
        ]
    ])
    let privateKey = "copied from serviceAccountKey.json"

    let signer = try HS256(bytes: privateKey.bytes)

    let jwt = try JWT(payload: payload, signer: signer)
    let token = try jwt.createToken()
    print(token)

serviceAccountKey.json


  "type": "service_account",
  "project_id": "",
  "private_key_id": "",
  "private_key": "",
  "client_email": "",
  "client_id": "",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": ""

【问题讨论】:

您没有解释问题。你有那个代码。好的。它有什么问题? @zerkms 这只是我生成令牌的尝试。令牌不起作用,我得到“权限被拒绝” 您是否检查过生成的 JWT 是否与您期望的完全一样? @zerkms 我不确定它应该是什么样子 第一步,检查令牌是否可以在 jwt.io 上解码。 【参考方案1】:

此时我使用的是 Xcode 8.3.3。 Package.swift 包含:

let package = Package(
name: "StripePayment",
dependencies: [
    .Package(url: "https://github.com/vapor/vapor.git", majorVersion: 1, minor: 5),
    .Package(url:"https://github.com/vapor/jwt.git", majorVersion: 0,minor: 8),
     .Package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", versions: Version(1, 0, 0)..<Version(3, .max, .max))

],
exclude: [
    "Config",
    "Database",
    "Localization",
    "Public",
    "Resources",
    "Tests",
]
)

如果您生成服务帐号凭据,则需要牢记以下内容,取自 https://cloud.google.com/storage/docs/authentication:您可以通过为服务帐号创建 OAuth 客户端 ID 在 Cloud Platform Console 中创建私钥。您可以获取 JSON 和 PKCS12 格式的私钥:

如果您在 Google Cloud Platform 之外的生产环境中使用 Application Default Credentials,则需要 JSON 密钥。 JSON 密钥无法转换为其他格式。许多不同的编程语言和库都支持 PKCS12 (.p12)。如果需要,您可以使用 OpenSSL (see Converting the private key to other formats) 将密钥转换为其他格式。但是,PKCS12 密钥无法转换为 JSON 格式。

注意:您不需要在 console.cloud.google.com 上生成服务帐户。只需按照下面列出的步骤 1...6。

    转到https://console.firebase.google.com,点击您的项目,在概览旁边点击滚轮设置,点击服务帐户,滚动到页面底部并点击生成新私钥。

    使用 OpenSSL 将 p.12(a.k.a pkcs12)文件转换为 .pem(a.k.a pkcs1)

    cat /path/to/xxxx-privatekey.p12 | openssl pkcs12 -nodes -nocerts -passin pass:notasecret | openssl rsa &gt; /path/to/secret.pem

    去github搜索VaporJWT并导入Xcode。它将帮助您创建一个签名的 JSON Web 令牌。

    在此 github 页面上,您将了解如何提取私钥以供 RSA 使用。

    将 .pem 转换为 deropenssl rsa -in /path/to/secret.pem -outform der -out /path/to/private.der

    将 .der 转换为 .base64openssl base64 -in /path/to/private.der -out /path/to/Desktop/private.txt 在 private.txt 中,您拥有以 base64 编码的私钥,您最终可以使用它来签署您的 JWT。然后,您可以使用签名的 JWT 调用 Google API。

``

 import Vapor
 import VaporJWT

 let drop = Droplet()
 var tokenID:String!

 //set current date
 let dateNow = Date()

 // assign to expDate the validity period of the token returned by OAuth server (3600 seconds)
 var expDate = String(Int(dateNow.timeIntervalSince1970 + (60 * 60)))

// assign to iatDate the time when the call was made to request an access token
 var iatDate = String(Int(dateNow.timeIntervalSince1970))

// the header of the JSON Web Token (first part of the JWT)
 let headerJWT = ["alg":"RS256","typ":"JWT"]

 // the claim set of the JSON Web Token
 let jwtClaimSet =
   ["iss":"firebase-adminsdk-c7i38@fir-30c9e.iam.gserviceaccount.com",
     "scope":"https://www.googleapis.com/auth/firebase.database",
     "aud":"https://www.googleapis.com/oauth2/v4/token",
     "exp": expDate,
     "iat": iatDate]


 //Using VaporJWT construct a JSON Web Token and sign it with RS256 algorithm
 //The only signing algorithm supported by the Google OAuth 2.0 Authorization     
 //Server is RSA using SHA-256 hashing algorithm.

  let jwt = try JWT(headers: Node(node: headerJWT), payload: Node(node:jwtClaimSet), encoding: Base64URLEncoding(), signer: RS256(encodedKey: "copy paste here what you have in private.txt as explained at point 7 above "))

 // create the JSON Web Token
  let JWTtoken = try jwt.createToken()
 let grant_type = "urn:ietf:params:oauth:grant-type:jwt-bearer" // this value must not be changed
   let unreserved = "*-._"
   let allowed = NSMutableCharacterSet.alphanumeric()
    allowed.addCharacters(in: unreserved)

// percent or URL encode grant_type
 let grant_URLEncoded = grant_type.addingPercentEncoding(withAllowedCharacters: allowed as CharacterSet)

 // create a string made of grant_type and assertion. NOTE!!! only grant_type's value is URL encoded.
 //JSON Web Token value does not need to be URL encoded
   var fullString = "grant_type=\(grant_URLEncoded!)&assertion=\(JWTtoken)"


  //pass fullString in the body parameter
   drop.get("call")  request in


    let response =  try drop.client.post("https://www.googleapis.com/oauth2/v4/token", headers: ["Content-Type": "application/x-www-form-urlencoded"], query: [:],body: fullString)

   let serverResp = response.headers
   let serverBody = response.body.bytes
      let serverJson = try JSON(bytes: serverBody!)
        print(serverJson)

     return "Success"

【讨论】:

我已经在我的项目中添加了 .package。看来您已经使用了该库,所以您能告诉我们为什么我收到错误“导入节点”而不是包中的此类模块。我也在源代码中查找了该文件,但没有这样的文件。 @avi 怎么无效?你可以解释吗?显示一些代码? @bibscy,我收到错误消息,unsupported_grant_type(error_description" = "Invalid grant_type: ";)。 @你应该把它放在一个问题中。我正在使用let grant_type = "urn:ietf:params:oauth:grant-type:jwt-bearer" 成功运行我的项目确保您拥有完全相同的代码行。 我错了。你的答案是正确的。对此感到抱歉【参考方案2】:

如果您只是想让事情正常运行,最好使用 1.5.0 版

.Package(url: "https://github.com/gtchance/FirebaseSwift.git", Version(1,5,0)),

并使用遗留秘密。项目设置>服务帐户>数据库机密

【讨论】:

这是我目前正在做的。不确定我是否应该将此标记为“解决方案”,因为原始问题仍然存在。

以上是关于如何使用 JWT for Google firebase 生成身份验证令牌?的主要内容,如果未能解决你的问题,请参考以下文章

Passport & JWT & Google/Facebook 策略 - 如何结合 JWT 和 Google/Facebook 策略?

如何使用 System.IdentityModel.Tokens.Jwt 生成具有 Google OAuth2 兼容算法 RSA SHA-256 的 JWT?

C++ 如何使用 OpenSSL 验证 Google JWT (RS256)

如何使用 Google Auth JWT 授权登录用户? (图片)

如何使用 JWT 通过 NodeJS 客户端库访问 Google Directory (Admin SDK)?

将 JWT 与 Google App Engine 结合使用