2024年4月27日 星期六

利用 Curl.exe 提交 Box 的 JWT 請求獲取 Access Token

利用 Curl.exe 提交 Box 的 JWT 請求獲取 Access Token

這邊比較難搞的是JWT,比較無腦一點就是直接載人家函式來弄,編碼之後會變成一長串文字,由Post送出去呼叫伺服器的API。


獲取 Box JSON File

請從BOX建立應用程式下載JWT認證Json私鑰檔案

$config 是直接從BOX上抓下來的Json檔案,他格式大概會長這樣子

{
  "boxAppSettings": {
    "clientID": "clientID",
    "clientSecret": "clientSecret",
    "appAuth": {
      "publicKeyID": "publicKeyID",
      "privateKey": "-----BEGIN ENCRYPTED PRIVATE KEY-----\nSTRING\n-----END ENCRYPTED PRIVATE KEY-----",
      "passphrase": "secret_passphrase"
    }
  },
  "enterpriseID": "enterpriseID"
}


打包成JWT令牌

一個完整的JWT是由三個部分的base64url組成,分別是 "$heder.$payload.$Signature"

這部分請參考這份代碼獲取 $assertion

hunandy14/PsJwt (github.com)



向伺服器發送JWT請求

$assertion 是完整的 JWT 令牌,包含簽名後的字串

要快速驗證內容有工具網站可以看 JSON Web Tokens - jwt.io



利用 Invoke-RestMethod 請求 AccessToken

    # Generate BoxToken Request
    $irmParams = @{
        Uri = 'https://api.box.com/oauth2/token'
        Method = 'Post'
        Body = @{
            grant_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer'
            assertion = "$tokenData.$signature"
            client_id = $config.boxAppSettings.clientID
            client_secret = $config.boxAppSettings.clientSecret
        }
        ContentType = 'application/x-www-form-urlencoded'
    }; if ($env:HTTP_PROXY) { $irmParams['Proxy'] = $env:HTTP_PROXY }

    # Request AccessToken
    try {
        $response = Invoke-RestMethod @irmParams
    } catch {
        Write-Error $PSItem.Exception.Message -ea 1
    }

    # Check AccessToken
    $response



利用外部程序 curl.exe 請求 AccessToken 

下面是用 PowerShell 寫的 Curl 請求代碼。這邊要注意一個坑是如果沒有加上 .exe 的話預設會呼叫內建的指令,內建會直接回傳 PowerShell 物件而不是文字,然後參數用法有不同不能直接換過去。

function RequestBoxToken {
    param (
        [string]$Assertion,
        [string]$ConfigPath
    )
    # Read configuration from JSON file
    $configContent = Get-Content $ConfigPath -Raw
    $config = ConvertFrom-Json $configContent

    # Generate Request queryString
    $url = 'https://api.box.com/oauth2/token'
    $proxyUrl = $env:http_proxy
    $response = curl.exe `
        -x $proxyUrl `
        -X POST $url `
        -d 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer' `
        -d "assertion=$Assertion" `
        -d "client_id=$($config.boxAppSettings.clientID)" `
        -d "client_secret=$($config.boxAppSettings.clientSecret)"
    # RequestBoxAccessToken
    $response = ConvertFrom-Json $response
    return $response
}



Python的請求方法 

import requests
import os
import json

def request_box_token(assertion, config_path):
    # 讀取設定檔
    with open(config_path, 'r') as file:
        config = json.load(file)

    url = 'https://api.box.com/oauth2/token'

    # 設置代理
    http_proxy = os.getenv('http_proxy')
    https_proxy = os.getenv('https_proxy')
    proxies = {}
    if http_proxy:
        proxies['http'] = http_proxy
    if https_proxy:
        proxies['https'] = https_proxy

    payload = {
        'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
        'assertion': assertion,
        'client_id': config['boxAppSettings']['clientID'],
        'client_secret': config['boxAppSettings']['clientSecret']
    }
    response = requests.post(url, data=payload, proxies=proxies if proxies else None)
    return response.json()

# 使用方法
assertion = '你的assertion'
config_path = 'config.json'  # 設定檔路徑
response = request_box_token(assertion, config_path)
print(response)




官方SDK請求方法

import json
from boxsdk import Client, JWTAuth

# 載入官方 JSON 檔案
with open('config.json') as json_file:
    config = json.load(json_file)

# 創建 JWTAuth 認證對象
auth = JWTAuth(
    client_id=config['boxAppSettings']['clientID'],
    client_secret=config['boxAppSettings']['clientSecret'],
    enterprise_id=config['enterpriseID'],
    jwt_key_id=config['boxAppSettings']['appAuth']['publicKeyID'],
    rsa_private_key_data=config['boxAppSettings']['appAuth']['privateKey'].replace('\\n', '\n'),
    rsa_private_key_passphrase=config['boxAppSettings']['appAuth']['passphrase']
)

# 獲取 Access Token
access_token = auth.authenticate_instance()
print(f"access_token: {access_token}")

# 使用 Access Token 創建 Box Client
client = Client(auth)

# 驗證登錄並獲取當前用戶信息
current_user = client.user().get()
print('Authenticated as:', current_user.name)


這個只要拿到 json 檔案並且審核通過後就可以直接拿來用了。至於如何通過 proxy 可以參考這一篇的說明 
CHG: 利用 Curl.exe 提交 Box 的 JWT 請求獲取 Access Token (charlottehong.blogspot.com)



沒有留言:

張貼留言