基于Apple Sign In的SSO登录及后端用户创建与路由权限控制
Expo + Flask 第三方登录安全合规实现方案
1. 后端创建Apple登录对应用户流程
- 第一步:严格验证Apple JWT合法性
前端传来Apple JWT后,后端不能直接提取内容,必须用pyjwt库结合Apple公钥做验证:- 缓存Apple的公钥(避免频繁请求官方端点),用公钥验证JWT签名
- 校验字段:
iss必须是https://appleid.apple.com,aud匹配你的应用Bundle ID,exp未过期
- 第二步:提取可信身份信息
验证通过后,从JWT的sub(永久唯一user_id)和email(用户授权才会返回)字段提取信息,sub是关联用户的核心标识 - 第三步:创建或关联用户
查询数据库中是否存在apple_sub等于该sub的用户:- 不存在则创建新用户,存储
apple_sub、email(若有)、创建时间等字段 - 存在则更新用户最新登录时间等信息
- 不存在则创建新用户,存储
2. 重复登录的身份验证流程
重复登录时流程和首次一致:
- 前端重新获取Apple JWT并传给后端
- 后端验证JWT合法性,提取
sub - 通过
sub查询数据库,确认用户存在即完成身份验证,无需重复创建用户
3. 必须由后端生成JWT供客户端鉴权
Apple的JWT有效期通常只有5分钟,不适合长期鉴权,后端生成自有JWT是必要的:
- 自定义有效期(比如7天),可以包含数据库用户ID、权限等业务所需信息
- 客户端存储该JWT,后续API请求在
Authorization: Bearer <token>头中携带,后端验证JWT有效性即可完成鉴权 - Flask中生成和验证示例:
import jwt from datetime import datetime, timedelta # 生成后端JWT def generate_user_jwt(user_id): payload = { 'user_id': user_id, 'exp': datetime.utcnow() + timedelta(days=7), 'iat': datetime.utcnow() } return jwt.encode(payload, '你的后端加密密钥', algorithm='HS256') # 验证后端JWT def verify_user_jwt(token): try: payload = jwt.decode(token, '你的后端加密密钥', algorithms=['HS256']) return payload['user_id'] except jwt.ExpiredSignatureError: return None except jwt.InvalidTokenError: return None
4. 扩展Google/Facebook登录的安全合规方案
统一采用OAuth 2.0授权码流程,禁止用隐式流程或直接传递access token:
通用流程
- 前端调用Expo的
AuthSession或对应第三方SDK,获取授权码(而非直接拿access token) - 前端将授权码传给后端,由后端携带客户端ID、客户端密钥(密钥绝不能暴露在前端)向第三方令牌端点请求access token和ID token
- 后端验证第三方ID token的合法性:校验签名、过期时间、受众、签发者等字段
- 提取ID token中的唯一用户标识(Google用
sub,Facebook用id),查询数据库:不存在则创建用户,存在则关联账号,最后返回后端生成的JWT给前端
数据库设计建议
为支持多平台登录,用户表可设如下字段:
id(主键)email(可选,部分用户可能不授权邮箱)apple_sub(唯一,可选)google_sub(唯一,可选)facebook_id(唯一,可选)created_atupdated_at
这样同一个用户可通过不同平台登录,关联到同一账号。
内容的提问来源于stack exchange,提问作者SamKle3
相关产品推荐
相关产品推荐

