#idcon vol.27 - Sign in with Apple 特集
※ ヤフースコアのことは禁句な!!
https://idcon.org
Sign in with Apple
~ diff from OIDC / OAuth 2.0 & characteristic identifiers design ~
@nov
https://matake.jp
https://rubygems.org/gems/apple_id
https://signin-with-apple.herokuapp.com
Diff from OIDC / OAuth 2.0
OIDC Spec Violations
❖ when nonce is provided in the code or code id_token grant types, it won’t be
included in the id_token returned #FIXED
❖ the code id_token response type does not include c_hash in the returned
id_token #FIXED
❖ the code id_token response type returns the response parameters as query
parameters, not in the fragment
❖ providing a prompt parameter with any value (e.g. login or consent) or empty
results in a 400 with no body #FIXED
❖ when max_age is requested, the id_token does not include an auth_time
claim #FIXED
http://bit.ly/diff-between-siwa-and-oidc
Peculiarities (奇妙な点)
❖ no Discovery document is published at https://appleid.apple.com/.well-known/openid-
configuration which makes developers have to read through the Apple docs to find out
about endpoints, scopes, signing algorithms, authentication methods, etc. #FEELS-OK
❖ no User Info endpoint is provided which means all of the claims about users have to be
included in the (expiring and potentially large) id_token
❖ does not include different claims in the id_token based on scope #PARTIALLY-FIXED
❖ the token endpoint does not accept client_secret_basic as authentication method
(required for OpenID Connect certification) and actually the default method to use for
Clients when there’s no Discovery document that says otherwise
http://bit.ly/diff-between-siwa-and-oidc
Peculiarities (奇妙な点)
❖ authentication towards the token endpoint requires a (custom) JWT assertion as a
client_secret in a client_secret_post authentication method whereas the more
appropriate private_key_jwt authentication method as defined in RFC7523 could have
been used
❖ using unsupported or wrong parameters (e.g. non-existing response_type, scope,
client_id, or redirect_uri) always results in the same message in the browser that says
“Your request could not be completed because of an error. Please try again later.”
without any explanation about what happened, why this is an error or how to fix it
#FEELS-OK #EXCEPT-FOR-SCOPE
❖ exchanging the authorization code according to https://developer.apple.com/
documentation/signinwithapplerestapi/generate_and_validate_tokens should present
a non-standard grant_type=authorization_token but using the standards-compliant
grant_type=authorization_code actually works whereas the former does not, so the
documentation is incorrect #FIXED
http://bit.ly/diff-between-siwa-and-oidc
Peculiarities (奇妙な点)
❖ the Authorization Code grant type (for public Clients?) does not use PKCE to avoid
code injection and code replay attacks #FEELS-OK
❖ when using the sample app available at https://github.com/aaronpk/sign-in-with-
apple-example, adding openid as a scope leads to an error message and it works just
with name and email as scope values; this behavior seems to be inconsistent across
Clients: for some it works, or at least does not lead to errors, for others it does not
work and ends with an error #FIXED?
❖ The scope value of only the very first request by an application is respected. If an
application initially requests only the name scope, and the user allows it, it is then
impossible to later also request the email scope.
http://bit.ly/diff-between-siwa-and-oidc
Characteristic Identifiers Design
Team X
Team X
App A
Team X
Primary App A
Service A-1
Team X
Primary App A
App A-3
App A-2
App A-1
Service A-1
Service A-2
Team X
Primary App A
App A-3
App A-2
App A-1
Service A-1
Service A-2
Primary App B
App B-2
App B-1
Service B-1
User-related Identifiers Design
User ID (sub)
Team X
Primary App A
App A-3
App A-2
App A-1
Service A-1
Service A-2
Primary App B
App B-2
App B-1
Service B-1
Private Email
Team X
Primary App A
App A-3
App A-2
App A-1
Service A-1
Service A-2
Primary App B
App B-2
App B-1
Service B-1
User ID :
Apple User ID :
Public Emails :
Private Email :
12345
000123.abc2xyz.0012
foo@icloud.com
foo@me.com
for-team-x@privaterelay.appleid.com
Q1. Which address to use in each app’s context?
Q2. How to handle email changes after revocation?
Consent Screen
Team X
Primary App A
App A-3
App A-2
App A-1
Service A-1
Service A-2
Primary App B
App B-2
App B-1
Service B-1
Revocation Screen
Team X
Primary App A
App A-3
App A-2
App A-1
Service A-1
Service A-2
Primary App B
App B-2
App B-1
Service B-1
Careful branding strategy required for primary app grouping
Developer-related Identifiers Design
Client ID
Team X
Primary App A
App A-3
App A-2
App A-1
Service A-1
Service A-2
Primary App B
App B-2
App B-1
Service B-1
Private Key
Team X
Primary App A
App A-3
App A-2
App A-1
Service A-1
Service A-2
Primary App B
App B-2
App B-1
Service B-1
CLIENT_ID is of the app / service which originally received the
authorization code, not of the backend server which accesses the token
endpoint, even when refreshing tokens.
Private Email Relay Service
Team X
Primary App A
App A-3
App A-2
App A-1
Service A-1
Service A-2
Primary App B
App B-2
App B-1
Service B-1
MAX 10
MAX 10
For the 11th domain / address, setup new team !?!?
Primary App A sends emails from
App A-1 sends emails from
App A-2 sends emails from
Service A-1 sends emails from
no-reply@primary-app-a.example.com
no-reply@app-a1.example.com
no-reply@app-a2.example.com
no-reply@service-a1.example.com
:
【結論】
iOS, iPad OS, Safari での UX は最高だが
クセが強いので注意

