summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webrtc-identity/RTCPeerConnection-getIdentityAssertion.sub.https.html
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/webrtc-identity/RTCPeerConnection-getIdentityAssertion.sub.https.html
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/webrtc-identity/RTCPeerConnection-getIdentityAssertion.sub.https.html')
-rw-r--r--testing/web-platform/tests/webrtc-identity/RTCPeerConnection-getIdentityAssertion.sub.https.html397
1 files changed, 397 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webrtc-identity/RTCPeerConnection-getIdentityAssertion.sub.https.html b/testing/web-platform/tests/webrtc-identity/RTCPeerConnection-getIdentityAssertion.sub.https.html
new file mode 100644
index 0000000000..57d7b16165
--- /dev/null
+++ b/testing/web-platform/tests/webrtc-identity/RTCPeerConnection-getIdentityAssertion.sub.https.html
@@ -0,0 +1,397 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>RTCPeerConnection.prototype.getIdentityAssertion</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-pc/archives/20170605/webrtc.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;
+ };
+ */
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ const port = window.location.port;
+
+ const [idpDomain] = getIdpDomains();
+ const idpHost = hostString(idpDomain, port);
+
+ pc.setIdentityProvider(idpHost, {
+ protocol: 'mock-idp.js?foo=bar',
+ usernameHint: `alice@${idpDomain}`,
+ peerIdentity: 'bob@example.org'
+ });
+
+ return pc.getIdentityAssertion()
+ .then(assertionResultStr => {
+ const { idp, assertion } = parseAssertionResult(assertionResultStr);
+
+ assert_equals(idp.domain, idpHost,
+ 'Expect mock-idp.js to construct domain from its location.host');
+
+ assert_equals(idp.protocol, 'mock-idp.js',
+ 'Expect mock-idp.js to return protocol of itself with no query string');
+
+ const {
+ watermark,
+ args,
+ env,
+ query,
+ } = assertion;
+
+ assert_equals(watermark, 'mock-idp.js.watermark',
+ 'Expect assertion result to contain watermark left by mock-idp.js');
+
+ assert_equals(args.origin, window.origin,
+ 'Expect args.origin argument to be the origin of this window');
+
+ assert_equals(env.location.href,
+ `https://${idpHost}/.well-known/idp-proxy/mock-idp.js?foo=bar`,
+ 'Expect IdP proxy to be loaded with full well-known URL constructed from provider and protocol');
+
+ assert_equals(env.location.origin, `https://${idpHost}`,
+ 'Expect IdP to have its own origin');
+
+ assert_equals(args.options.protocol, 'mock-idp.js?foo=bar',
+ 'Expect options.protocol to be the same value as being passed from here');
+
+ assert_equals(args.options.usernameHint, `alice@${idpDomain}`,
+ 'Expect options.usernameHint to be the same value as being passed from here');
+
+ assert_equals(args.options.peerIdentity, 'bob@example.org',
+ 'Expect options.peerIdentity to be the same value as being passed from here');
+
+ assert_equals(query.foo, 'bar',
+ 'Expect query string to be parsed by mock-idp.js and returned back');
+ });
+ }, 'getIdentityAssertion() should load IdP proxy and return assertion generated');
+
+ // When generating assertion, the RTCPeerConnection doesn't care if the returned assertion
+ // represents identity of different domain
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ const port = window.location.port;
+
+ const [idpDomain1, idpDomain2] = getIdpDomains();
+ assert_not_equals(idpDomain1, idpDomain2,
+ 'Sanity check two idpDomains are different');
+
+ // Ask mock-idp.js to return a custom domain idpDomain2 and custom protocol foo
+ pc.setIdentityProvider(hostString(idpDomain1, port), {
+ protocol: `mock-idp.js?generatorAction=return-custom-idp&domain=${idpDomain2}&protocol=foo`,
+ usernameHint: `alice@${idpDomain2}`,
+ });
+
+ return pc.getIdentityAssertion()
+ .then(assertionResultStr => {
+ const { idp, assertion } = parseAssertionResult(assertionResultStr);
+ assert_equals(idp.domain, idpDomain2);
+ assert_equals(idp.protocol, 'foo');
+ assert_equals(assertion.args.options.usernameHint, `alice@${idpDomain2}`);
+ });
+ }, 'getIdentityAssertion() should succeed if mock-idp.js return different domain and protocol in assertion');
+
+ /*
+ 9.3. Requesting Identity Assertions
+ 4. If the IdP proxy produces an error or returns a promise that does not resolve to
+ a valid RTCIdentityValidationResult (see 9.5 IdP Error Handling), then identity
+ validation fails.
+
+ 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.6. RTCPeerConnection Interface Extensions
+ idpErrorInfo
+ An attribute that the IdP can use to pass additional information back to the
+ applications about the error. The format of this string is defined by the IdP and
+ may be JSON.
+ */
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ assert_equals(pc.idpErrorInfo, null,
+ 'Expect initial pc.idpErrorInfo to be null');
+
+ const port = window.location.port;
+ const [idpDomain] = getIdpDomains();
+
+ // Ask mock-idp.js to throw an error with err.errorInfo set to bar
+ pc.setIdentityProvider(hostString(idpDomain, port), {
+ protocol: `mock-idp.js?generatorAction=throw-error&errorInfo=bar`,
+ usernameHint: `alice@${idpDomain}`,
+ });
+
+ return assert_rtcerror_rejection('idp-execution-failure',
+ pc.getIdentityAssertion())
+ .then(() => {
+ assert_equals(pc.idpErrorInfo, 'bar',
+ 'Expect pc.idpErrorInfo to be set to the err.idpErrorInfo thrown by mock-idp.js');
+ });
+ }, `getIdentityAssertion() should reject with RTCError('idp-execution-failure') if mock-idp.js throws error`);
+
+ /*
+ 9.5. IdP Error Handling
+ - If the script loaded from the identity provider is not valid JavaScript or does
+ not implement the correct interfaces, it causes an IdP failure with an RTCError
+ with errorDetail set to "idp-bad-script-failure".
+ */
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ const port = window.location.port;
+ const [idpDomain] = getIdpDomains();
+
+ // Ask mock-idp.js to not register its callback to the
+ // RTCIdentityProviderRegistrar
+ pc.setIdentityProvider(hostString(idpDomain, port), {
+ protocol: `mock-idp.js?action=do-not-register`,
+ usernameHint: `alice@${idpDomain}`,
+ });
+
+ return assert_rtcerror_rejection('idp-bad-script-failure',
+ pc.getIdentityAssertion());
+
+ }, `getIdentityAssertion() should reject with RTCError('idp-bad-script-failure') if IdP proxy script do not register its callback`);
+
+ /*
+ 9.3. Requesting Identity Assertions
+ 4. If the IdP proxy produces an error or returns a promise that does not resolve
+ to a valid RTCIdentityAssertionResult (see 9.5 IdP Error Handling), then assertion
+ generation fails.
+ */
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ const port = window.location.port;
+ const [idpDomain] = getIdpDomains();
+
+ // Ask mock-idp.js to return an invalid result that is not proper
+ // RTCIdentityAssertionResult
+ pc.setIdentityProvider(hostString(idpDomain, port), {
+ protocol: `mock-idp.js?generatorAction=return-invalid-result`,
+ usernameHint: `alice@${idpDomain}`,
+ });
+
+ return promise_rejects_dom(t, 'OperationError',
+ pc.getIdentityAssertion());
+ }, `getIdentityAssertion() should reject with OperationError if mock-idp.js return invalid result`);
+
+ /*
+ 9.5. IdP Error Handling
+ - A RTCPeerConnection might be configured with an identity provider, but loading of
+ the IdP URI fails. Any procedure that attempts to invoke such an identity provider
+ and cannot load the URI fails with an RTCError with errorDetail set to
+ "idp-load-failure" and the httpRequestStatusCode attribute of the error set to the
+ HTTP status code of the response.
+ */
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ pc.setIdentityProvider('nonexistent.{{domains[]}}', {
+ protocol: `non-existent`,
+ usernameHint: `alice@example.org`,
+ });
+
+ return assert_rtcerror_rejection('idp-load-failure',
+ pc.getIdentityAssertion());
+ }, `getIdentityAssertion() should reject with RTCError('idp-load-failure') if IdP cannot be loaded`);
+
+ /*
+ 9.3.1. User Login Procedure
+ Rejecting the promise returned by generateAssertion will cause the error to
+ propagate to the application. Login errors are indicated by rejecting the
+ promise with an RTCError with errorDetail set to "idp-need-login".
+
+ The URL to login at will be passed to the application in the idpLoginUrl
+ attribute of the RTCPeerConnection.
+
+ 9.5. IdP Error Handling
+ - If the identity provider requires the user to login, the operation will fail
+ RTCError with errorDetail set to "idp-need-login" and the idpLoginUrl attribute
+ of the error set to the URL that can be used to login.
+ */
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+
+ assert_equals(pc.idpLoginUrl, null,
+ 'Expect initial pc.idpLoginUrl to be null');
+
+ const port = window.location.port;
+ const [idpDomain] = getIdpDomains();
+ const idpHost = hostString(idpDomain, port);
+
+ pc.setIdentityProvider(idpHost, {
+ protocol: `mock-idp.js?generatorAction=require-login`,
+ usernameHint: `alice@${idpDomain}`,
+ });
+
+ return assert_rtcerror_rejection('idp-need-login',
+ pc.getIdentityAssertion())
+ .then(err => {
+ assert_equals(err.idpLoginUrl, `https://${idpHost}/login`,
+ 'Expect err.idpLoginUrl to be set to url set by mock-idp.js');
+
+ assert_equals(pc.idpLoginUrl, `https://${idpHost}/login`,
+ 'Expect pc.idpLoginUrl to be set to url set by mock-idp.js');
+
+ assert_equals(pc.idpErrorInfo, 'login required',
+ 'Expect pc.idpErrorInfo to be set to info set by mock-idp.js');
+ });
+ }, `getIdentityAssertion() should reject with RTCError('idp-need-login') when mock-idp.js requires login`);
+
+ /*
+ RTCIdentityProviderOptions Members
+ peerIdentity
+ The identity of the peer. For identity providers that bind their assertions to a
+ particular pair of communication peers, this allows them to generate an assertion
+ that includes both local and remote identities. If this value is omitted, but a
+ value is provided for the peerIdentity member of RTCConfiguration, the value from
+ RTCConfiguration is used.
+ */
+ promise_test(t => {
+ const pc = new RTCPeerConnection({
+ peerIdentity: 'bob@example.net'
+ });
+
+ const port = window.location.port;
+ const [idpDomain] = getIdpDomains();
+ const idpHost = hostString(idpDomain, port);
+
+ pc.setIdentityProvider(idpHost, {
+ protocol: 'mock-idp.js'
+ });
+
+ return pc.getIdentityAssertion()
+ .then(assertionResultStr => {
+ const { assertion } = parseAssertionResult(assertionResultStr);
+ assert_equals(assertion.args.options.peerIdentity, 'bob@example.net');
+ });
+ }, 'setIdentityProvider() with no peerIdentity provided should use peerIdentity value from getConfiguration()');
+
+ /*
+ 9.6. setIdentityProvider
+ 3. If any identity provider value has changed, discard any stored identity assertion.
+ */
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ const port = window.location.port;
+ const [idpDomain] = getIdpDomains();
+ const idpHost = hostString(idpDomain, port);
+
+ pc.setIdentityProvider(idpHost, {
+ protocol: 'mock-idp.js?mark=first'
+ });
+
+ return pc.getIdentityAssertion()
+ .then(assertionResultStr => {
+ const { assertion } = parseAssertionResult(assertionResultStr);
+ assert_equals(assertion.query.mark, 'first');
+
+ pc.setIdentityProvider(idpHost, {
+ protocol: 'mock-idp.js?mark=second'
+ });
+
+ return pc.getIdentityAssertion();
+ })
+ .then(assertionResultStr => {
+ const { assertion } = parseAssertionResult(assertionResultStr);
+ assert_equals(assertion.query.mark, 'second',
+ 'Expect generated assertion is from second IdP config');
+ });
+ }, `Calling setIdentityProvider() multiple times should reset identity assertions`);
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ const port = window.location.port;
+ const [idpDomain] = getIdpDomains();
+
+ pc.setIdentityProvider(hostString(idpDomain, port), {
+ protocol: 'mock-idp.js',
+ usernameHint: `alice@${idpDomain}`
+ });
+
+ return pc.getIdentityAssertion()
+ .then(assertionResultStr =>
+ pc.createOffer()
+ .then(offer => {
+ assert_true(offer.sdp.includes(`\r\na=identity:${assertionResultStr}`,
+ 'Expect SDP to have a=identity line containing assertion string'));
+ }));
+ }, 'createOffer() should return SDP containing identity assertion string if identity provider is set');
+
+ /*
+ 6. Requesting Identity Assertions
+
+ The identity assertion request process is triggered by a call to
+ createOffer, createAnswer, or getIdentityAssertion. When these calls are
+ invoked and an identity provider has been set, the following steps are
+ executed:
+
+ ...
+
+ If assertion generation fails, then the promise for the corresponding
+ function call is rejected with a newly created OperationError. */
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ const port = window.location.port;
+ const [idpDomain] = getIdpDomains();
+
+ pc.setIdentityProvider(hostString(idpDomain, port), {
+ protocol: 'mock-idp.js?generatorAction=throw-error',
+ usernameHint: `alice@${idpDomain}`
+ });
+
+ return promise_rejects_dom(t, 'OperationError',
+ pc.createOffer());
+ }, 'createOffer() should reject with OperationError if identity assertion request fails');
+
+ promise_test(t => {
+ const pc = new RTCPeerConnection();
+ const port = window.location.port;
+ const [idpDomain] = getIdpDomains();
+
+ pc.setIdentityProvider(hostString(idpDomain, port), {
+ protocol: 'mock-idp.js?generatorAction=throw-error',
+ usernameHint: `alice@${idpDomain}`
+ });
+
+ return new RTCPeerConnection()
+ .createOffer()
+ .then(offer => pc.setRemoteDescription(offer))
+ .then(() =>
+ promise_rejects_dom(t, 'OperationError',
+ pc.createAnswer()));
+
+ }, 'createAnswer() should reject with OperationError if identity assertion request fails');
+
+</script>