Swift Vapor unsupported_grant_type 无效签名/OAuth 访问令牌 [英] Swift Vapor unsupported_grant_type invalid signature / OAuth access token

查看:67
本文介绍了Swift Vapor unsupported_grant_type 无效签名/OAuth 访问令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 Vapor 和 SWIFT 3 运行 Xcode 8.1.

I am running Xcode 8.1 with Vapor and SWIFT 3.

我正在向谷歌服务器发布请求以获取身份验证令牌,因此我可以调用 FireBaseDB API,但出现错误:unsupported_grant_type/Invalid grant_type.
developers.google.com 上,它说我必须在 URL 中编码以下内容: https://www.googleapis.com/oauth2/v4/token + grant_type+ 断言,并在 POST 请求的正文中传递编码的 URL.我将它作为字符串传递.

I am posting a request to to google server to get an auth token, so I can call FireBaseDB API, but I get error: unsupported_grant_type/Invalid grant_type.
On developers.google.com it says that I have to encode in a URL the following: https://www.googleapis.com/oauth2/v4/token + grant_type + assertion, and pass the encoded URL in the body of the POST request. I pass it as a string.

我注意到从我的服务帐户下载的 JSON 文件中的私钥包含/n 、----、== 等字符,我应该在发布密钥之前删除它们吗?

I have noticed that the private key from the JSON file downloaded from my service account contains characters such as /n , ----,==, should I delete them before posting the key?

    let dateNow = Date()
      var expDate = String(Int(dateNow.timeIntervalSince1970 + (60 * 60)))
        var iatDate = String(Int(dateNow.timeIntervalSince1970))


 let headerJWT = ["alg":"HS256","typ":"JWT"]
    let jwtClaimSet =
    ["iss":"firebase-adminsdk-c7i48@fir-10c2e.iam.gserviceaccount.com",
     "scope":"https://www.googleapis.com/auth/firebase.database",
      "aud":"https://www.googleapis.com/oauth2/v4/token",
       "exp": expDate,
         "iat": iatDate]

      //create and sign JSON Web Token
   let jwt = try JWT(headers: Node(node: headerJWT),
              payload: Node(node: jwtClaimSet),
               signer: HS256(key:"-----BEGIN PRIVATE KEY-----\nMIIEvAWvQ== \n-----END PRIVATE KEY-----\n"))

    // Store JSON Web Token
      let JWTtoken = try jwt.createToken()

func createUrlWithString() -> NSURL {
    var urlString = "https://www.googleapis.com/oauth2/v4/token"
     urlString.append("?grant_type=")
      urlString.append("urn:ietf:params:oauth:grant-type:jwt-bearer")
       urlString.append("&assertion=")
        urlString.append(JWTtoken)
  return NSURL(string: urlString)!
 }

        // make the body input for our POST
      let bodyURL =  createUrlWithString().absoluteURL

     drop.get("any") { request in
        let response =  
 try drop.client.request(.other(method:"Post"),
           "https://www.googleapis.com/oauth2/v4/token", 
             headers: ["Content-Type": "application/x-www-form-urlencoded"], 
                 query: [:], 
                  body: String(describing: bodyURL) )


     let serverResp = response.headers
        let serverBody = response.body.bytes
          let serverJson = try JSON(bytes: serverBody!)
             print(serverJson)
    return "POST Request went through"
}

更新

根据 Karol Gasienica 的建议,我将 grant_typeassertion 参数作为 POST 请求参数传递.现在我得到 "error_description": Node.Node.string("SSL is required to perform this operation.")]))

Update

As per Karol Gasienica suggestion, I am passing grant_type and assertion parameters as POST request parameters. Now I get "error_description": Node.Node.string("SSL is required to perform this operation.")]))

func createUrlWithString() -> NSURL {
 var urlString = "https://www.googleapis.com/oauth2/v4/token"
  urlString.append("?grant_type=")
    urlString.append("urn:ietf:params:oauth:grant-type:jwt-bearer")
     urlString.append("&assertion=")
      urlString.append(JWTtoken)
  return NSURL(string: urlString)!
}

  let response =  try drop.client.request(.other(method:"Post"), 
   String(describing: bodyURL),
      headers: ["Content-Type": "application/x-www-form-urlencoded"], 
         query: [:])

推荐答案

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

When you generate a service account credential you need to have in mind the following, taken from https://cloud.google.com/storage/docs/authentication: You can create a private key in the Cloud Platform Console by creating an OAuth Client ID for a service account. You can get your private key in JSON and PKCS12 format:

如果您使用 应用默认凭据,则需要 JSON 密钥Google Cloud Platform 之外的生产环境.JSON 密钥无法转换为其他格式.许多不同的编程语言和库都支持 PKCS12 (.p12).如果需要,您可以使用 OpenSSL 将密钥转换为其他格式(请参阅将私钥转换为其他格式).但是,PKCS12 密钥无法转换为 JSON 格式.

JSON keys are required if you are using Application Default Credentials in a production environment outside of Google Cloud Platform. JSON keys cannot be converted to other formats. PKCS12 (.p12) is supported by many different programming languages and libraries. If needed, you can convert the key into other formats using OpenSSL (see Converting the private key to other formats). However, PKCS12 keys cannot be converted to JSON format.

  1. 创建您的服务帐户,然后下载您的 .p12 文件.
  2. 使用 OpenSSL 将 p.12(又名 pkcs12)文件转换为 .pem(又名 pkcs1)

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

  1. 转到 github 并搜索 VaporJWT 并将其导入 Xcode.它将帮助您创建一个签名的 JSON Web 令牌.

  1. Go to github and search VaporJWT and import it in Xcode. It will help you create a signed JSON Web Token.

在这个 github 页面上,您将学习如何提取私钥以供 RSA 使用.

On this github page you will learn how to extract the private key for RSA use.

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

// convert .pem to der
openssl rsa -in /path/to/secret.pem -outform der -out /path/to/private.der

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

//convert .der to .base64
openssl base64 -in /path/to/private.der -out /path/to/Desktop/private.txt
In private.txt you have the private key encoded in base64 which you can finally use to sign you JWT. Then you can make calls to Google API with the signed JWT.

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 returnd 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"
}

这篇关于Swift Vapor unsupported_grant_type 无效签名/OAuth 访问令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