WWDC Quick Look 💓 By SwiftGGTeam
Discover Sign in with Apple at Work & School

Discover Sign in with Apple at Work & School

观看原视频

Highlight

Sign in with Apple 最初只支持个人 Apple ID。这次更新将其扩展到 Managed Apple ID——由组织(学校或企业)通过 Apple School Manager 或 Apple Business Manager 管理的账号。这意味着学生、教师和员工可以用他们的 Managed Apple ID 一键登录你的 App。


核心内容

学校和企业里的登录问题,和个人 App 不一样。

个人用户用 Sign in with Apple 时,可以编辑姓名,也可以隐藏邮箱。组织账号的诉求更直接:App 需要知道是谁在登录,然后给他正确的权限。Slack 的例子很典型。员工用工作账号登录后,Slack 需要根据姓名和邮箱判断他能进入哪些频道。(02:15

WWDC 2022 的变化是:Sign in with Apple 支持 Managed Apple ID。Managed Apple ID 由组织拥有,通过 Apple School Manager 或 Apple Business Manager 管理。学生、教师、员工可以用这类账号登录支持 Sign in with Apple 的 App。(01:10

对于教育类 App,登录只是第一步。老师要发作业和通知,系统还需要提前导入学生、教师和班级。如果一个学区有几百或几千个学生,IT 管理员手工录入会很慢。Roster API 就是为这件事准备的:它让 App 通过 REST 端点读取 Apple School Manager 里的用户和班级数据。(05:35

整个流程分三层:

  1. 用户用 Managed Apple ID 登录 App。
  2. IT 管理员通过 OAuth 2.0 同意共享组织数据。
  3. App 后端用访问令牌调用 Roster API,导入用户和班级。

这场 Session 没有官方 Code tab 代码片段。下面的示例都按演讲展示的字段和流程整理,属于概念代码,用来说明请求结构,不代表 Apple 文档中的完整端点地址或 SDK 签名。


详细内容

Managed Apple ID 登录时,姓名和邮箱的处理方式

03:12)使用 Sign in with Apple at Work & School 时,App 可以访问姓名和邮箱字段。前提是授权请求包含 full name 和 email scopes。

演讲还提醒了一个边界情况:有些学校不会给年幼学生分配邮箱。遇到这种账号时,账号创建界面只显示姓名,邮箱不存在。(04:18

概念流程:成功授权后读取登录结果中的字段

userIdentifier = authorizationResult.user
fullName = authorizationResult.fullName
email = authorizationResult.email

saveOrUpdateAccount(
  stableUserID: userIdentifier,
  displayName: fullName,
  emailAddress: email
)

关键点:

  • userIdentifier 是稳定用户标识,后面可与 Roster API 返回的用户标识对应起来。
  • fullName 来自授权结果;Managed Apple ID 登录场景下,App 需要它做组织内身份识别。
  • email 可能不存在,教育场景尤其要处理空值。
  • stableUserID 应作为账号关联主键,邮箱更适合做展示或辅助匹配。

如果你已经实现 Sign in with Apple,不需要额外工作来支持 Managed Apple ID。Apple 在这次发布中把已有登录体验扩展到了组织账号。(05:04

在 Developer Portal 里申请组织数据 scope

08:24)Roster API 的接入先从 Developer Portal 开始。开发者进入 Certificates, Identifiers & Profiles,在 Account & Organizational Data Sharing 下配置主 App ID,并选择需要的 Organizational Data Sharing scopes。

本次发布提供两个 scope:

  • user access:访问用户数据。
  • class access:访问班级数据。

同时要配置 return URLs。后续 OAuth 2.0 授权完成后,授权码会回到这些 URL。(08:51

# 概念清单:Developer Portal 配置项
Primary App ID: com.example.education-app
Organizational Data Sharing Scopes:
  - user access
  - class access
Return URLs:
  - https://example.com/apple-school-manager/callback

关键点:

  • Primary App ID 绑定请求组织数据的 App。
  • user access 决定后端能否读取 Apple School Manager 中的用户信息。
  • class access 决定后端能否读取班级及其成员关系。
  • Return URLs 会进入 OAuth 2.0 授权流程,配置错误会导致授权码无法回到你的服务端。

用 OAuth 2.0 获取 Roster API 访问令牌

09:47)第二步是让 IT 管理员授权。演讲里的例子是 App 提供一个“Connect to Apple School Manager”按钮,管理员点击后进入 OAuth 2.0 流程。

第一个请求是 GET authorize endpoint。请求包含 client_idredirect_uristateresponse_typescopes。响应会把管理员带到 Apple 的同意界面。(10:16

# 概念请求:启动授权流程
GET {authorize endpoint}?
  client_id={your-client-id}&
  redirect_uri={registered-return-url}&
  state={csrf-protection-token}&
  response_type=code&
  scope={requested-organizational-data-scopes}

关键点:

  • client_id 标识请求数据访问的 App。
  • redirect_uri 必须匹配 Developer Portal 里配置的 return URL。
  • state 用来在回调时校验请求来源,避免串改授权流程。
  • response_type=code 表示请求授权码。
  • scope 对应前面申请的组织数据访问范围。

管理员点击 Allow 后,Apple 会把授权码传给你的 return URL。随后 App 后端向 token endpoint 发 POST 请求,用授权码换取 access token、过期时间和 refresh token。(11:08

# 概念请求:用授权码换取访问令牌
POST {token endpoint}
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code={authorization-code-from-return-url}&
redirect_uri={registered-return-url}&
client_id={your-client-id}

关键点:

  • authorization_code 来自管理员同意后的回调。
  • redirect_uri 继续使用注册过的 return URL。
  • 响应包含 access token,后续调用 Roster API 时放入 Authorization header。
  • 响应还包含 refresh token,access token 过期后用它换新令牌。

刷新令牌也是 POST token endpoint。演讲明确说,请求体包含标准 OAuth 参数和 refresh token,响应返回新的 access token 及过期时间。(11:49

# 概念请求:用 refresh token 更新访问令牌
POST {token endpoint}
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&
refresh_token={refresh-token}&
client_id={your-client-id}

关键点:

  • grant_type=refresh_token 表示这次不是重新让管理员授权。
  • refresh_token 应保存在服务端,不应暴露给客户端。
  • 新的 access token 继续用于读取用户和班级。

调用 users endpoint 导入学生、教师和员工

12:18)当前发布包含五类 Roster API 查询:获取班级列表、获取用户列表、获取特定班级、获取特定用户、获取某个班级里的用户。

演讲先展示 users endpoint。它有三个查询参数:pageTokenlimit 和可选的 rolepageTokenlimit 用于分页,role 可筛选 students、instructors 或 staff。请求头需要带上前面 OAuth 流程生成的 access token。(12:53

# 概念请求:读取最多 10 个学生
GET {users endpoint}?limit=10&role=students
Authorization: Bearer {access-token}

关键点:

  • limit=10 控制单次响应里最多返回多少用户。
  • role=students 把结果限定为学生。
  • Authorization header 使用 OAuth 2.0 access token。
  • 第一次请求可以不传 pageToken

响应是 JSON payload,包含 usersnextPageTokenmoreToFollow。用户对象包含 givenName、familyName、email、roles 等信息。演讲特别指出,响应里还有稳定的用户唯一标识,它和用户通过 Sign in with Apple 认证时 App 收到的标识相同。(13:14

{
  "users": [
    {
      "id": "stable-user-identifier",
      "givenName": "Fatima",
      "familyName": "Silva",
      "email": null,
      "roles": ["student"]
    }
  ],
  "nextPageToken": "next-page-token",
  "moreToFollow": true
}

关键点:

  • users 是当前页的用户数组。
  • id 是稳定用户标识,可与 Sign in with Apple 登录结果关联。
  • email 可能为 null,账号模型不能强依赖邮箱。
  • nextPageToken 用于下一次分页请求。
  • moreToFollowtrue 时,说明还有下一页。

调用 classes endpoint 建立班级关系

14:24)导入用户后,App 后端再请求 classes endpoint。它返回学区里的班级列表,以及班级和学生、教师之间的关系。

classes 请求包含 pageTokenlimit 两个查询参数。请求头和 users endpoint 相同,都要带 access token。(14:45

# 概念请求:读取最多 200 个班级
GET {classes endpoint}?limit=200&pageToken={next-page-token}
Authorization: Bearer {access-token}

关键点:

  • limit=200 对应演讲中的示例规模。
  • pageToken 表示这次请求处在分页导入过程中。
  • Authorization header 继续使用同一个授权流程得到的 access token。

响应里的 classes 包含班级名称、班级标识、教师 ID 列表和学生 ID 列表。这样 App 可以把前面导入的用户和班级关联起来。(15:10

{
  "classes": [
    {
      "id": "class-identifier",
      "name": "Biology 101",
      "instructorIds": ["teacher-user-id"],
      "studentIds": ["student-user-id-1", "student-user-id-2"]
    }
  ]
}

关键点:

  • classes 是当前页的班级数组。
  • id 是班级标识,用来更新或去重本地班级记录。
  • instructorIds 引用教师用户 ID。
  • studentIds 引用学生用户 ID。
  • 这些 ID 让 App 能构建“老师—班级—学生”的本地关系表。

IT 管理员有两层访问控制

15:47)组织数据由组织负责管理。个人 Sign in with Apple 是用户自己决定使用哪些 App;Work & School 场景下,IT 管理员要替组织控制哪些 App 可以登录,哪些 App 可以访问组织数据。

Apple School Manager、Apple Business Manager 和 Business Essentials 提供相同的控制模式:

  • Allow all apps:组织内用户可以用支持 Sign in with Apple 的所有 App 登录。
  • Allow only certain apps:管理员把允许的 App 加入列表,列表外 App 会显示错误。(16:50

Organizational Data Sharing 也有相同模式。管理员可以限制只有特定 App 能通过 Roster API 访问用户和班级信息。这是同意界面之外的第二层控制。(17:56

组织侧访问控制

Sign in with Apple at Work & School:
  - Allow all apps
  - Allow only certain apps

Organizational Data Sharing:
  - Allow all apps
  - Allow only certain apps
  - IT admin consent screen

关键点:

  • 登录权限和组织数据访问权限是两组控制。
  • “Allow only certain apps” 会把可用 App 限定在管理员维护的列表中。
  • Roster API 访问需要管理员同意,也受 Organizational Data Sharing 访问模式限制。
  • 接入教育组织时,开发者要把管理员授权和访问控制说明写进 onboarding 流程。

核心启发

1. 给教育 App 做一键开学导入

  • 做什么:让管理员点击“Connect to Apple School Manager”,自动导入学生、教师和班级。
  • 为什么值得做:Roster API 解决了开学前手工录入几百或几千个账号的问题。
  • 怎么开始:先申请 user access 和 class access,再实现 OAuth 2.0 授权流程,最后分页调用 users 与 classes endpoints。

2. 用稳定用户 ID 合并登录账号和花名册账号

  • 做什么:学生第一次用 Managed Apple ID 登录时,自动找到 Roster API 中对应的用户记录。
  • 为什么值得做:演讲说明 Roster API 返回的稳定用户标识,和 Sign in with Apple 认证时 App 收到的标识相同。
  • 怎么开始:账号表以 Sign in with Apple 的 user identifier 为主键,Roster 导入时用同一个标识更新姓名、角色和班级关系。

3. 为无邮箱学生设计账号模型

  • 做什么:允许学生账号没有邮箱,只显示姓名和班级信息。
  • 为什么值得做:Apple 明确提到,有些学校不会给年幼学生分配邮箱。
  • 怎么开始:把邮箱字段设为可空;登录、导入、通知设置都以稳定用户 ID 和组织角色为核心。

4. 给 IT 管理员做权限排障页

  • 做什么:在后台显示当前是否获得 user access、class access,以及管理员是否允许 App 访问组织数据。
  • 为什么值得做:Roster API 访问同时受 OAuth 同意界面和 Organizational Data Sharing 访问控制影响。
  • 怎么开始:在授权失败、令牌刷新失败、接口返回拒绝时,把错误归类到“未授权”“scope 不足”“组织侧未允许 App”三类提示。

5. 为班级同步做增量任务

  • 做什么:定时分页同步 users 和 classes,更新本地学生名单与任课教师关系。
  • 为什么值得做:Roster API 的响应设计包含分页字段,适合后端批量导入和持续同步。
  • 怎么开始:保存 nextPageToken、同步时间和本地导入版本;每次同步完成后再切换线上班级数据。

关联 Session

评论

GitHub Issues · utterances