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