<!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,
        `https://${idpHost}/.well-known/idp-proxy/idp-test.js?foo=bar`,
        'Expect IdP proxy to be loaded with full well-known URL constructed from provider and protocol');

      assert_equals(env.origin, `https://${idpHost}`,
        'Expect IdP to have its own origin');

      assert_equals(args.options.protocol, 'idp-test.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.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(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');

  /*
    4.4.2.  Steps to create an offer
      1.  If the need for an identity assertion was identified when createOffer was
          invoked, wait for the identity assertion request process to complete.
      2.  If the identity provider was unable to produce an identity assertion, reject p
          with a newly created NotReadableError and abort these steps.
   */
  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(t, 'NotReadableError',
      pc.createOffer());
  }, 'createOffer() should reject with NotReadableError if identitity assertion request fails');

  /*
    4.4.2.  Steps to create an answer
      1.  If the need for an identity assertion was identified when createAnswer was
          invoked, wait for the identity assertion request process to complete.

      2.  If the identity provider was unable to produce an identity assertion, reject p
          with a newly created NotReadableError and abort these steps.
   */
  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(t, 'NotReadableError',
        pc.createAnswer()));

  }, 'createAnswer() should reject with NotReadableError if identitity assertion request fails');

</script>
