Platform SSO (dynamicOpenID): redirect_uri changes case between the Authentication request and the Login Request subject_token, breaking RFC 6749 Section ( 4.1.3 ). Bug or expected?

Hi Apple Community,

I have been Developing Platform SSO With OpenID as Authentication Method, This is Great as it will allow clients to Configure their own Identity Provider Authentication Policy Enforced at Login Screen

I have used Platform SSO with dynamicOpenID method with this , macOS sends redirect_uri=com.apple.PlatformSSO://callback (Camel Case "com.apple.PlatformSSO") to the Identity Provider during OIDC Authentication to Authorization URL .
After During Platform SSO Login Request The subject_token in the Login Request then contains com.apple.platformsso://callback (lowercase).

RFC 6749 Section 4.1.3 requires these values to be identical, so my Identity Provider rejects the token request. Is this expected, or a macOS bug?

Environment

  • macOS version: Golden Gate ( 27.0.1 )
  • Platform SSO Authentication method: OpenID ( dynamicOpenID )
  • Document Followed : https://developer.apple.com/documentation/authenticationservices/implementing-web-based-authentication

Configuration

  • federationType = .dynamicOpenID
  • fallbackFederationType = .dynamicOpenID
  • authorizationURLKeypath = "authorizationURL"
  • Reference

Steps to reproduce

  1. macOS makes the pre-authentication request, and my server responds:
HTTP/1.1 200 OK
Content-Type: application/json

{
  "account_type": "Federated",
  "federation_protocol": "OIDC",
  "authorizationURL": "https://idp.example.com/authorize?state=random"
}
  1. Platform SSO opens a WebView, loads the authorization URL, and appends redirect_uri with a capital "PSSO":
GET https://idp.example.com/authorize?state=random&redirect_uri=com.apple.PlatformSSO://callback
  1. Authentication completes. Platform SSO then sends the Login Request. The decoded JWT claims contain a subject_token with a lowercase "platformsso":
{
  "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
  "subject_token": "com.apple.platformsso://callback?code=gAJZwNpLDPardp8NKwvyyJLYefxLqMQH&state=ABCD1234",
  "subject_token_type": "urn:apple:platformsso:authorization-code-response",
  "scope": "openid offline_access urn:apple:platformsso urn:apple:platformsso:auth:auth-prompt",
  "aud": "https://auth.example.com/auth/token",
  "...": "other claims omitted for brevity"
}

The mismatch

  • Authorization request (WebView): com.apple.PlatformSSO://callback
  • Login Request subject_token: com.apple.platformsso://callback

Why it matters
RFC 6749 Section 4.1.3 says redirect_uri is REQUIRED in the token request if it was included in the authorization request, and the values MUST be identical. Because the two differ, a spec-compliant IdP rejects the code exchange.

Expected behavior
Both stages use the same redirect_uri string.

Actual behavior
The scheme differs in case, and the IdP rejects the request.

Questions

  1. Is this intentional? If so, how should an IdP handle it without breaking RFC compliance?
  2. Is there a configuration option to control or normalize the redirect_uri that Platform SSO sends?

Can someone from the Community help with how to overcome this if faced Thanks!!!

Answered by Security Engineer in 914970022

Hello,

The RFC you referenced, RFC 6749 §4.1.3, is about the redirect_uri parameter. A token request has to send the same value as the authorization request. It doesn't cover how the scheme is spelled on the URL the browser is redirected to.

That scheme is case-insensitive. RFC 6749 bases the redirection endpoint on RFC 3986, and RFC 3986 §3.1 says schemes are case-insensitive, with lowercase as the canonical form. So a redirect to com.apple.PlatformSSO://callback arriving as com.apple.platformsso://callback is expected and valid.

PSSO is consistent with §4.1.3 because it doesn't do the code exchange itself. The flow is:

  1. PSSO sends the authorization request with redirect_uri exactly as configured.
  2. When the IdP redirects back, PSSO takes the callback URL as it was received, with the authorization code in it, and passes it to the IdP unchanged in the login request.
  3. The IdP extracts the code and makes the token request to its own token endpoint.

Because the IdP builds that token request, the IdP also supplies its redirect_uri parameter. For §4.1.3, that value has to be identical to the one in the authorization request. The IdP can take it from its registered redirect URI or from the original authorization request, both of which have the configured spelling. The callback URL PSSO hands back carries the code to the IdP. It isn't meant to be copied into the token request as the redirect_uri.

If an IdP rejects the lowercase callback, it's either comparing the scheme case-sensitively or using the callback URL as the redirect_uri in its token request. Either way the fix belongs in that IdP.

Accepted Answer

Hello,

The RFC you referenced, RFC 6749 §4.1.3, is about the redirect_uri parameter. A token request has to send the same value as the authorization request. It doesn't cover how the scheme is spelled on the URL the browser is redirected to.

That scheme is case-insensitive. RFC 6749 bases the redirection endpoint on RFC 3986, and RFC 3986 §3.1 says schemes are case-insensitive, with lowercase as the canonical form. So a redirect to com.apple.PlatformSSO://callback arriving as com.apple.platformsso://callback is expected and valid.

PSSO is consistent with §4.1.3 because it doesn't do the code exchange itself. The flow is:

  1. PSSO sends the authorization request with redirect_uri exactly as configured.
  2. When the IdP redirects back, PSSO takes the callback URL as it was received, with the authorization code in it, and passes it to the IdP unchanged in the login request.
  3. The IdP extracts the code and makes the token request to its own token endpoint.

Because the IdP builds that token request, the IdP also supplies its redirect_uri parameter. For §4.1.3, that value has to be identical to the one in the authorization request. The IdP can take it from its registered redirect URI or from the original authorization request, both of which have the configured spelling. The callback URL PSSO hands back carries the code to the IdP. It isn't meant to be copied into the token request as the redirect_uri.

If an IdP rejects the lowercase callback, it's either comparing the scheme case-sensitively or using the callback URL as the redirect_uri in its token request. Either way the fix belongs in that IdP.