(Re|de)fining the identity provider sandbox

Firefox has had a disabled implementation of the identity provider for
a while now, but it hasn't worked with our upcoming process isolation
feature.  In the process of trying to get it working, I have learned
that the exact form of the identity provider sandbox is somewhat
abnormal.  Based on the feedback I've received from a range of people
on this, I'm going to propose some structure changes to how the
identity provider sandbox is described in the spec.

This doesn't change the semantics of the API (we can talk about that
subsequently), but it changes the specification.  Browser
implementations will likely be somewhat different (they won't have to
load HTML any more).  The IdP will see a different interface, which -
in my opinion at least - is much nicer.

----

An IdP is identified in the same way, but rather than HTML, it loads a
JavaScript file.  That JavaScript runs in a sandbox, which might
implemented like a worker.  A few basic facilities are exposed to that
sandbox, including WebCrypto and XMLHttpRequest, plus one custom
property.

The presence of the rtcIdentityProvider property on the sandbox global
signals to the IdP that this is a browser-created sandbox (or script
from its own origin, an ever-present risk, sadly).  This property
conforms to the following WebIDL:

[NoInterfaceObject]
interface RTCIdentityProviderRegistrar {
  void register(RTCIdentityProvider idp);
};

The IdP calls the register function on this object to indicate that it
is ready.  This MUST be called before the sandbox execution completes,
or the browser will regard the IdP as being broken.

The interface that the IdP conforms to covers the two basic operations
that the current "protocol" does, namely "SIGN" and "VERIFY",
respectively generateAssertion() and validateAssertion():

callback interface RTCIdentityProvider {
  Promise<RTCIdentityAssertionResult>
    generateAssertion(DOMString contents, DOMString origin,
                    optional DOMString usernameHint);
  Promise<RTCIdentityValidationResult>
    validateAssertion(DOMString assertion, DOMString origin);
};

And that's it.  The dictionaries that comprise the results are the
same as they were previously, but here is the IDL:

dictionary RTCIdentityAssertionResult {
  required RTCIdentityProviderDetails idp;
  required DOMString assertion;
};

dictionary RTCIdentityProviderDetails {
  required DOMString domain;
  DOMString protocol = "default";
};

dictionary RTCIdentityValidationResult {
  required DOMString identity;
  required DOMString contents;
};

The only part that is a little ugly is the "LOGINNEEDED" stuff.  My
current idea is to expose a RTCIdentityLoginNeeded object that can be
used in rejecting generateAssertion().  I need to gather some more
input on that though.  I thought that I'd share where this is at
though.

----

I have an implementation of this, but I'm told that it isn't properly
secure; I'm working on fixing that.

Received on Tuesday, 30 December 2014 18:47:51 UTC