Sign in with Apple

  • 1.
    #idcon vol.27 -Sign in with Apple 特集 ※ ヤフースコアのことは禁句な!! https://idcon.org
  • 2.
    Sign in withApple ~ diff from OIDC / OAuth 2.0 & characteristic identifiers design ~ @nov
  • 3.
  • 4.
  • 5.
  • 6.
    Diff from OIDC/ OAuth 2.0
  • 7.
    OIDC Spec Violations ❖when nonce is provided in the code or code id_token grant types, it won’t be included in the id_token returned #FIXED ❖ the code id_token response type does not include c_hash in the returned id_token #FIXED ❖ the code id_token response type returns the response parameters as query parameters, not in the fragment ❖ providing a prompt parameter with any value (e.g. login or consent) or empty results in a 400 with no body #FIXED ❖ when max_age is requested, the id_token does not include an auth_time claim #FIXED http://bit.ly/diff-between-siwa-and-oidc
  • 8.
    Peculiarities (奇妙な点) ❖ noDiscovery document is published at https://appleid.apple.com/.well-known/openid- configuration which makes developers have to read through the Apple docs to find out about endpoints, scopes, signing algorithms, authentication methods, etc. #FEELS-OK ❖ no User Info endpoint is provided which means all of the claims about users have to be included in the (expiring and potentially large) id_token ❖ does not include different claims in the id_token based on scope #PARTIALLY-FIXED ❖ the token endpoint does not accept client_secret_basic as authentication method (required for OpenID Connect certification) and actually the default method to use for Clients when there’s no Discovery document that says otherwise http://bit.ly/diff-between-siwa-and-oidc
  • 9.
    Peculiarities (奇妙な点) ❖ authenticationtowards the token endpoint requires a (custom) JWT assertion as a client_secret in a client_secret_post authentication method whereas the more appropriate private_key_jwt authentication method as defined in RFC7523 could have been used ❖ using unsupported or wrong parameters (e.g. non-existing response_type, scope, client_id, or redirect_uri) always results in the same message in the browser that says “Your request could not be completed because of an error. Please try again later.” without any explanation about what happened, why this is an error or how to fix it #FEELS-OK #EXCEPT-FOR-SCOPE ❖ exchanging the authorization code according to https://developer.apple.com/ documentation/signinwithapplerestapi/generate_and_validate_tokens should present a non-standard grant_type=authorization_token but using the standards-compliant grant_type=authorization_code actually works whereas the former does not, so the documentation is incorrect #FIXED http://bit.ly/diff-between-siwa-and-oidc
  • 10.
    Peculiarities (奇妙な点) ❖ theAuthorization Code grant type (for public Clients?) does not use PKCE to avoid code injection and code replay attacks #FEELS-OK ❖ when using the sample app available at https://github.com/aaronpk/sign-in-with- apple-example, adding openid as a scope leads to an error message and it works just with name and email as scope values; this behavior seems to be inconsistent across Clients: for some it works, or at least does not lead to errors, for others it does not work and ends with an error #FIXED? ❖ The scope value of only the very first request by an application is respected. If an application initially requests only the name scope, and the user allows it, it is then impossible to later also request the email scope. http://bit.ly/diff-between-siwa-and-oidc
  • 11.
  • 12.
  • 13.
  • 14.
    Team X Primary AppA Service A-1
  • 15.
    Team X Primary AppA App A-3 App A-2 App A-1 Service A-1 Service A-2
  • 16.
    Team X Primary AppA App A-3 App A-2 App A-1 Service A-1 Service A-2 Primary App B App B-2 App B-1 Service B-1
  • 17.
  • 18.
    User ID (sub) TeamX Primary App A App A-3 App A-2 App A-1 Service A-1 Service A-2 Primary App B App B-2 App B-1 Service B-1
  • 19.
    Private Email Team X PrimaryApp A App A-3 App A-2 App A-1 Service A-1 Service A-2 Primary App B App B-2 App B-1 Service B-1
  • 22.
    User ID : AppleUser ID : Public Emails : Private Email : 12345 000123.abc2xyz.0012 foo@icloud.com foo@me.com for-team-x@privaterelay.appleid.com Q1. Which address to use in each app’s context? Q2. How to handle email changes after revocation?
  • 23.
    Consent Screen Team X PrimaryApp A App A-3 App A-2 App A-1 Service A-1 Service A-2 Primary App B App B-2 App B-1 Service B-1
  • 24.
    Revocation Screen Team X PrimaryApp A App A-3 App A-2 App A-1 Service A-1 Service A-2 Primary App B App B-2 App B-1 Service B-1
  • 27.
    Careful branding strategyrequired for primary app grouping
  • 28.
  • 29.
    Client ID Team X PrimaryApp A App A-3 App A-2 App A-1 Service A-1 Service A-2 Primary App B App B-2 App B-1 Service B-1
  • 30.
    Private Key Team X PrimaryApp A App A-3 App A-2 App A-1 Service A-1 Service A-2 Primary App B App B-2 App B-1 Service B-1
  • 31.
    CLIENT_ID is ofthe app / service which originally received the authorization code, not of the backend server which accesses the token endpoint, even when refreshing tokens.
  • 32.
    Private Email RelayService Team X Primary App A App A-3 App A-2 App A-1 Service A-1 Service A-2 Primary App B App B-2 App B-1 Service B-1
  • 33.
  • 34.
    For the 11thdomain / address, setup new team !?!? Primary App A sends emails from App A-1 sends emails from App A-2 sends emails from Service A-1 sends emails from no-reply@primary-app-a.example.com no-reply@app-a1.example.com no-reply@app-a2.example.com no-reply@service-a1.example.com :
  • 35.
    【結論】 iOS, iPad OS,Safari での UX は最高だが クセが強いので注意