2017-05-12 10 views
2

Googleドライブでファイルを操作する方法については、PowerShellでは個人用のOAuth2トークンを使用していますが、ドメイン全体の特権では扱いません。私が理解からGoogleドライブAPIを使用しようとしたJWTの署名が正しくありません

、ワークフローはこのように書きます:

  1. ヘッダを作成し、base64でエンコード
  2. は、請求項を作成し、base64でエンコード
  3. は、RSA256でそれに署名し、ヘッダーと主張を組み合わせますそして、Googleが提供する秘密鍵

私は以下のコードを参照してくださいステップ3で問題を抱えている:

$firstdate = Get-Date -Year 1970 -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0 -Millisecond 0 
$endtime = (New-TimeSpan -Start $firstdate -End (Get-Date).AddMinutes(30).ToUniversalTime()).TotalSeconds 
$issuetime = (New-TimeSpan -Start $firstdate -End (Get-Date).ToUniversalTime()).TotalSeconds 
$jsonfile = Get-Content 'secret_file.json' | ConvertFrom-Json 

$headerhash = [ordered]@{ 
    'alg' = 'RS256' 
    'typ' = 'JWT' 
} 
$headerjson = $headerhash | ConvertTo-Json -Compress 
$encodedheader = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($headerjson)) 

$claimhash = [ordered]@{ 
    'iss' = $jsonfile.client_email 
    'scope' = 'https://www.googleapis.com/auth/drive' 
    'aud' = 'https://www.googleapis.com/oauth2/v4/token' 
    'exp' = [math]::Round($endtime,0) 
    'iat' = [math]::Round($issuetime,0) 
} 
$claimjson = $claimhash | ConvertTo-Json -Compress 
$encodedclaim = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($claimjson)) 

#$sha = [System.Security.Cryptography.RSACryptoServiceProvider]::Create() 
#$sha.Key = [System.Text.Encoding]::UTF8.Getbytes($jsonfile.private_key) 
#$sha.FromXmlString($sha.ToXmlString($jsonfile.private_key)) 
#$signature = $sha.ComputeHash([System.Text.Encoding]::UTF8.GetBytes("$encodedheader.$encodedclaim")) 
#$signature = $sha.SignData([System.Text.Encoding]::UTF8.GetBytes("$encodedheader.$encodedclaim"),[System.Security.Cryptography.CryptoConfig]::MapNameToOID('RSASSA-PKCS1-V1_5-SIGN')) 
#$encodedsignature = [System.Convert]::ToBase64String($signature) 
#$formatter = [System.Security.Cryptography.RSAPKCS1SignatureFormatter]::new($sha) 
#$formatter.SetKey($sha) 
#$formatter.CreateSignature([System.Text.Encoding]::UTF8.GetBytes("$encodedheader.$encodedclaim")) 

$jws = "$encodedheader.$encodedclaim" 
$encodedjws = [System.Text.Encoding]::UTF8.GetBytes($jws) 

$rsa = [System.Security.Cryptography.RSACryptoServiceProvider]::Create() 
# This is the key -- need to convert PEM to proper format 
$rsa.FromXmlString($rsa.ToXmlString($jsonfile.private_key)) 
$sha256OID = [System.Security.Cryptography.CryptoConfig]::MapNameToOID("SHA256") 
$signature = $rsa.SignData($encodedjws,$sha256OID) 
$encodedsignature = [System.Convert]::ToBase64String($signature) 

$jwt = "$encodedheader.$encodedclaim.$encodedsignature" 

$requestUri = 'https://www.googleapis.com/oauth2/v4/token' 
$method = 'POST' 
$body = [ordered]@{ 
    'grant_type' = 'urn:ietf:params:oauth:grant-type:jwt-bearer' 
    'assertion' = $jwt 
} 
Invoke-webrequest -Uri $requestUri -Method $method -Body $body -ContentType application/x-www-form-urlencoded 

エラーは、悪いJWT署名を示しています。 Googleが提供している秘密鍵はPEM形式ですが、Powershellが理解できるものに変換する際に問題があります。

答えて

0

私はOWINライブラリを使ってそれをやり遂げるまで、同じ問題がしばらくありました。

私のPSGSuiteモジュールの一部であるGet-GSToken関数へのリンクです。あなたが必要とするものを実行したい場合(この機能の目的はトークンを取得することです)、これを裂くことができますが、それを動作させるにはnugetフォルダも必要です(OWINライブラリはそこ):

https://github.com/nferrell/PSGSuite/blob/master/Public/Get-GSToken.ps1

はサンプルのため、モジュール全体をつかむお気軽に! Google APIコールのほぼすべてをPowerShell関数にラップしました。すべて関数Get-GSTokenを利用して、関数が必要とするスコープでトークンを最初に取得します。

注意事項:これは、サービスアカウントとP12キーファイルを活用し、clientsecrets.jsonファイルのキータイプではありません。私はJSONファイルを使って純粋なPowershellを使って作業用JWTを構築する方法がわかりませんが、P12 + OWINライブラリは驚くほどうまく機能します。

+0

素晴らしい、@ nferrell、ありがとう。この関数でOWINライブラリを使用しているのは、base64エンコーディングを行うことだけです。モジュールの残りの部分がどこを使っているのかは分かりませんが、[System.Convert] :: ToBase64String()を簡単に使うことができます。私はこれを解決したと考えることができると思う。 –

+0

OWINライブラリは、( '$ encoder = New-Object Microsoft.Owin.Security.DataHandler.Encoder.Base64UrlTextEncoder')のための本当の組み込みライブラリがない* WebSafe/URLSafe * Base64エンコーディングを特別に扱います...私はチャーの交換とパディングの会計処理による回避策がありましたが、私が取り組んでいた数ヶ月ではうまくいかなかったのです。私はそれが迅速かつ簡単に動作することを知っている場合私は個人的に外部のライブラリを使用して完全にうまくいく –

関連する問題