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

      [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(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}`
    });

    return pc1.createOffer()
    .then(offer => pc2.setRemoteDescription(offer))
    .then(() => pc2.peerIdentity)
    .then(identityAssertion => {
      const { idp, name } = identityAssertion;
      assert_equals(idp, idpDomain, `Expect IdP domain to be ${idpDomain}`);
      assert_equals(identityAssertion, `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');

  /*
    4.3.2. setRemoteDescription
      The target peer identity cannot be changed once set. Once set, if a different
      value is provided, the user agent MUST reject the returned promise with a newly
      created InvalidModificationError and abort this operation. The RTCPeerConnection
      MUST be closed if the validated peer identity does not match the target peer
      identity.
   */
  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: `bob@${idpDomain}`
    });

    t.add_cleanup(() => pc2.close());

    pc1.setIdentityProvider(idpHost, {
      protocol: 'mock-idp.js',
      usernameHint: `alice@${idpDomain}`
    });

    return pc1.createOffer()
    .then(offer =>
      promise_rejects(t, 'InvalidModificationError',
        pc2.setRemoteDescription(offer)))
    .then(() => {
      assert_true(pc2.signalingState, 'closed',
        'Expect peer connection to be closed after mismatch peer identity');
    });
  }, 'setRemoteDescription() on offer with a=identity that resolve to value different from target peer identity should reject with InvalidModificationError');

  /*
    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(t, 'OperationError',
        pc2.setRemoteDescription(offer)),
      promise_rejects(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, idpDomain1,
        'Sanity check domain of assertion is domain1');

      assert_equals(assertion.options.usernameHint, `alice@${idpDomain2}`,
        'Sanity check domain1 is going to validate a domain2 identity');

      return pc1.createOffer();
    })
    .then(offer => Promise.all([
      promise_rejects(t, 'OperationError',
        pc2.setRemoteDescription(offer)),
      promise_rejects(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>
