PHP accesses Apple login to perform JWT verification on access_token/identityToken

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 $keysthe 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 $headercontains one , and there is also a key corresponding to the value kidin the parsed$parsedKeyskid

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 . decodeThe 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

  1. After the Apple login authorization, the front end gets identityTokenanother one userbesides OpenID, but the is OpenIDuntrustworthy, and can be compared after decoding the JWT;
  2. The validity period of JWT is 10 minutes;

Guess you like

Origin blog.csdn.net/maxsky/article/details/126904637