<!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.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.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();
    const pc2 = new RTCPeerConnection();

    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();
    const pc2 = new RTCPeerConnection({
      peerIdentity: `bob@${idpDomain}`
    });

    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();
    const pc2 = new RTCPeerConnection({
      peerIdentity: `alice@${idpDomain}`
    });

    // 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();
    const pc2 = new RTCPeerConnection({
      peerIdentity: `alice@${idpDomain2}`
    });

    // 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();
    const pc2 = new RTCPeerConnection({
      peerIdentity: `alice@${idpDomain}`
    });

    // 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();
    const pc2 = new RTCPeerConnection();

    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>
