The Composer library is required: firebase/php-jwt
, just install it directlycomposer require firebase/php-jwt
Parsing JWT headers
uni.login()
Obtain JWT through the method in UniApp in a simple example
let type = 'apple'
uni.getProvider({
service: 'oauth',
success: function(res) {
if (res.provider.includes(type)) {
uni.login({
provider: type,
success: function(authed) {
console.log('三方登录获取用户信息成功', authed)
// Apple 登录这儿可用 authed.authResult 或 authed.appleInfo 得到授权数据
// authResult.access_token 与 appleInfo.identityToken 相同;authResult.openid 与 appleInfo.user 相同
// TODO: 登录请求
},
fail: function(err) {
console.log('三方登录获取登录信息失败', err)
if (err.errCode === 1001) {
// 登录已取消
} else {
// 其它错误情况
}
}
})
} else {
// 当前环境不支持该登录方式
}
},
fail: function(err) {
console.log('获取三方登录信息异常', err)
}
})
Example JWT:eyJhbGciOiAiUlMyNTYiLCJraWQiOiAiWXV5WG9ZIn0.
Note that the JWT actually obtained is very long, but only the header part is needed for verification, so we can intercept the header part first:
// 截取至第一个「点」的位置为 JWT 头
$header = json_decode(base64_decode(substr($token, 0, strpos($token, '.'))), true);
Get the Apple public key
The public key can be obtained directly through the interface: https://appleid.apple.com/auth/keys
Because there is no change, it is recommended to decode and cache after the first acquisition $keys = json_decode($keys, true)
, and take it directly from the cache next time
parse $keys
(publickey)
Here you need to use the installed Composer library:
$parsedKeys = \Firebase\JWT\JWK::parseKeySet($keys, true);
Get the target key
The target Key mentioned here is $keys
the Key used to decode the JWT in , of course you may want to loop $keys
, this is definitely not in the river!
The initially obtained $header
contains one , and there is also a key corresponding to the value kid
in the parsed$parsedKeys
kid
So we can directly judge:
if (!($parsedKeys[$header['kid']] ?? null)) {
throw new \Exception('JWT decode failed');
}
Decode to get OpenID
Be sure to catch the exception . decode
The method will throw 7 different exceptions. A simple and friendly way is to judge the expired exception separately and respond to the friendly prompt
try {
$decoded = \Firebase\JWT\JWT::decode($token, $parsedKeys[$header['kid']]);
} catch (\Exception $e) {
if ($e instanceof \Firebase\JWT\ExpiredException) {
// 返回友好提示告知用户授权过期
}
// 可直接响应登录异常或参数异常
}
// JWT 中 sub 即为 OpenID
$openId = $decoded->sub;
say a few more words
- After the Apple login authorization, the front end gets
identityToken
another oneuser
besidesOpenID
, but the isOpenID
untrustworthy, and can be compared after decoding the JWT; - The validity period of JWT is 10 minutes;