我们正在为在Google应用引擎上运行的节点应用构建api服务。目前,我已设置护照以使用'passport-http-bearer'策略来处理对我们的api的无浏览器http请求。这将从请求的授权标头中获取令牌,并使用该令牌对其进行身份验证。
我们还在构建一个本地python程序,该程序将请求Google提供令牌,我们将发送给节点应用程序以进行API调用。基于我在网络上看到的内容,似乎最好的方法是使用与GCP项目相关联的服务帐户。不幸的是,我见过的所有教程都使用服务帐户凭据来对Google API进行授权调用。我想使用服务帐户凭据对我们的应用程序API进行授权调用。我的问题是,我似乎无法找到任何代码从请求中获取持有者令牌,然后检查服务帐户是否说“是这是从正确的帐户生成”或“不应该拒绝此请求” 。任何有关如何弥合这一差距的见解都会非常有帮助。目前我的(最初的,非常差的)承载策略是:
passport.use(new BearerStrategy((token, done) => {
console.log('Bearer called with token: ', token);
if (token === '<Fake test token for SO>') {
console.log(' valid token!');
return done(null, { name: 'api_service' });
}
console.log(' invalid token...');
return done(null, false);
}));
答案 0 :(得分:1)
我们最终直接向google auth端点使用https请求。这是代码:
// Bearer token strategy for headless requests. This is used to authenticate API calls
passport.use(new BearerStrategy((token, done) => {
//forming the request to hit the google auth endpoint
const options = {
host: 'www.googleapis.com',
path: `/oauth2/v1/tokeninfo?access_token=${token}`,
headers: {
Accept: 'application/json'
}
};
//ask google endpoint if the token has the service account's email
https.get(options, (res) => {
res.setEncoding('utf8');
res.on('data', (chunk) => {
if (JSON.parse(chunk).email === config.get('SVCACCT_NAME')) {
//good request from the service account
return done(null, { name: 'api_service' });
}
//not the service account
return done(null, false);
});
}).on('error', (err) => {
console.log('Got API auth error: ', err.message);
//error or bad token. Either way reject it
return done(err, false);
});
}));
我们使用shell脚本和项目控制台中的服务帐户json文件来生成用于测试目的的令牌(这不会在mac上运行。我必须使用安装了jq的docker容器。)。稍后我们将其转换为python:
#!/bin/bash
if [ -z "${1}" ]; then
PROG=$( basename $0 )
echo "usage: ${PROG} <JSON account file>"
exit 1
fi
keyfile="${1}"
client_email=$( jq -r '.client_email' $keyfile )
if [ -z "${client_email}" ]; then
echo "JSON file does not appear to be valid"
exit 2
fi
private_key=$( jq '.private_key' $keyfile | tr -d '"' )
if [ -z "${private_key}" ]; then
echo "JSON file does not appear to be valid"
exit 3
fi
keyfile=$( mktemp -p . privkeyXXXXX )
echo -e $private_key > $keyfile
now=$( date "+%s" )
later=$( date -d '+30 min' "+%s" )
header=$( echo -n "{\"alg\":\"RS256\",\"typ\":\"JWT\"}" | base64 -w 0 )
claim=$( echo -n "{ \"iss\":\"${client_email}\", \"scope\":\"email profile\", \"aud\":\"https://www.googleapis.com/oauth2/v4/token\", \"exp\":${later}, \"iat\":${now} }" | base64 -w 0 )
data="${header}.${claim}"
sig=$( echo -n $data | openssl dgst -sha256 -sign $keyfile -keyform PEM -binary | base64 -w 0 )
rm -f $keyfile
stuff=$( echo "${header}.${claim}.${sig}" | sed 's!\/!%2F!g' | sed 's/=/%3D/g' | sed 's/\+/%2B/g' )
curl -d "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=${stuff}" https://www.googleapis.com/oauth2/v4/token
答案 1 :(得分:0)
Google提供了google.oauth2.id_token模块来帮助验证令牌。
verify_oauth2_token
已用于检查Google令牌:
verify_oauth2_token(id_token, request, audience=None)[source]
Verifies an ID Token issued by Google’s OAuth 2.0 authorization server.
[ ... ]
Returns: The decoded token.