Oauth 2.0 谷歌OAuth2返回“;无效的授权”;-签署JWT问题
我有一个OAuth2Java客户机(用于服务器到服务器的应用程序),它试图创建一个JWT,然后使用私钥(从GoogleAPI控制台)进行签名——请参见以下页面。然而,GoogleOAuth2不断返回“无效授权” 以下是客户端代码:Oauth 2.0 谷歌OAuth2返回“;无效的授权”;-签署JWT问题,oauth-2.0,google-oauth,Oauth 2.0,Google Oauth,我有一个OAuth2Java客户机(用于服务器到服务器的应用程序),它试图创建一个JWT,然后使用私钥(从GoogleAPI控制台)进行签名——请参见以下页面。然而,GoogleOAuth2不断返回“无效授权” 以下是客户端代码: import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.MessageFormat;
import org.apache.commons.codec.binary.Base64;
public class WebToken
{
private String iss;
private String prn;
private String scope;
private String aud;
private long exp;
private long iat;
private String keystoreLoc;
private String keyAlias;
private String password;
public WebToken(String iss, String prn, String scope, String aud, long exp, long iat, String p12file, String keyAlias, String password)
{
super();
this.iss = iss;
this.prn = prn;
this.scope = scope;
this.aud = aud;
this.exp = exp;
this.iat = iat;
this.keystoreLoc = p12file;
this.keyAlias = keyAlias;
this.password = password;
}
public static String encodeBase64(byte[] rawData)
{
byte[] data = Base64.encodeBase64(rawData);
return new String(data);
}
public String getToken()
throws Exception
{
String header = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}";
//String header = "{\"alg\":\"RS256\"}";
String claimTemplate = "'{'\"iss\": \"{0}\", \"prn\": \"{1}\", \"scope\": \"{2}\", \"aud\": \"{3}\", \"exp\": {4}, \"iat\": {5}'}'";
StringBuffer token = new StringBuffer();
//Encode the JWT Header and add it to our string to sign
token.append(encodeBase64(header.getBytes("UTF-8")));
//Separate with a period
token.append(".");
//Create the JWT Claims Object
String[] claimArray = new String[6];
claimArray[0] = this.iss;
claimArray[1] = this.prn;
claimArray[2] = this.scope;
claimArray[3] = this.aud;
claimArray[4] = "" + this.exp;
claimArray[5] = "" + this.iat;
MessageFormat claims = new MessageFormat(claimTemplate);
String payload = claims.format(claimArray);
print(payload);
//Add the encoded claims object
token.append(encodeBase64(payload.getBytes("UTF-8")));
//Load the private key
PrivateKey privateKey = getPrivateKey(keystoreLoc, password);
byte[] sig = signData(token.toString().getBytes("UTF-8"), privateKey);
String signedPayload = encodeBase64(sig);
//Separate with a period
token.append(".");
//Add the encoded signature
token.append(signedPayload);
return token.toString();
}
private PrivateKey getPrivateKey(String keyFile, String password)
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException
{
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(new FileInputStream(keyFile), password.toCharArray());
PrivateKey privateKey = (PrivateKey) keystore.getKey(keyAlias, password.toCharArray());
return privateKey;
}
public byte[] signData(byte[] data, PrivateKey privateKey)
throws InvalidKeyException, SignatureException, NoSuchAlgorithmException
{
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
public static void print(String msg)
{
System.out.println(msg);
}
public static void main(String[] args)
throws Exception
{
String iss = "????????@developer.gserviceaccount.com";
String prn = "xxx@gmail.com";
String scope = "https://www.googleapis.com/auth/urlshortener";
String aud = "https://accounts.google.com/o/oauth2/token";
long iat = System.currentTimeMillis()/1000 - 60;
long exp = iat + 3600;
String keystoreLoc = "D:\\OAuth2\\google_sURL\\pkey1.p12";
String keyAlias = "privatekey";
String pwd = "notasecret";
WebToken jwt = new WebToken(iss, prn, scope, aud, exp, iat, keystoreLoc, keyAlias, pwd);
String token = jwt.getToken();
print(token);
// urn:ietf:params:oauth:grant-type:jwt-bearer
print("curl -vSs -X POST -d \"grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=" + token +
"\" -k https://accounts.google.com/o/oauth2/token");
}
}
然后使用curl获取访问令牌:curl-k-vSs-X POST-d“grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant type%3Ajwt承载和断言=”
知道怎么了吗
============================
最后我自己发现了问题:
1) 在JWT中,不要设置“prn”(但根据需要,您可能需要设置)
2) 使用“@developer.gserviceaccount.com”作为“iss”
以下是更新的代码:
import java.io.FileInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.text.MessageFormat;
import org.apache.commons.codec.binary.Base64;
public class WebToken
{
private String iss;
private String scope;
private String aud;
private long exp;
private long iat;
private String keystoreLoc;
private String keyAlias;
private String password;
public WebToken(String iss, String scope, String aud, long exp, long iat, String p12file, String keyAlias, String password)
{
super();
this.iss = iss;
this.scope = scope;
this.aud = aud;
this.exp = exp;
this.iat = iat;
this.keystoreLoc = p12file;
this.keyAlias = keyAlias;
this.password = password;
}
/**
* Performs base64-encoding of input bytes.
*
* @param rawData * Array of bytes to be encoded.
* @return * The base64 encoded string representation of rawData.
*/
public static String encodeBase64(byte[] rawData)
{
String data = Base64.encodeBase64URLSafeString(rawData);
return data;
}
public String getToken()
throws Exception
{
String header = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}";
String claimTemplate = "'{'\"iss\": \"{0}\", \"scope\": \"{1}\", \"aud\": \"{2}\", \"exp\": {3}, \"iat\": {4}'}'";
StringBuffer token = new StringBuffer();
//Encode the JWT Header and add it to our string to sign
token.append(encodeBase64(header.getBytes("UTF-8")));
//Separate with a period
token.append(".");
//Create the JWT Claims Object
String[] claimArray = new String[6];
claimArray[0] = this.iss;
claimArray[1] = this.scope;
claimArray[2] = this.aud;
claimArray[3] = "" + this.exp;
claimArray[4] = "" + this.iat;
MessageFormat claims = new MessageFormat(claimTemplate);
String payload = claims.format(claimArray);
print(payload);
//Add the encoded claims object
token.append(encodeBase64(payload.getBytes("UTF-8")));
//Load the private key
PrivateKey privateKey = getPrivateKey(keystoreLoc, password);
byte[] sig = signData(token.toString().getBytes("UTF-8"), privateKey);
String signedPayload = encodeBase64(sig);
//Separate with a period
token.append(".");
//Add the encoded signature
token.append(signedPayload);
return token.toString();
}
private PrivateKey getPrivateKey(String keyFile, String password)
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException
{
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(new FileInputStream(keyFile), password.toCharArray());
PrivateKey privateKey = (PrivateKey) keystore.getKey(keyAlias, password.toCharArray());
return privateKey;
}
public byte[] signData(byte[] data, PrivateKey privateKey)
throws InvalidKeyException, SignatureException, NoSuchAlgorithmException
{
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
public static void print(String msg)
{
System.out.println(msg);
}
public static void main(String[] args)
throws Exception
{
String iss = "<client id email>@developer.gserviceaccount.com";
String scope = "https://www.googleapis.com/auth/urlshortener";
String aud = "https://accounts.google.com/o/oauth2/token";
long iat = (System.currentTimeMillis()/1000)-60;
long exp = iat + 3600;
String keystoreLoc = "<privatekey>.p12";
String keyAlias = "privatekey";
String pwd = "notasecret";
WebToken jwt = new WebToken(iss, scope, aud, exp, iat, keystoreLoc, keyAlias, pwd);
String token = jwt.getToken();
print(token);
print("\\curl\\curl -vSs -X POST -H \"Content-Type: application/x-www-form-urlencoded\"" +
" -d \"grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=" + token +
"\" -k https://accounts.google.com/o/oauth2/token");
}
}
import java.io.FileInputStream;
导入java.io.IOException;
导入java.security.InvalidKeyException;
导入java.security.KeyStore;
导入java.security.KeyStoreException;
导入java.security.NoSuchAlgorithmException;
导入java.security.PrivateKey;
导入java.security.Signature;
导入java.security.SignatureException;
导入java.security.UnrecoverableKeyException;
导入java.security.cert.CertificateException;
导入java.text.MessageFormat;
导入org.apache.commons.codec.binary.Base64;
公共类WebToken
{
专用字符串iss;
私有字符串范围;
私人字符串aud;
私人长期出口;
私人长途电话;
私有字符串keystoreLoc;
私有字符串密钥别名;
私有字符串密码;
公共WebToken(字符串iss、字符串范围、字符串aud、长exp、长iat、字符串P12文件、字符串keyAlias、字符串密码)
{
超级();
this.iss=iss;
this.scope=范围;
this.aud=aud;
this.exp=exp;
this.iat=iat;
this.keystoreLoc=p12文件;
this.keyalis=keyalis;
this.password=密码;
}
/**
*对输入字节执行base64编码。
*
*@param rawData*要编码的字节数组。
*@return*原始数据的base64编码字符串表示形式。
*/
公共静态字符串encodeBase64(字节[]rawData)
{
String data=Base64.encodebase64urlsafetstring(rawData);
返回数据;
}
公共字符串getToken()
抛出异常
{
字符串头=“{\“alg\”:\“RS256\”,\“typ\”:\“JWT\”}”;
String claimTemplate=“{'\'iss\':\“{0}\”、\'scope\':\“{1}\”、\'aud\':\“{2}\”、\'exp\':{3}、\'iat\':{4}';
StringBuffer令牌=新的StringBuffer();
//对JWT头进行编码,并将其添加到字符串中进行签名
token.append(encodeBase64(header.getBytes(“UTF-8”));
//以句号分开
标记。附加(“.”);
//创建JWT声明对象
String[]clairray=新字符串[6];
Clairerray[0]=this.iss;
索偿权[1]=此范围;
索偿权[2]=本澳元;
Claimerray[3]=“this.exp;
Claimerray[4]=“this.iat;
MessageFormat索赔=新的MessageFormat(索赔模板);
字符串有效载荷=claims.format(claimerray);
打印(有效载荷);
//添加编码的索赔对象
token.append(encodeBase64(payload.getBytes(“UTF-8”));
//加载私钥
PrivateKey PrivateKey=getPrivateKey(keystoreLoc,密码);
byte[]sig=signData(token.toString().getBytes(“UTF-8”),privateKey);
String signedPayload=encodeBase64(sig);
//以句号分开
标记。附加(“.”);
//添加编码的签名
token.append(signedPayload);
返回token.toString();
}
private PrivateKey getPrivateKey(字符串密钥文件、字符串密码)
抛出KeyStoreException、IOException、NoSuchAlgorithmException、CertificateException、UnrecoverableKeyException
{
KeyStore KeyStore=KeyStore.getInstance(“PKCS12”);
load(新文件输入流(keyFile),password.toCharArray());
PrivateKey PrivateKey=(PrivateKey)keystore.getKey(keyalis,password.toCharArray());
返回私钥;
}
公共字节[]signData(字节[]数据,私钥私钥)
抛出InvalidKeyException、SignatureException、NoSuchAlgorithmException
{
Signature=Signature.getInstance(“SHA256withRSA”);
signature.initSign(私钥);
签名。更新(数据);
返回签名。sign();
}
公共静态无效打印(字符串消息)
{
System.out.println(msg);
}
公共静态void main(字符串[]args)
抛出异常
{
字符串iss=“@developer.gserviceaccount.com”;
字符串范围=”https://www.googleapis.com/auth/urlshortener";
字符串aud=”https://accounts.google.com/o/oauth2/token";
长iat=(System.currentTimeMillis()/1000)-60;
长期有效期=iat+3600;
字符串keystoreLoc=“.p12”;
字符串keyalis=“privatekey”;
字符串pwd=“notasecret”;
WebToken jwt=新的WebToken(iss、范围、aud、exp、iat、KeystoreOC、keyAlias、pwd);
字符串标记=jwt.getToken();
打印(代币);
打印(“\\curl\\curl-vSs-X POST-H\”内容类型:application/X-www-form-urlencoded\”+
“-d\”授权类型=urn%3aitef%3aparms%3oauth%3aagrant类型%3Ajwt承载与断言=“+token+
“\”-khttps://accounts.g
import java.io.FileInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.text.MessageFormat;
import org.apache.commons.codec.binary.Base64;
public class WebToken
{
private String iss;
private String scope;
private String aud;
private long exp;
private long iat;
private String keystoreLoc;
private String keyAlias;
private String password;
public WebToken(String iss, String scope, String aud, long exp, long iat, String p12file, String keyAlias, String password)
{
super();
this.iss = iss;
this.scope = scope;
this.aud = aud;
this.exp = exp;
this.iat = iat;
this.keystoreLoc = p12file;
this.keyAlias = keyAlias;
this.password = password;
}
/**
* Performs base64-encoding of input bytes.
*
* @param rawData * Array of bytes to be encoded.
* @return * The base64 encoded string representation of rawData.
*/
public static String encodeBase64(byte[] rawData)
{
String data = Base64.encodeBase64URLSafeString(rawData);
return data;
}
public String getToken()
throws Exception
{
String header = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}";
String claimTemplate = "'{'\"iss\": \"{0}\", \"scope\": \"{1}\", \"aud\": \"{2}\", \"exp\": {3}, \"iat\": {4}'}'";
StringBuffer token = new StringBuffer();
//Encode the JWT Header and add it to our string to sign
token.append(encodeBase64(header.getBytes("UTF-8")));
//Separate with a period
token.append(".");
//Create the JWT Claims Object
String[] claimArray = new String[6];
claimArray[0] = this.iss;
claimArray[1] = this.scope;
claimArray[2] = this.aud;
claimArray[3] = "" + this.exp;
claimArray[4] = "" + this.iat;
MessageFormat claims = new MessageFormat(claimTemplate);
String payload = claims.format(claimArray);
print(payload);
//Add the encoded claims object
token.append(encodeBase64(payload.getBytes("UTF-8")));
//Load the private key
PrivateKey privateKey = getPrivateKey(keystoreLoc, password);
byte[] sig = signData(token.toString().getBytes("UTF-8"), privateKey);
String signedPayload = encodeBase64(sig);
//Separate with a period
token.append(".");
//Add the encoded signature
token.append(signedPayload);
return token.toString();
}
private PrivateKey getPrivateKey(String keyFile, String password)
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException
{
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(new FileInputStream(keyFile), password.toCharArray());
PrivateKey privateKey = (PrivateKey) keystore.getKey(keyAlias, password.toCharArray());
return privateKey;
}
public byte[] signData(byte[] data, PrivateKey privateKey)
throws InvalidKeyException, SignatureException, NoSuchAlgorithmException
{
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
public static void print(String msg)
{
System.out.println(msg);
}
public static void main(String[] args)
throws Exception
{
String iss = "<client id email>@developer.gserviceaccount.com";
String scope = "https://www.googleapis.com/auth/urlshortener";
String aud = "https://accounts.google.com/o/oauth2/token";
long iat = (System.currentTimeMillis()/1000)-60;
long exp = iat + 3600;
String keystoreLoc = "<privatekey>.p12";
String keyAlias = "privatekey";
String pwd = "notasecret";
WebToken jwt = new WebToken(iss, scope, aud, exp, iat, keystoreLoc, keyAlias, pwd);
String token = jwt.getToken();
print(token);
print("\\curl\\curl -vSs -X POST -H \"Content-Type: application/x-www-form-urlencoded\"" +
" -d \"grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=" + token +
"\" -k https://accounts.google.com/o/oauth2/token");
}
}