<!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>
