码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • PHP 接入 Apple 登录对 identityToken 验证


    需用到 Composer 库:firebase/php-jwt,直接安装即可 composer require firebase/php-jwt

    资源

    生成 Apple 登录按钮图标:https://appleid.apple.com/signinwithapple/button

    官方文档(使用 Apple 登录):https://developer.apple.com/documentation/sign_in_with_apple

    生成并验证 Token:https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens

    校验 Identity Token:https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/verifying_a_user#3383769

    这个简单说下,苹果建议使用 5 个校验

    1. 使用公钥校验 JWS E256 签名
    2. 验证 nonce 随机数
    3. 验证 iss 字段包含 https://appleid.apple.com
    4. 验证 aud 字段为开发者的 client_id(即 Bundle ID)
    5. 验证当前时间早于 exp 字段时间

    JWKSet:https://developer.apple.com/documentation/sign_in_with_apple/jwkset

    获取 access_token/identityToken

    简单示例下 UniApp 中通过 uni.login() 方法获取 JWT

    let type = 'apple'
    
    uni.getProvider({
        service: 'oauth',
        success: (res) => {
            if (res.provider.includes(type)) {
                uni.login({
                    provider: type,
                    success: (authed) => {
                        console.log('三方登录获取用户信息成功', authed)
    
                        // Apple 登录这儿可用 authed.authResult 或 authed.appleInfo 得到授权数据
                        // authResult.access_token 与 appleInfo.identityToken 相同;authResult.openid 与 appleInfo.user 相同
                        // 但 Authorization Code 存在于 appleInfo,即 appleInfo.authorizationCode
                        // TODO: 登录请求
                    },
                    fail: (err) => {
                        console.log('三方登录获取登录信息失败', err)
    
                        if (err.errCode === 1001) {
                            // 登录已取消
                        } else {
                            // 其它错误情况
                        }
                    }
                })
            } else {
                // 当前环境不支持该登录方式
            }
        },
        fail: (err) => {
            console.log('获取三方登录信息异常', err)
        }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    获取 Apple 公钥

    公钥说明:https://developer.apple.com/documentation/sign_in_with_apple/fetch_apple_s_public_key_for_verifying_token_signature

    需要注意的是这段说明:

    The endpoint can return multiple keys, and the count of keys can vary over time. From this set of keys, select the key with the matching key identifier (kid) to verify the signature of any JSON Web Token (JWT) issued by Apple. For more information, see the JSON Web Signature specification.
    该接口会返回多个密钥,并且密钥的数量会随着时间发生变化。在该密钥集中,选择具有标识符(kid)的密钥来验证所有由 Apple 颁布的 JWT 签名。有关更多信息,请参阅 JSON Web 签名规范。

    公钥接口:https://appleid.apple.com/auth/keys

    因为该密钥集会产生变化,所以在不了解更新周期的情况下 不建议缓存 该内容

    获取后需进行解码 $keys = json_decode($keys, true);

    解析 $keys(公钥)

    这里就需要使用安装的 Composer 库了:

    try {
        $parsedKeys = \Firebase\JWT\JWK::parseKeySet($keys);
    } catch (Exception $e) {
        // 一定要捕获异常并自行处理解析 Key 失败的情况
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    解码获取 OpenID

    一定要捕获异常,decode 方法会抛出 7 种不同的异常,有个简单且友好的做法是单独判断过期异常并响应友好提示

    try {
        $decoded = \Firebase\JWT\JWT::decode($token, $parsedKeys);
    } catch (\Exception $e) {
        if ($e instanceof \Firebase\JWT\ExpiredException) {
            // 返回友好提示告知用户授权过期
        }
    
        // 可直接响应登录异常或参数异常
    }
    
    // JWT 中 sub 即为 OpenID
    $openId = $decoded->sub;
    // 邮箱地址
    $email = $decoded->email;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    多说两句

    1. Apple 登录授权后前端除了拿到 identityToken 还有一个 user 也是 OpenID,但是该 OpenID 不可信,可以在解码 JWT 后进行对比;
    2. JWT 的有效期是 10 分钟;

    解码后的完整结果(var_dump 示例):

    class stdClass#89 (10) {
      public $iss =>
      string(25) "https://appleid.apple.com"
      public $aud =>
      string(15) "Bundle ID"
      public $exp =>
      int(1695473542)
      public $iat =>
      int(1695387142)
      public $sub =>
      string(44) "此段为 OpenID"
      public $c_hash =>
      string(22) "一段 hash 值"
      public $email =>
      string(18) "Apple ID 邮箱地址"
      public $email_verified =>
      string(4) "true"
      public $auth_time =>
      int(1695387142)
      public $nonce_supported =>
      bool(true)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    【图像融合】基于matlab DSIFT多聚焦图像融合【含Matlab源码 2224期】
    原文远知行COO张力加盟逐际动力 自动驾驶进入视觉时代?
    Leo赠书活动-01期 【Python数据挖掘——入门进阶与实用案例分析】
    3.1 OrCAD中怎么创建新的原理图工程文件?OrCAD中原理图的设计纸张大小应该怎么设置?
    安卓常见设计模式4------原型模式(Kotlin版)
    C语言:结构体
    Chapter 11 Working with Dates and Times
    docker/云托管/serverless部署Node项目总结
    Qt QChart 自定义qChartView(重写鼠标事件)完美实现缩放与平移(新增android下手势缩放实现)
    获取分布式的请求响应内容
  • 原文地址:https://blog.csdn.net/maxsky/article/details/126904637
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号