Supporting key requests and key exchange requests
Support the Platform SSO 2.0 protocol for encryption and decryption operations.
Overview
Key requests and key exchange requests require the SSO extension and the server to support the Platform SSO 2.0 protocol. To do so, the server needs to fully support requests, shared device keys, and the modified flows for registration, login, and unlock.
These requests are similar to login requests. They start with a server nonce request, sign the JSON Web Token (JWT) using the device signing key, and require an encrypted response that uses the device encryption key.
Request the key
The system uses a key request to ask the server to provision an EC256 key for the supplied purpose. The server needs to issue a public key in a certificate so that normal keychain operations can find it and use the key. In macOS, encryption operations for login and unlock use the public key. The server can also return a context that’s stored with the key and sent with all key exchange requests. The use of the context isn’t required, but the server can encrypt it to store key material for the key, for example, to rotate encryption values. Storage of the context doesn’t include additional encryption.
After user registration completes, macOS sends the key request. However, macOS can also send the request if it detects a problem or if it needs to rotate the keys.
The following flowchart provides a high-level overview of the key request flow:
[Image]
The request is a JSON Object Signing and Encryption object (JOSE) that’s formatted per RFC 7519 and signed with the DeviceSigningKey and ES256 per RFC 7515.
The following table specifies the header parameters for a key request:
Key | Value | Notes |
|---|---|---|
|
| Required. |
|
| Required. The signing algorithm, only |
| The base-64 encoded SHA256 hash of the ANSI X9.63 formatted public key for the signing key | Required. |
| The base-64 encoded device signing certificate from Savecertificate(_:keytype:) | Optional: The value is base-64 encoded per RFC 7517. |
The following table specifies the body parameters for a key request:
Key | Value | Notes |
|---|---|---|
| 1.0 | Required. |
| key_request | Required. |
| user_unlock | Required. |
| Required. The identity provider (IdP) needs to verify this value to ensure that the assertion was created for them. | |
| Required. Per RFC 7523 Section 3. | |
| The current time | Required. The IdP needs to verify this value. |
| 5 minutes from now | Required. The IdP needs to verify this value. |
| A nonce value | Required. A unique nonce value for this request. |
Servernonceclaimname or | The value returned from the nonce request | Required. The key name is either the Servernonceclaimname or the default value |
| Required. The login user name. If not set, the system uses the local account name. | |
| Required. Per RFC 7523 Section 3. | |
| The current refresh token | Required. |
| Optional. If present, adds the key value pairs to the assertion. |
The following code provides an example of a key request:
{
"kid" : "6cgzt+gMK7vzj4iXhQj4AA4lyJUQ4ZVA/wTnA2kaYcg=",
"x5c" : "MIIBg...Mhw==",
"typ" : "platformsso-key-request+jwt",
"alg" : "ES256"
}.{
"jwe_crypto" : {
"alg" : "ECDH-ES",
"enc" : "A256GCM",
"apv" : "AAAAB...TNGMQ"
},
"exp" : 1685756137,
"request_type" : "key_request",
"nonce" : "EA7D38B1-B9EA-444B-9141-97FFE7D0E3F1",
"version" : "1.0",
"request_nonce" : "AwABA...YQgAA",
"refresh_token" : "abcd1234",
"iss" : "aaff1524-fa35-40c5-94e3-2b233c5f2965",
"key_purpose" : "user_unlock",
"sub" : "foo",
"username" : "foo",
"iat" : 1685755837
}.[Signature]The key network request is an HTTP POST to the keyEndpointURL that’s formatted per RFC 7523 and includes the following parameters:
Key | Value | Notes |
|---|---|---|
|
| Required. The version of the login protocol. |
|
| Required. The assertion type. |
Customrequestjwtparametername or assertion | The base-64 URL encoded signed key request | Required. |
Optional. If present, adds the key value pairs to the key request. |
The following code provides an example of a key network request:
POST /oauth2/token HTTP/1.1
Host: auth.example.com
Accept: application/platformsso-key-response+jwt
Content-Type: application/x-www-form-urlencoded
client-request-id: DCAB01D3-B1FE-4E1C-802F-B3EBDCDF9E67
platform_sso_version2.0&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=ewogI...HGuQgCreate the key response JSON Web Encryption (JWE)
The response is a JWE that’s decrypted according to RFC 7516 Section 5.2 with JWE Compact Serialization.
The JWE key response header contains the following values:
Key | Value | Notes |
|---|---|---|
|
| Required. |
|
| Required. The supported encryption algorithm per RFC 7518 Section 4.6. |
|
| Required: The supported key agreement algorithm per RFC 7518 Section 5.3. |
| The ephemeral public key for the key exchange | Required. Per RFC 7518 Section 4.6.1.1, formatted per RFC 7517. |
| The | Optional. |
| The base-64 URL encoded | Required. Per RFC 7518 Section 4.6.1.2. |
| The base-64 URL encoded | Optional. Per RFC 7518 Section 4.6.1.3, the client uses the value from the request. |
The following code provides an example of a key response JWE header:
{
"enc" : "A256GCM",
"kid" : "8fWc60nKm8I07JE3yG+xf9Kb61wUNrjWnVBV9zIB5mQ=",
"epk" : {
"y" : "SwUUA5FVmbe5K8OZ7ElRH5_qB8Z9klZyiGVvrTMyn8A",
"x" : "o7YsVVlHr5VrMLFX6rqT5MQkNip9_GgYAnm8nQYIrVQ",
"kty" : "EC",
"crv" : "P-256"
},
"apu" : "AAAAB...zMp_A",
"typ" : "platformsso-key-response+jwt",
"alg" : "ECDH-ES"
}The JWE key response body contains the following values:
Key | Value | Notes |
|---|---|---|
| The base-64 URL encoded certificate that contains the provisioned public key | Required. |
| 5 minutes from now | Required. Per RFC 7523 Section 3. |
| The current time | Required. Per RFC 7523 Section 3. |
| The key context for the key | Optional. |
The following code provides an example of a key response JWE body:
{
"certificate" : "MIIBc...2dGpb",
"exp" : 1685756137,
"iat" : 1685755837,
"key_context" : "BHmTq...scA=="
}Request the key exchange
The system uses the key exchange request when using the keys to decrypt data. Typically there are two or three requests occuring at the same time, depending on the number of decryption calls and required checks. These calls need to return quickly because the user is waiting for them to complete.
The following graph provides a high-level overview of the key exchange flow:
[Image]
The key exchange request is a JOSE that’s formatted per RFC 7519 and signed with the DeviceSigningKey and ES256 per RFC 7515.
The following table specifies the header parameters for a key exchange request:
Key | Value | Notes |
|---|---|---|
|
| Required. |
|
| Required. The signing algorithm. The system only supports |
| The base-64 encoded SHA256 hash of the ANSI X9.63 formatted public key for the signing key | Required. |
| The base-64 encoded device signing certificate from Savecertificate(_:keytype:) | Optional. The value is base-64 encoded per RFC 7517. |
| Optional. If present, adds the key value pairs to the assertion. |
The following table specifies the body parameters for a key exchange request:
Key | Value | Notes |
|---|---|---|
|
| Required. |
|
| Required. |
|
| Required. |
| Required. The identity provider (IdP) needs to verify the value to ensure that the assertion was created for them. | |
| Required. Per RFC 7523 Section 3. | |
| The current time | Required. The identity provider (IdP) needs to verify the value. |
| 5 minutes from now | Required. The identity provider (IdP) needs to verify the value. |
| A nonce value | Required. A unique nonce value for this request. |
Servernonceclaimname or | The value returned from the nonce request | Required. The key name is either the Servernonceclaimname or the default value |
| Required. If not set, the system uses the local account name. | |
| Required. Per RFC 7523 Section 3. If not set, the system uses the local account name. | |
| The current refresh token | Required. |
| The base-64 encoded other party public key | Required. |
| The context for the key | Optional. |
| Optional. If present, adds the key value pairs to the assertion. |
The following code provides an example of a key exchange request:
{
"kid" : "NKuTL/WHlroXidcyrxgA2Eqpt/cXjh5s22NAkJl7Acs=",
"x5c" : "MIIBg...YtQ==",
"typ" : "platformsso-key-request+jwt",
"alg" : "ES256"
}.{
"jwe_crypto" : {
"alg" : "ECDH-ES",
"enc" : "A256GCM",
"apv" : "AAAAB...UEwRQ"
},
"exp" : 1685759411,
"request_type" : "key_exchange",
"nonce" : "7F48971A-E559-4668-A680-97D1BCF7AA0E",
"version" : "1.0",
"request_nonce" : "AwABA...HYQgAA",
"other_publickey" : "BCdD2...RJIv0=",
"refresh_token" : "abcd1234",
"key_context" : "BHp+H...Axw==",
"iss" : "aaff1524-fa35-40c5-94e3-2b233c5f2965",
"key_purpose" : "user_unlock",
"sub" : "foo",
"username" : "foo",
"iat" : 1685759111
}.[Signature]The key exchange network request is an HTTP POST to the keyEndpointURL that’s formatted per RFC 7523 and includes the following parameters:
Key | Value | Notes |
|---|---|---|
|
| Required. The version of the login protocol. |
|
| Required. The assertion type. |
Customrequestjwtparametername or | The base-64 URL encoded signed key exchange request | Required. |
Optional. If present, adds the key value pairs to the key exchange request. |
The following code sample provides an example of a key exchange network request:
POST /oauth2/token HTTP/1.1
Host: auth.example.com
Accept: application/platformsso-key-response+jwt
Content-Type: application/x-www-form-urlencoded
client-request-id: DCAB01D3-B1FE-4E1C-802F-B3EBDCDF9E67
platform_sso_version=2.0&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=ewogIC...JmVhgReceive the key exchange response JWE
The response is a JWE that’s decrypted according to RFC 7516 Section 5.2 with JWE Compact Serialization.
The JWE key exchange response header contains the following values:
Key | Value | Notes |
|---|---|---|
|
| Required. |
|
| Required: The supported encryption algorithm per RFC 7518 Section 4.6. |
|
| Required. The supported key agreement algorithm per RFC 7518 Section 5.3. |
| The ephemeral public key for the key exchange | Required: Per RFC 7518 Section 4.6.1.1, formatted per RFC 7517. |
| The | Optional. |
| The base-64 URL encoded | Required. Per RFC 7518 Section 4.6.1.2. |
| The base-64 URL encoded | Optional. Per RFC 7518 Section 4.6.1.3, the client uses the value from the request. |
The following code provides an example of a key exchange response JWE header:
{
"enc" : "A256GCM",
"kid" : "cNYXaKrqHO+mBB0MHxuaEUZ2edf0T/GgMNB/tlHGews=",
"epk" : {
"y" : "WFUG_Llu2uD70NfbIFOkP5LaNsZlJ1JGIme2DPdbijU",
"x" : "kXzpm4kt-sbm5QlOJPNZAHhaW8rQ5QE_E2HLFcz2uNs",
"kty" : "EC",
"crv" : "P-256"
},
"apu" : "AAAAB...z3W4o1",
"typ" : "platformsso-key-response+jwt",
"alg" : "ECDH-ES"
}The IdP creates a successful key response. The JWE key exchange response body contains the following values:
Key | Value | Notes |
|---|---|---|
| 5 minutes from now | Required. Per RFC 7523 Section 3. |
| The current time | Required. Per RFC 7523 Section 3. |
| The result of Diffie-Hellman standard key exchange with the | Required. |
| The updated key context for the key | Optional. |
The following code provides an example of a key exchange response JWE body:
{
"exp" : 1685756137,
"iat" : 1685755837,
"key" : "DpWD3c4SPmfYteESkRYk+pKVHHuryb1EtnuzhF9OjTc=",
"key_context" : "BHp+H...Axw=="
}