diff options
Diffstat (limited to 'testing/web-platform/tests/.well-known/idp-proxy')
3 files changed, 208 insertions, 0 deletions
diff --git a/testing/web-platform/tests/.well-known/idp-proxy/META.yml b/testing/web-platform/tests/.well-known/idp-proxy/META.yml new file mode 100644 index 0000000000..9901aed94e --- /dev/null +++ b/testing/web-platform/tests/.well-known/idp-proxy/META.yml @@ -0,0 +1,2 @@ +suggested_reviewers: + - nils-ohlmeier diff --git a/testing/web-platform/tests/.well-known/idp-proxy/README.md b/testing/web-platform/tests/.well-known/idp-proxy/README.md new file mode 100644 index 0000000000..dc5795cf81 --- /dev/null +++ b/testing/web-platform/tests/.well-known/idp-proxy/README.md @@ -0,0 +1,12 @@ +Identity Provider Proxy +======================= + +This directory is used for hosting the mock identity provider proxy script +for testing the identity provider feature in WebRTC. +[[ietf-rtcweb-security-arch](https://tools.ietf.org/html/draft-ietf-rtcweb-security-arch-12#section-5.6.5)] +[[webrtc-pc](https://w3c.github.io/webrtc-pc/#sec.identity-proxy)] + +The script for identity provider proxy must be hosted at /.well-known/idp-proxy +instead of the usual [/webrtc](../../webrtc) directory as it follows the +well-known URI standard that derives the script URI from a given domain name. +[[RFC5785](https://tools.ietf.org/html/rfc5785)] diff --git a/testing/web-platform/tests/.well-known/idp-proxy/mock-idp.js b/testing/web-platform/tests/.well-known/idp-proxy/mock-idp.js new file mode 100644 index 0000000000..e73ca22bb2 --- /dev/null +++ b/testing/web-platform/tests/.well-known/idp-proxy/mock-idp.js @@ -0,0 +1,194 @@ +'use strict'; + +// Code is based on the following editor draft: +// https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html + +/* + mock-idp.js is a naive IdP that provides absolutely no + security for authentication. It can generate identity + assertion for whatever identity that is requested. + + mock-idp.js validates identity assertion by simply decoding + the JSON and return whatever that is inside, with no integrity + protection and thus can be spoofed by anyone. + + While being not practical at all, mock-idp.js allows us + to test various aspects of the identity API and allow tests + to manipulate the IdP at will. + */ + +// We pass around test options as query string to instruct +// the test IdP proxy script on what actions to perform. +// This hack is based on the fact that query string is allowed +// when specifying the IdP protocol. +function parseQueryString(urlStr) { + const url = new URL(urlStr); + const result = {}; + for(const [key, value] of url.searchParams) { + result[key] = value; + } + return result; +} + +/* + 9.2.1. Interface Exposed by Identity Providers + callback GenerateAssertionCallback = + Promise<RTCIdentityAssertionResult> ( + DOMString contents, + DOMString origin, + RTCIdentityProviderOptions options); + + dictionary RTCIdentityProviderOptions { + DOMString protocol = "default"; + DOMString usernameHint; + DOMString peerIdentity; + }; + + dictionary RTCIdentityAssertionResult { + required RTCIdentityProviderDetails idp; + required DOMString assertion; + }; + + dictionary RTCIdentityProviderDetails { + required DOMString domain; + DOMString protocol = "default"; + }; + */ + +const query = parseQueryString(location); + +// Generate a naive identity assertion. The result assertion +// is a JSON string that report the various parameters +// received by this function. +// watermark - a special mark to make sure the result is returned +// from this function +// args - the function arguments received +// env - some global variable values when this function is called +// query - the parsed query string of the script URL +function generateAssertion(contents, origin, options) { + const args = { + contents, origin, options + }; + + const env = { + origin, + location + }; + + const assertion = { + watermark: 'mock-idp.js.watermark', + args, + env, + query + }; + + const assertionStr = JSON.stringify(assertion); + + const { generatorAction } = query; + + if(generatorAction === 'throw-error') { + const err = new Error('Mock Internal IdP Error'); + err.idpErrorInfo = query.errorInfo; + throw err; + + } else if(generatorAction === 'require-login') { + const err = new RTCError('idp-need-login'); + err.idpLoginUrl = `${origin}/login`; + err.idpErrorInfo = 'login required'; + throw err; + + } else if(generatorAction === 'return-custom-idp') { + const { domain, protocol } = query; + + return { + idp: { + domain, + protocol + }, + assertion: assertionStr + }; + + } else if(generatorAction === 'return-invalid-result') { + return 'invalid-result'; + + } else { + return { + idp: { + domain: location.host, + protocol: 'mock-idp.js' + }, + assertion: assertionStr + }; + } +} + +/* + 9.2.1. Interface Exposed by Identity Providers + callback ValidateAssertionCallback = + Promise<RTCIdentityValidationResult> ( + DOMString assertion, + DOMString origin); + + dictionary RTCIdentityValidationResult { + required DOMString identity; + required DOMString contents; + }; + */ +function validateAssertion(assertionStr, origin) { + const assertion = JSON.parse(assertionStr); + + const { args, query } = assertion; + const { contents, options } = args; + + const identity = options.usernameHint; + + const { + validatorAction + } = query; + + if(validatorAction === 'throw-error') { + const err = new Error('Mock Internal IdP Error'); + err.idpErrorInfo = query.errorInfo; + throw err; + + } else if(validatorAction === 'return-custom-contents') { + const { contents } = query; + return { + identity, + contents + }; + + } else { + return { + identity, contents + }; + } +} + +/* + 9.2. Registering an IdP Proxy + [Global, + Exposed=RTCIdentityProviderGlobalScope] + interface RTCIdentityProviderGlobalScope : WorkerGlobalScope { + readonly attribute RTCIdentityProviderRegistrar rtcIdentityProvider; + }; + + [Exposed=RTCIdentityProviderGlobalScope] + interface RTCIdentityProviderRegistrar { + void register(RTCIdentityProvider idp); + }; + + dictionary RTCIdentityProvider { + required GenerateAssertionCallback generateAssertion; + required ValidateAssertionCallback validateAssertion; + }; + */ + +// if rtcIdentityProvider is defined, and the caller do not ask +// to not register through query string, register our assertion callbacks. +if(rtcIdentityProvider && query.action !== 'do-not-register') { + rtcIdentityProvider.register({ + generateAssertion, + validateAssertion + }); +} |