diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
commit | 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch) | |
tree | a31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /testing/web-platform/tests/webrtc-identity/RTCPeerConnection-peerIdentity.https.html | |
parent | Initial commit. (diff) | |
download | firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip |
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/webrtc-identity/RTCPeerConnection-peerIdentity.https.html')
-rw-r--r-- | testing/web-platform/tests/webrtc-identity/RTCPeerConnection-peerIdentity.https.html | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webrtc-identity/RTCPeerConnection-peerIdentity.https.html b/testing/web-platform/tests/webrtc-identity/RTCPeerConnection-peerIdentity.https.html new file mode 100644 index 0000000000..268e406211 --- /dev/null +++ b/testing/web-platform/tests/webrtc-identity/RTCPeerConnection-peerIdentity.https.html @@ -0,0 +1,328 @@ +<!doctype html> +<meta charset=utf-8> +<title>RTCPeerConnection.prototype.peerIdentity</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="identity-helper.sub.js"></script> +<script> + 'use strict'; + + // Test is based on the following editor draft: + // https://w3c.github.io/webrtc-identity/identity.html + + // The tests here interacts with the mock identity provider located at + // /.well-known/idp-proxy/mock-idp.js + + // The following helper functions are called from identity-helper.sub.js + // parseAssertionResult + // getIdpDomains + // assert_rtcerror_rejection + // hostString + + /* + 9.6. RTCPeerConnection Interface Extensions + partial interface RTCPeerConnection { + void setIdentityProvider(DOMString provider, + optional RTCIdentityProviderOptions options); + Promise<DOMString> getIdentityAssertion(); + readonly attribute Promise<RTCIdentityAssertion> peerIdentity; + readonly attribute DOMString? idpLoginUrl; + readonly attribute DOMString? idpErrorInfo; + }; + + dictionary RTCIdentityProviderOptions { + DOMString protocol = "default"; + DOMString usernameHint; + DOMString peerIdentity; + }; + + [Constructor(DOMString idp, DOMString name)] + interface RTCIdentityAssertion { + attribute DOMString idp; + attribute DOMString name; + }; + */ + + /* + 4.3.2. setRemoteDescription + If an a=identity attribute is present in the session description, the browser + validates the identity assertion.. + + If the "peerIdentity" configuration is applied to the RTCPeerConnection, this + establishes a target peer identity of the provided value. Alternatively, if the + RTCPeerConnection has previously authenticated the identity of the peer (that + is, there is a current value for peerIdentity ), then this also establishes a + target peer identity. + */ + promise_test(async t => { + const pc1 = new RTCPeerConnection(); + t.add_cleanup(() => pc1.close()); + const pc2 = new RTCPeerConnection(); + + t.add_cleanup(() => pc2.close()); + + const port = window.location.port; + const [idpDomain] = getIdpDomains(); + const idpHost = hostString(idpDomain, port); + + pc1.setIdentityProvider(idpHost, { + protocol: 'mock-idp.js', + usernameHint: `alice@${idpDomain}` + }); + + const peerIdentity = pc2.peerIdentity; + await pc2.setRemoteDescription(await pc1.createOffer()); + const { idp, name } = await peerIdentity; + assert_equals(idp, idpHost, `Expect IdP to be ${idpHost}`); + assert_equals(name, `alice@${idpDomain}`, + `Expect validated identity from mock-idp.js to be same as specified in usernameHint`); + }, 'setRemoteDescription() on offer with a=identity should establish peerIdentity'); + + promise_test(async t => { + const port = window.location.port; + const [idpDomain] = getIdpDomains(); + const idpHost = hostString(idpDomain, port); + + const pc1 = new RTCPeerConnection(); + t.add_cleanup(() => pc1.close()); + pc1.setIdentityProvider(idpHost, { + protocol: 'mock-idp.js', + usernameHint: `doesnt_matter@${idpDomain}` + }); + + const pc2 = new RTCPeerConnection({ + peerIdentity: `bob@${idpDomain}` + }); + + t.add_cleanup(() => pc2.close()); + + pc2.setIdentityProvider(idpHost, { + protocol: 'mock-idp.js', + usernameHint: `alice@${idpDomain}` + }); + + const offer = await pc1.createOffer(); + + await promise_rejects_dom(t, 'OperationError', + pc2.setRemoteDescription(offer)); + await promise_rejects_dom(t, 'OperationError', + pc2.peerIdentity); + }, 'setRemoteDescription() on offer with a=identity that resolve to value different from target peer identity should reject with OperationError'); + + /* + 9.4. Verifying Identity Assertions + 8. The RTCPeerConnection decodes the contents and validates that it contains a + fingerprint value for every a=fingerprint attribute in the session description. + This ensures that the certificate used by the remote peer for communications + is covered by the identity assertion. + + If identity validation fails, the peerIdentity promise is rejected with a newly + created OperationError. + + If identity validation fails and there is a target peer identity for the + RTCPeerConnection, the promise returned by setRemoteDescription MUST be rejected + with the same DOMException. + */ + promise_test(t => { + const port = window.location.port; + const [idpDomain] = getIdpDomains(); + const idpHost = hostString(idpDomain, port); + + const pc1 = new RTCPeerConnection(); + t.add_cleanup(() => pc1.close()); + const pc2 = new RTCPeerConnection({ + peerIdentity: `alice@${idpDomain}` + }); + + t.add_cleanup(() => pc2.close()); + + // Ask mockidp.js to return custom contents in validation result + pc1.setIdentityProvider(idpHost, { + protocol: 'mock-idp.js?validatorAction=return-custom-contents&contents=bogus', + usernameHint: `alice@${idpDomain}` + }); + + const peerIdentityPromise = pc2.peerIdentity; + + return pc1.createOffer() + .then(offer => Promise.all([ + promise_rejects_dom(t, 'IdpError', + pc2.setRemoteDescription(offer)), + promise_rejects_dom(t, 'OperationError', + peerIdentityPromise) + ])); + }, 'setRemoteDescription() with peerIdentity set and with IdP proxy that return validationAssertion with mismatch contents should reject with OperationError'); + + /* + 9.4. Verifying Identity Assertions + 9. The RTCPeerConnection validates that the domain portion of the identity matches + the domain of the IdP as described in [RTCWEB-SECURITY-ARCH]. If this check + fails then the identity validation fails. + */ + promise_test(t => { + const port = window.location.port; + const [idpDomain1, idpDomain2] = getIdpDomains(); + assert_not_equals(idpDomain1, idpDomain2, + 'Sanity check two idpDomains are different'); + + const idpHost1 = hostString(idpDomain1, port); + + const pc1 = new RTCPeerConnection(); + t.add_cleanup(() => pc1.close()); + const pc2 = new RTCPeerConnection({ + peerIdentity: `alice@${idpDomain2}` + }); + + t.add_cleanup(() => pc2.close()); + + // mock-idp.js will return assertion of domain2 identity + // with domain1 in the idp.domain field + pc1.setIdentityProvider(idpHost1, { + protocol: 'mock-idp.js', + usernameHint: `alice@${idpDomain2}` + }); + + return pc1.getIdentityAssertion() + .then(assertionResultStr => { + const { idp, assertion } = parseAssertionResult(assertionResultStr); + + assert_equals(idp.domain, idpHost1, + 'Sanity check domain of assertion is host1'); + + assert_equals(assertion.args.options.usernameHint, `alice@${idpDomain2}`, + 'Sanity check domain1 is going to validate a domain2 identity'); + + return pc1.createOffer(); + }) + .then(offer => Promise.all([ + promise_rejects_dom(t, 'OperationError', + pc2.setRemoteDescription(offer)), + promise_rejects_dom(t, 'OperationError', + pc2.peerIdentity) + ])); + }, 'setRemoteDescription() and peerIdentity should reject with OperationError if IdP return validated identity that is different from its own domain'); + + /* + 9.4 Verifying Identity Assertions + If identity validation fails and there is a target peer identity for the + RTCPeerConnection, the promise returned by setRemoteDescription MUST be rejected + with the same DOMException. + + 9.5 IdP Error Handling + - If an identity provider throws an exception or returns a promise that is ultimately + rejected, then the procedure that depends on the IdP MUST also fail. These types of + errors will cause an IdP failure with an RTCError with errorDetail set to + "idp-execution-failure". + + Any error generated by the IdP MAY provide additional information in the + idpErrorInfo attribute. The information in this string is defined by the + IdP in use. + */ + promise_test(t => { + const port = window.location.port; + const [idpDomain] = getIdpDomains(); + const idpHost = hostString(idpDomain, port); + + const pc1 = new RTCPeerConnection(); + t.add_cleanup(() => pc1.close()); + const pc2 = new RTCPeerConnection({ + peerIdentity: `alice@${idpDomain}` + }); + + t.add_cleanup(() => pc2.close()); + + // Ask mock-idp.js to throw error during validation, + // i.e. during pc2.setRemoteDescription() + pc1.setIdentityProvider(idpHost, { + protocol: 'mock-idp.js?validatorAction=throw-error&errorInfo=bar', + usernameHint: `alice@${idpDomain}` + }); + + return pc1.createOffer() + .then(offer => Promise.all([ + assert_rtcerror_rejection('idp-execution-failure', + pc2.setRemoteDescription(offer)), + assert_rtcerror_rejection('idp-execution-failure', + pc2.peerIdentity) + ])) + .then(() => { + assert_equals(pc2.idpErrorInfo, 'bar', + 'Expect pc2.idpErrorInfo to be set to the err.idpErrorInfo thrown by mock-idp.js'); + }); + }, `When IdP throws error and pc has target peer identity, setRemoteDescription() and peerIdentity rejected with RTCError('idp-execution-error')`); + + /* + 4.3.2. setRemoteDescription + If there is no target peer identity, then setRemoteDescription does not await the + completion of identity validation. + + 9.5. IdP Error Handling + - If an identity provider throws an exception or returns a promise that is + ultimately rejected, then the procedure that depends on the IdP MUST also fail. + These types of errors will cause an IdP failure with an RTCError with errorDetail + set to "idp-execution-failure". + + 9.4. Verifying Identity Assertions + If identity validation fails and there is no a target peer identity, the value of + the peerIdentity MUST be set to a new, unresolved promise instance. This permits + the use of renegotiation (or a subsequent answer, if the session description was + a provisional answer) to resolve or reject the identity. + */ + promise_test(t => { + const pc1 = new RTCPeerConnection(); + t.add_cleanup(() => pc1.close()); + const pc2 = new RTCPeerConnection(); + + t.add_cleanup(() => pc2.close()); + + const port = window.location.port; + const [idpDomain] = getIdpDomains(); + const idpHost = hostString(idpDomain, port); + + // Ask mock-idp.js to throw error during validation, + // i.e. during pc2.setRemoteDescription() + pc1.setIdentityProvider(idpHost, { + protocol: 'mock-idp.js?validatorAction=throw-error', + usernameHint: `alice@${idpDomain}` + }); + + const peerIdentityPromise1 = pc2.peerIdentity; + + return pc1.createOffer() + .then(offer => + // setRemoteDescription should succeed because there is no target peer identity set + pc2.setRemoteDescription(offer)) + .then(() => + assert_rtcerror_rejection('idp-execution-failure', + peerIdentityPromise1, + `Expect first peerIdentity promise to be rejected with RTCError('idp-execution-failure')`)) + .then(() => { + const peerIdentityPromise2 = pc2.peerIdentity; + assert_not_equals(peerIdentityPromise2, peerIdentityPromise1, + 'Expect pc2.peerIdentity to be replaced with a fresh unresolved promise'); + + // regenerate an identity assertion with no test option to throw error + pc1.setIdentityProvider(idpHost, { + protocol: 'idp-test.js', + usernameHint: `alice@${idpDomain}` + }); + + return pc1.createOffer() + .then(offer => pc2.setRemoteDescription(offer)) + .then(peerIdentityPromise2) + .then(identityAssertion => { + const { idp, name } = identityAssertion; + + assert_equals(idp, idpDomain, + `Expect IdP domain to be ${idpDomain}`); + + assert_equals(name, `alice@${idpDomain}`, + `Expect validated identity to be alice@${idpDomain}`); + + assert_equals(pc2.peeridentity, peerIdentityPromise2, + 'Expect pc2.peerIdentity to stay fixed after identity is validated'); + }); + }); + }, 'IdP failure with no target peer identity should have following setRemoteDescription() succeed and replace pc.peerIdentity with a new promise'); + +</script> |