tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

mock-idp.js (5094B)


      1 'use strict';
      2 
      3 // Code is based on the following editor draft:
      4 //   https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
      5 
      6 /*
      7  mock-idp.js is a naive IdP that provides absolutely no
      8  security for authentication. It can generate identity
      9  assertion for whatever identity that is requested.
     10 
     11  mock-idp.js validates identity assertion by simply decoding
     12  the JSON and return whatever that is inside, with no integrity
     13  protection and thus can be spoofed by anyone.
     14 
     15  While being not practical at all, mock-idp.js allows us
     16  to test various aspects of the identity API and allow tests
     17  to manipulate the IdP at will.
     18 */
     19 
     20 // We pass around test options as query string to instruct
     21 // the test IdP proxy script on what actions to perform.
     22 // This hack is based on the fact that query string is allowed
     23 // when specifying the IdP protocol.
     24 function parseQueryString(urlStr) {
     25  const url = new URL(urlStr);
     26  const result = {};
     27  for(const [key, value] of url.searchParams) {
     28    result[key] = value;
     29  }
     30  return result;
     31 }
     32 
     33 /*
     34  9.2.1.  Interface Exposed by Identity Providers
     35    callback GenerateAssertionCallback =
     36      Promise<RTCIdentityAssertionResult> (
     37        DOMString contents,
     38        DOMString origin,
     39        RTCIdentityProviderOptions options);
     40 
     41    dictionary RTCIdentityProviderOptions {
     42      DOMString protocol = "default";
     43      DOMString usernameHint;
     44      DOMString peerIdentity;
     45    };
     46 
     47    dictionary RTCIdentityAssertionResult {
     48      required RTCIdentityProviderDetails idp;
     49      required DOMString                  assertion;
     50    };
     51 
     52    dictionary RTCIdentityProviderDetails {
     53      required DOMString domain;
     54               DOMString protocol = "default";
     55    };
     56 */
     57 
     58 const query = parseQueryString(location);
     59 
     60 // Generate a naive identity assertion. The result assertion
     61 // is a JSON string that report the various parameters
     62 // received by this function.
     63 //   watermark - a special mark to make sure the result is returned
     64 //               from this function
     65 //   args - the function arguments received
     66 //   env - some global variable values when this function is called
     67 //   query - the parsed query string of the script URL
     68 function generateAssertion(contents, origin, options) {
     69  const args = {
     70    contents, origin, options
     71  };
     72 
     73  const env = {
     74    origin,
     75    location
     76  };
     77 
     78  const assertion = {
     79    watermark: 'mock-idp.js.watermark',
     80    args,
     81    env,
     82    query
     83  };
     84 
     85  const assertionStr = JSON.stringify(assertion);
     86 
     87  const { generatorAction } = query;
     88 
     89  if(generatorAction === 'throw-error') {
     90    const err = new Error('Mock Internal IdP Error');
     91    err.idpErrorInfo = query.errorInfo;
     92    throw err;
     93 
     94  } else if(generatorAction === 'require-login') {
     95    const err = new RTCError('idp-need-login');
     96    err.idpLoginUrl = `${origin}/login`;
     97    err.idpErrorInfo = 'login required';
     98    throw err;
     99 
    100  } else if(generatorAction === 'return-custom-idp') {
    101    const { domain, protocol } = query;
    102 
    103    return {
    104      idp: {
    105        domain,
    106        protocol
    107      },
    108      assertion: assertionStr
    109    };
    110 
    111  } else if(generatorAction === 'return-invalid-result') {
    112    return 'invalid-result';
    113 
    114  } else {
    115    return {
    116      idp: {
    117        domain: location.host,
    118        protocol: 'mock-idp.js'
    119      },
    120      assertion: assertionStr
    121    };
    122  }
    123 }
    124 
    125 /*
    126  9.2.1.  Interface Exposed by Identity Providers
    127    callback ValidateAssertionCallback =
    128      Promise<RTCIdentityValidationResult> (
    129        DOMString assertion,
    130        DOMString origin);
    131 
    132    dictionary RTCIdentityValidationResult {
    133      required DOMString identity;
    134      required DOMString contents;
    135    };
    136 */
    137 function validateAssertion(assertionStr, origin) {
    138  const assertion = JSON.parse(assertionStr);
    139 
    140  const { args, query } = assertion;
    141  const { contents, options } = args;
    142 
    143  const identity = options.usernameHint;
    144 
    145  const {
    146    validatorAction
    147  } = query;
    148 
    149  if(validatorAction === 'throw-error') {
    150    const err = new Error('Mock Internal IdP Error');
    151    err.idpErrorInfo = query.errorInfo;
    152    throw err;
    153 
    154  } else if(validatorAction === 'return-custom-contents') {
    155    const { contents } = query;
    156    return {
    157      identity,
    158      contents
    159    };
    160 
    161  } else {
    162    return {
    163      identity, contents
    164    };
    165  }
    166 }
    167 
    168 /*
    169  9.2.  Registering an IdP Proxy
    170    [Global,
    171     Exposed=RTCIdentityProviderGlobalScope]
    172    interface RTCIdentityProviderGlobalScope : WorkerGlobalScope {
    173      readonly attribute RTCIdentityProviderRegistrar rtcIdentityProvider;
    174    };
    175 
    176    [Exposed=RTCIdentityProviderGlobalScope]
    177    interface RTCIdentityProviderRegistrar {
    178      void register(RTCIdentityProvider idp);
    179    };
    180 
    181    dictionary RTCIdentityProvider {
    182      required GenerateAssertionCallback generateAssertion;
    183      required ValidateAssertionCallback validateAssertion;
    184    };
    185 */
    186 
    187 // if rtcIdentityProvider is defined, and the caller do not ask
    188 // to not register through query string, register our assertion callbacks.
    189 if(rtcIdentityProvider && query.action !== 'do-not-register') {
    190  rtcIdentityProvider.register({
    191    generateAssertion,
    192    validateAssertion
    193  });
    194 }