зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1892010 - Redefine the IdentityCredential to support the lightweight version, r=anti-tracking-reviewers,webidl,smaug,timhuang,geckoview-reviewers,owlish
Prototyping https://github.com/fedidcg/CrossSiteCookieAccessCredential. There is no change here in even Nightly behavior- keeping everything behind a pref. Differential Revision: https://phabricator.services.mozilla.com/D209828
This commit is contained in:
Родитель
6d5d7fe17d
Коммит
5562014f59
|
@ -3025,6 +3025,7 @@ pref("cookiebanners.ui.desktop.cfrVariant", 0);
|
|||
|
||||
#ifdef NIGHTLY_BUILD
|
||||
pref("dom.security.credentialmanagement.identity.enabled", true);
|
||||
pref("dom.security.credentialmanagement.identity.heavyweight.enabled", true);
|
||||
#endif
|
||||
|
||||
pref("ui.new-webcompat-reporter.enabled", true);
|
||||
|
|
|
@ -4,14 +4,22 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include "mozilla/dom/PermissionMessageUtils.h";
|
||||
[RefCounted] using class nsIPrincipal from "nsIPrincipal.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
struct IPCIdentityCredential
|
||||
{
|
||||
nsString id;
|
||||
nsString type;
|
||||
nsString token;
|
||||
nsString? token;
|
||||
nsCString? name;
|
||||
nsCString? iconURL;
|
||||
nsCString[] originAllowlist;
|
||||
nsCString? dynamicViaCors;
|
||||
nsCString? infoExpires;
|
||||
nullable nsIPrincipal identityProvider;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -37,26 +37,106 @@ JSObject* IdentityCredential::WrapObject(JSContext* aCx,
|
|||
}
|
||||
|
||||
IdentityCredential::IdentityCredential(nsPIDOMWindowInner* aParent)
|
||||
: Credential(aParent) {}
|
||||
|
||||
void IdentityCredential::CopyValuesFrom(const IPCIdentityCredential& aOther) {
|
||||
this->SetToken(aOther.token());
|
||||
this->SetId(aOther.id());
|
||||
this->SetType(aOther.type());
|
||||
: Credential(aParent) {
|
||||
if (aParent && aParent->GetBrowsingContext() &&
|
||||
aParent->GetBrowsingContext()->Top() &&
|
||||
aParent->GetBrowsingContext()->Top()->GetDocument()) {
|
||||
this->mIdentityProvider =
|
||||
aParent->GetBrowsingContext()->Top()->GetDocument()->GetPrincipal();
|
||||
}
|
||||
}
|
||||
|
||||
IPCIdentityCredential IdentityCredential::MakeIPCIdentityCredential() {
|
||||
nsString token, id, type;
|
||||
GetToken(token);
|
||||
GetId(id);
|
||||
GetType(type);
|
||||
IdentityCredential::IdentityCredential(nsPIDOMWindowInner* aParent,
|
||||
const IPCIdentityCredential& aOther)
|
||||
: Credential(aParent) {
|
||||
CopyValuesFrom(aOther);
|
||||
}
|
||||
|
||||
void IdentityCredential::CopyValuesFrom(const IPCIdentityCredential& aOther) {
|
||||
this->SetId(aOther.id());
|
||||
this->SetType(u"identity"_ns);
|
||||
if (aOther.token().isSome()) {
|
||||
this->SetToken(aOther.token().value());
|
||||
}
|
||||
IdentityCredentialInit creationOptions;
|
||||
if (aOther.dynamicViaCors().isSome()) {
|
||||
creationOptions.mDynamicViaCORS.Construct(aOther.dynamicViaCors().value());
|
||||
}
|
||||
if (aOther.originAllowlist().Length() > 0) {
|
||||
creationOptions.mOriginAllowlist.Construct(
|
||||
Sequence(aOther.originAllowlist().Clone()));
|
||||
}
|
||||
creationOptions.mId = aOther.id();
|
||||
IdentityCredentialUserData userData;
|
||||
if (aOther.name().isSome()) {
|
||||
userData.mName = aOther.name()->Data();
|
||||
}
|
||||
if (aOther.iconURL().isSome()) {
|
||||
userData.mIconURL = aOther.iconURL()->Data();
|
||||
}
|
||||
if (aOther.infoExpires().isSome()) {
|
||||
userData.mExpires.Construct(aOther.infoExpires()->get());
|
||||
}
|
||||
if (aOther.name().isSome() || aOther.iconURL().isSome() ||
|
||||
aOther.infoExpires().isSome()) {
|
||||
creationOptions.mUiHint.Construct(userData);
|
||||
}
|
||||
this->mCreationOptions = Some(creationOptions);
|
||||
this->mIdentityProvider = aOther.identityProvider();
|
||||
}
|
||||
|
||||
IPCIdentityCredential IdentityCredential::MakeIPCIdentityCredential() const {
|
||||
IPCIdentityCredential result;
|
||||
result.token() = token;
|
||||
result.id() = id;
|
||||
result.type() = type;
|
||||
result.identityProvider() = mIdentityProvider;
|
||||
this->GetId(result.id());
|
||||
if (!this->mToken.IsEmpty()) {
|
||||
result.token() = Some(this->mToken);
|
||||
}
|
||||
if (this->mCreationOptions.isSome()) {
|
||||
if (this->mCreationOptions->mDynamicViaCORS.WasPassed()) {
|
||||
result.dynamicViaCors() =
|
||||
Some(this->mCreationOptions->mDynamicViaCORS.Value());
|
||||
}
|
||||
if (this->mCreationOptions->mOriginAllowlist.WasPassed()) {
|
||||
result.originAllowlist() =
|
||||
this->mCreationOptions->mOriginAllowlist.Value();
|
||||
}
|
||||
if (this->mCreationOptions->mUiHint.WasPassed() &&
|
||||
!this->mCreationOptions->mUiHint.Value().mIconURL.IsEmpty()) {
|
||||
result.iconURL() = Some(this->mCreationOptions->mUiHint.Value().mIconURL);
|
||||
}
|
||||
if (this->mCreationOptions->mUiHint.WasPassed() &&
|
||||
!this->mCreationOptions->mUiHint.Value().mName.IsEmpty()) {
|
||||
result.name() = Some(this->mCreationOptions->mUiHint.Value().mName);
|
||||
}
|
||||
if (this->mCreationOptions->mUiHint.WasPassed() &&
|
||||
this->mCreationOptions->mUiHint.Value().mExpires.WasPassed()) {
|
||||
result.infoExpires() =
|
||||
Some(this->mCreationOptions->mUiHint.Value().mExpires.Value());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<IdentityCredential> IdentityCredential::Constructor(
|
||||
const GlobalObject& aGlobal, const IdentityCredentialInit& aInit,
|
||||
ErrorResult& aRv) {
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!global || !global->GetAsInnerWindow() || !global->PrincipalOrNull()) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<IdentityCredential> result =
|
||||
new IdentityCredential(global->GetAsInnerWindow());
|
||||
result->SetId(aInit.mId);
|
||||
result->SetType(u"identity"_ns);
|
||||
result->mCreationOptions.emplace(aInit);
|
||||
result->mIdentityProvider = global->PrincipalOrNull();
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
void IdentityCredential::GetToken(nsAString& aToken) const {
|
||||
aToken.Assign(mToken);
|
||||
}
|
||||
|
@ -64,6 +144,16 @@ void IdentityCredential::SetToken(const nsAString& aToken) {
|
|||
mToken.Assign(aToken);
|
||||
}
|
||||
|
||||
void IdentityCredential::GetOrigin(nsACString& aOrigin,
|
||||
ErrorResult& aError) const {
|
||||
nsresult rv = mIdentityProvider->GetWebExposedOriginSerialization(aOrigin);
|
||||
if (NS_FAILED(rv)) {
|
||||
aOrigin.SetLength(0);
|
||||
aError.Throw(rv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
RefPtr<IdentityCredential::GetIdentityCredentialPromise>
|
||||
IdentityCredential::DiscoverFromExternalSource(
|
||||
|
@ -130,6 +220,19 @@ IdentityCredential::DiscoverFromExternalSourceInMainProcess(
|
|||
NS_ERROR_DOM_NOT_ALLOWED_ERR, __func__);
|
||||
}
|
||||
|
||||
// Make sure we support the set of features needed for this request
|
||||
RequestType requestType = DetermineRequestType(aOptions);
|
||||
if ((!StaticPrefs::
|
||||
dom_security_credentialmanagement_identity_heavyweight_enabled() &&
|
||||
requestType == HEAVYWEIGHT) ||
|
||||
(!StaticPrefs::
|
||||
dom_security_credentialmanagement_identity_lightweight_enabled() &&
|
||||
requestType == LIGHTWEIGHT) ||
|
||||
requestType == INVALID) {
|
||||
return IdentityCredential::GetIPCIdentityCredentialPromise::CreateAndReject(
|
||||
NS_ERROR_DOM_NOT_ALLOWED_ERR, __func__);
|
||||
}
|
||||
|
||||
RefPtr<IdentityCredential::GetIPCIdentityCredentialPromise::Private> result =
|
||||
new IdentityCredential::GetIPCIdentityCredentialPromise::Private(
|
||||
__func__);
|
||||
|
@ -214,7 +317,8 @@ IdentityCredential::DiscoverFromExternalSourceInMainProcess(
|
|||
IdentityProviderAPIConfig manifest;
|
||||
IdentityProviderConfig provider;
|
||||
std::tie(provider, manifest) = providerAndManifest;
|
||||
return IdentityCredential::CreateCredential(
|
||||
return IdentityCredential::
|
||||
CreateHeavyweightCredentialDuringDiscovery(
|
||||
principal, browsingContext, provider, manifest);
|
||||
},
|
||||
[](nsresult error) {
|
||||
|
@ -243,7 +347,7 @@ IdentityCredential::DiscoverFromExternalSourceInMainProcess(
|
|||
|
||||
// static
|
||||
RefPtr<IdentityCredential::GetIPCIdentityCredentialPromise>
|
||||
IdentityCredential::CreateCredential(
|
||||
IdentityCredential::CreateHeavyweightCredentialDuringDiscovery(
|
||||
nsIPrincipal* aPrincipal, BrowsingContext* aBrowsingContext,
|
||||
const IdentityProviderConfig& aProvider,
|
||||
const IdentityProviderAPIConfig& aManifest) {
|
||||
|
@ -316,9 +420,8 @@ IdentityCredential::CreateCredential(
|
|||
IdentityProviderAccount account;
|
||||
std::tie(token, account) = promiseResult;
|
||||
IPCIdentityCredential credential;
|
||||
credential.token() = token.mToken;
|
||||
credential.token() = Some(token.mToken);
|
||||
credential.id() = account.mId;
|
||||
credential.type() = u"identity"_ns;
|
||||
return IdentityCredential::GetIPCIdentityCredentialPromise::
|
||||
CreateAndResolve(credential, __func__);
|
||||
},
|
||||
|
@ -342,7 +445,7 @@ IdentityCredential::CheckRootManifest(nsIPrincipal* aPrincipal,
|
|||
}
|
||||
|
||||
// Build the URL
|
||||
nsCString configLocation = aProvider.mConfigURL;
|
||||
nsCString configLocation = aProvider.mConfigURL.Value();
|
||||
nsCOMPtr<nsIURI> configURI;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(configURI), configLocation);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
@ -407,7 +510,8 @@ IdentityCredential::CheckRootManifest(nsIPrincipal* aPrincipal,
|
|||
|
||||
// Resolve whether or not that provider URL is the one we were
|
||||
// passed as an argument.
|
||||
bool correctURL = manifest.mProvider_urls[0] == aProvider.mConfigURL;
|
||||
bool correctURL =
|
||||
manifest.mProvider_urls[0] == aProvider.mConfigURL.Value();
|
||||
return IdentityCredential::ValidationPromise::CreateAndResolve(
|
||||
correctURL, __func__);
|
||||
},
|
||||
|
@ -423,7 +527,7 @@ IdentityCredential::FetchInternalManifest(
|
|||
nsIPrincipal* aPrincipal, const IdentityProviderConfig& aProvider) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
// Build the URL
|
||||
nsCString configLocation = aProvider.mConfigURL;
|
||||
nsCString configLocation = aProvider.mConfigURL.Value();
|
||||
|
||||
// Create the global
|
||||
RefPtr<NullPrincipal> nullPrincipal =
|
||||
|
@ -472,7 +576,8 @@ IdentityCredential::FetchAccountList(
|
|||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
// Build the URL
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(baseURI), aProvider.mConfigURL);
|
||||
nsresult rv =
|
||||
NS_NewURI(getter_AddRefs(baseURI), aProvider.mConfigURL.Value());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return IdentityCredential::GetAccountListPromise::CreateAndReject(rv,
|
||||
__func__);
|
||||
|
@ -560,7 +665,7 @@ RefPtr<IdentityCredential::GetTokenPromise> IdentityCredential::FetchToken(
|
|||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
// Build the URL
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
nsCString baseURIString = aProvider.mConfigURL;
|
||||
nsCString baseURIString = aProvider.mConfigURL.Value();
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(baseURI), baseURIString);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return IdentityCredential::GetTokenPromise::CreateAndReject(rv, __func__);
|
||||
|
@ -603,7 +708,7 @@ RefPtr<IdentityCredential::GetTokenPromise> IdentityCredential::FetchToken(
|
|||
internalRequest->SetMethod("POST"_ns);
|
||||
URLParams bodyValue;
|
||||
bodyValue.Set("account_id"_ns, NS_ConvertUTF16toUTF8(aAccount.mId));
|
||||
bodyValue.Set("client_id"_ns, aProvider.mClientId);
|
||||
bodyValue.Set("client_id"_ns, aProvider.mClientId.Value());
|
||||
if (aProvider.mNonce.WasPassed()) {
|
||||
bodyValue.Set("nonce"_ns, aProvider.mNonce.Value());
|
||||
}
|
||||
|
@ -658,7 +763,7 @@ IdentityCredential::FetchMetadata(nsIPrincipal* aPrincipal,
|
|||
MOZ_ASSERT(aPrincipal);
|
||||
// Build the URL
|
||||
nsCOMPtr<nsIURI> baseURI;
|
||||
nsCString baseURIString = aProvider.mConfigURL;
|
||||
nsCString baseURIString = aProvider.mConfigURL.Value();
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(baseURI), baseURIString);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return IdentityCredential::GetMetadataPromise::CreateAndReject(rv,
|
||||
|
@ -914,7 +1019,7 @@ IdentityCredential::PromptUserWithPolicy(
|
|||
}
|
||||
|
||||
// Check the storage bit
|
||||
nsCString configLocation = aProvider.mConfigURL;
|
||||
nsCString configLocation = aProvider.mConfigURL.Value();
|
||||
nsCOMPtr<nsIURI> idpURI;
|
||||
error = NS_NewURI(getter_AddRefs(idpURI), configLocation);
|
||||
if (NS_WARN_IF(NS_FAILED(error))) {
|
||||
|
@ -1048,66 +1153,20 @@ void IdentityCredential::CloseUserInterface(BrowsingContext* aBrowsingContext) {
|
|||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<Promise> IdentityCredential::LogoutRPs(
|
||||
GlobalObject& aGlobal,
|
||||
const Sequence<IdentityCredentialLogoutRPsRequest>& aLogoutRequests,
|
||||
ErrorResult& aRv) {
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
RefPtr<Promise> promise = Promise::CreateResolvedWithUndefined(global, aRv);
|
||||
NS_ENSURE_FALSE(aRv.Failed(), nullptr);
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIIdentityCredentialStorageService> icStorageService =
|
||||
components::IdentityCredentialStorageService::Service(&rv);
|
||||
if (NS_WARN_IF(!icStorageService)) {
|
||||
aRv.Throw(rv);
|
||||
return nullptr;
|
||||
IdentityCredential::RequestType IdentityCredential::DetermineRequestType(
|
||||
const IdentityCredentialRequestOptions& aOptions) {
|
||||
if (!aOptions.mProviders.WasPassed()) {
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
RefPtr<nsIPrincipal> rpPrincipal = global->PrincipalOrNull();
|
||||
for (const auto& request : aLogoutRequests) {
|
||||
// Get the current state
|
||||
nsCOMPtr<nsIURI> idpURI;
|
||||
rv = NS_NewURI(getter_AddRefs(idpURI), request.mUrl);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.ThrowTypeError<MSG_INVALID_URL>(request.mUrl);
|
||||
return nullptr;
|
||||
for (const IdentityProviderConfig& provider : aOptions.mProviders.Value()) {
|
||||
if (provider.mConfigURL.WasPassed()) {
|
||||
return HEAVYWEIGHT;
|
||||
}
|
||||
nsCOMPtr<nsIPrincipal> idpPrincipal = BasePrincipal::CreateContentPrincipal(
|
||||
idpURI, rpPrincipal->OriginAttributesRef());
|
||||
bool registered, allowLogout;
|
||||
icStorageService->GetState(rpPrincipal, idpPrincipal, request.mAccountId,
|
||||
®istered, &allowLogout);
|
||||
|
||||
// Ignore this request if it isn't permitted
|
||||
if (!(registered && allowLogout)) {
|
||||
continue;
|
||||
if (!provider.mOrigin.WasPassed() && !provider.mLoginURL.WasPassed()) {
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
// Issue the logout request
|
||||
constexpr auto fragment = ""_ns;
|
||||
auto internalRequest =
|
||||
MakeSafeRefPtr<InternalRequest>(request.mUrl, fragment);
|
||||
internalRequest->SetRedirectMode(RequestRedirect::Error);
|
||||
internalRequest->SetCredentialsMode(RequestCredentials::Include);
|
||||
internalRequest->SetReferrerPolicy(ReferrerPolicy::Strict_origin);
|
||||
internalRequest->SetMode(RequestMode::Cors);
|
||||
internalRequest->SetCacheMode(RequestCache::No_cache);
|
||||
internalRequest->OverrideContentPolicyType(
|
||||
nsContentPolicyType::TYPE_WEB_IDENTITY);
|
||||
RefPtr<Request> domRequest =
|
||||
new Request(global, std::move(internalRequest), nullptr);
|
||||
RequestOrUTF8String fetchInput;
|
||||
fetchInput.SetAsRequest() = domRequest;
|
||||
RootedDictionary<RequestInit> requestInit(RootingCx());
|
||||
IgnoredErrorResult error;
|
||||
RefPtr<Promise> fetchPromise = FetchRequest(global, fetchInput, requestInit,
|
||||
CallerType::System, error);
|
||||
|
||||
// Change state to disallow more logout requests
|
||||
icStorageService->SetState(rpPrincipal, idpPrincipal, request.mAccountId,
|
||||
true, false);
|
||||
}
|
||||
return promise.forget();
|
||||
return LIGHTWEIGHT;
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
||||
#include "mozilla/dom/Credential.h"
|
||||
#include "mozilla/dom/IPCIdentityCredential.h"
|
||||
#include "mozilla/IdentityCredentialStorageService.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
@ -20,6 +21,8 @@ namespace mozilla::dom {
|
|||
// with an "identity" argument. It also includes static functions that
|
||||
// perform operations that are used in constructing the credential.
|
||||
class IdentityCredential final : public Credential {
|
||||
friend class mozilla::IdentityCredentialStorageService;
|
||||
|
||||
public:
|
||||
// These are promise types, all used to support the async implementation of
|
||||
// this API. All are of the form MozPromise<RefPtr<T>, nsresult>.
|
||||
|
@ -53,12 +56,18 @@ class IdentityCredential final : public Credential {
|
|||
typedef MozPromise<IdentityProviderClientMetadata, nsresult, true>
|
||||
GetMetadataPromise;
|
||||
|
||||
// This needs to be constructed in the context of a window
|
||||
explicit IdentityCredential(nsPIDOMWindowInner* aParent);
|
||||
|
||||
protected:
|
||||
~IdentityCredential() override;
|
||||
|
||||
// This needs to be constructed in the context of a window
|
||||
// This is called in the context of Create and Constructor. aParent is the
|
||||
// identity provider
|
||||
explicit IdentityCredential(nsPIDOMWindowInner* aParent);
|
||||
// This is called in the context of Discover and Collect. the identity
|
||||
// provider is in aOther
|
||||
explicit IdentityCredential(nsPIDOMWindowInner* aParent,
|
||||
const IPCIdentityCredential& aOther);
|
||||
|
||||
public:
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
@ -70,31 +79,18 @@ class IdentityCredential final : public Credential {
|
|||
void CopyValuesFrom(const IPCIdentityCredential& aOther);
|
||||
|
||||
// This is the inverse of CopyValuesFrom. Included for completeness.
|
||||
IPCIdentityCredential MakeIPCIdentityCredential();
|
||||
IPCIdentityCredential MakeIPCIdentityCredential() const;
|
||||
|
||||
static already_AddRefed<IdentityCredential> Constructor(
|
||||
const GlobalObject& aGlobal, const IdentityCredentialInit& aInit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// Getter and setter for the token member of this class
|
||||
void GetToken(nsAString& aToken) const;
|
||||
void SetToken(const nsAString& aToken);
|
||||
|
||||
// This function allows a relying party to send one last credentialed request
|
||||
// to the IDP when logging out. This only works if the current account state
|
||||
// in the IdentityCredentialStorageService allows logouts and clears that bit
|
||||
// when a request is sent.
|
||||
//
|
||||
// Arguments:
|
||||
// aGlobal: the global of the window calling this function
|
||||
// aLogoutRequest: all of the logout requests to try to send.
|
||||
// This is pairs of the IDP's logout url and the account
|
||||
// ID for that IDP.
|
||||
// Return value:
|
||||
// a promise resolving to undefined
|
||||
// Side effects:
|
||||
// Will send a network request to each IDP that have a state allowing
|
||||
// logouts and disables that bit.
|
||||
static already_AddRefed<Promise> LogoutRPs(
|
||||
GlobalObject& aGlobal,
|
||||
const Sequence<IdentityCredentialLogoutRPsRequest>& aLogoutRequests,
|
||||
ErrorResult& aRv);
|
||||
// Get the Origin of this credential's identity provider
|
||||
void GetOrigin(nsACString& aOrigin, ErrorResult& aError) const;
|
||||
|
||||
// This is the main static function called when a credential needs to be
|
||||
// fetched from the IDP. Called in the content process.
|
||||
|
@ -138,7 +134,8 @@ class IdentityCredential final : public Credential {
|
|||
// Side effects:
|
||||
// Will send network requests to the IDP. The details of which are in the
|
||||
// other static methods here.
|
||||
static RefPtr<GetIPCIdentityCredentialPromise> CreateCredential(
|
||||
static RefPtr<GetIPCIdentityCredentialPromise>
|
||||
CreateHeavyweightCredentialDuringDiscovery(
|
||||
nsIPrincipal* aPrincipal, BrowsingContext* aBrowsingContext,
|
||||
const IdentityProviderConfig& aProvider,
|
||||
const IdentityProviderAPIConfig& aManifest);
|
||||
|
@ -307,6 +304,14 @@ class IdentityCredential final : public Credential {
|
|||
|
||||
private:
|
||||
nsAutoString mToken;
|
||||
nsCOMPtr<nsIPrincipal> mIdentityProvider;
|
||||
Maybe<IdentityCredentialInit> mCreationOptions;
|
||||
|
||||
// Identity credential requests can either be heavyweight or lighweight in
|
||||
// their browser UI. The heavyweight ones are "traditional" FedCM
|
||||
enum RequestType { INVALID, LIGHTWEIGHT, HEAVYWEIGHT };
|
||||
static RequestType DetermineRequestType(
|
||||
const IdentityCredentialRequestOptions& aOptions);
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
|
|
@ -20,12 +20,20 @@ struct ParamTraits<mozilla::dom::IdentityProviderConfig> {
|
|||
WriteParam(aWriter, aParam.mConfigURL);
|
||||
WriteParam(aWriter, aParam.mClientId);
|
||||
WriteParam(aWriter, aParam.mNonce);
|
||||
WriteParam(aWriter, aParam.mOrigin);
|
||||
WriteParam(aWriter, aParam.mLoginURL);
|
||||
WriteParam(aWriter, aParam.mLoginTarget);
|
||||
WriteParam(aWriter, aParam.mDynamicViaCORS);
|
||||
}
|
||||
|
||||
static bool Read(MessageReader* aReader, paramType* aResult) {
|
||||
return ReadParam(aReader, &aResult->mConfigURL) &&
|
||||
ReadParam(aReader, &aResult->mClientId) &&
|
||||
ReadParam(aReader, &aResult->mNonce);
|
||||
ReadParam(aReader, &aResult->mNonce) &&
|
||||
ReadParam(aReader, &aResult->mOrigin) &&
|
||||
ReadParam(aReader, &aResult->mLoginURL) &&
|
||||
ReadParam(aReader, &aResult->mLoginTarget) &&
|
||||
ReadParam(aReader, &aResult->mDynamicViaCORS);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -39,7 +47,6 @@ struct ParamTraits<mozilla::dom::IdentityCredentialRequestOptions> {
|
|||
|
||||
static bool Read(MessageReader* aReader, paramType* aResult) {
|
||||
return ReadParam(aReader, &aResult->mProviders);
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[DEFAULT]
|
||||
prefs = [
|
||||
"dom.security.credentialmanagement.identity.enabled=true",
|
||||
"dom.security.credentialmanagement.identity.heavyweight.enabled=true",
|
||||
"dom.security.credentialmanagement.identity.ignore_well_known=true",
|
||||
"privacy.antitracking.enableWebcompat=false", # disables opener heuristic
|
||||
]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
[DEFAULT]
|
||||
prefs = [
|
||||
"dom.security.credentialmanagement.identity.enabled=true",
|
||||
"dom.security.credentialmanagement.identity.heavyweight.enabled=true",
|
||||
"dom.security.credentialmanagement.identity.select_first_in_ui_lists=true",
|
||||
"dom.security.credentialmanagement.identity.reject_delay.enabled=false",
|
||||
"privacy.antitracking.enableWebcompat=false", # disables opener heuristic
|
||||
|
|
|
@ -54,5 +54,7 @@ dictionary CredentialCreationOptions {
|
|||
// https://w3c.github.io/webauthn/#sctn-credentialcreationoptions-extension
|
||||
[Pref="security.webauth.webauthn"]
|
||||
PublicKeyCredentialCreationOptions publicKey;
|
||||
[Pref="dom.security.credentialmanagement.identity.enabled"]
|
||||
IdentityCredentialInit identity;
|
||||
AbortSignal signal;
|
||||
};
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
Pref="dom.security.credentialmanagement.identity.enabled"]
|
||||
interface IdentityCredential : Credential {
|
||||
readonly attribute USVString? token;
|
||||
[Throws]
|
||||
static Promise<undefined> logoutRPs(sequence<IdentityCredentialLogoutRPsRequest> logoutRequests);
|
||||
[Throws, Pref="dom.security.credentialmanagement.identity.lightweight.enabled"]
|
||||
readonly attribute UTF8String origin;
|
||||
[Throws, Pref="dom.security.credentialmanagement.identity.lightweight.enabled"]
|
||||
constructor(IdentityCredentialInit init);
|
||||
};
|
||||
|
||||
dictionary IdentityCredentialRequestOptions {
|
||||
|
@ -22,11 +24,38 @@ dictionary IdentityCredentialRequestOptions {
|
|||
|
||||
[GenerateConversionToJS]
|
||||
dictionary IdentityProviderConfig {
|
||||
required UTF8String configURL;
|
||||
required UTF8String clientId;
|
||||
UTF8String configURL;
|
||||
UTF8String clientId;
|
||||
UTF8String nonce;
|
||||
[Pref="dom.security.credentialmanagement.identity.lightweight.enabled"]
|
||||
UTF8String origin;
|
||||
[Pref="dom.security.credentialmanagement.identity.lightweight.enabled"]
|
||||
UTF8String loginURL;
|
||||
[Pref="dom.security.credentialmanagement.identity.lightweight.enabled"]
|
||||
UTF8String loginTarget;
|
||||
[Pref="dom.security.credentialmanagement.identity.lightweight.enabled"]
|
||||
UTF8String dynamicViaCORS;
|
||||
[Pref="dom.security.credentialmanagement.identity.lightweight.enabled"]
|
||||
UTF8String data;
|
||||
};
|
||||
|
||||
// Lightweight only
|
||||
|
||||
dictionary IdentityCredentialUserData {
|
||||
required UTF8String name;
|
||||
required UTF8String iconURL;
|
||||
UTF8String expires;
|
||||
};
|
||||
|
||||
dictionary IdentityCredentialInit {
|
||||
required DOMString id;
|
||||
sequence<UTF8String> originAllowlist;
|
||||
UTF8String dynamicViaCORS;
|
||||
IdentityCredentialUserData uiHint;
|
||||
};
|
||||
|
||||
// Heavyweight only
|
||||
|
||||
// https://fedidcg.github.io/FedCM/#dictdef-identityproviderwellknown
|
||||
[GenerateInit]
|
||||
dictionary IdentityProviderWellKnown {
|
||||
|
@ -85,9 +114,3 @@ dictionary IdentityProviderClientMetadata {
|
|||
dictionary IdentityProviderToken {
|
||||
required USVString token;
|
||||
};
|
||||
|
||||
// https://fedidcg.github.io/FedCM/#dictdef-identitycredentiallogoutrpsrequest
|
||||
dictionary IdentityCredentialLogoutRPsRequest {
|
||||
required UTF8String url;
|
||||
required UTF8String accountId;
|
||||
};
|
||||
|
|
|
@ -669,6 +669,11 @@ class PromptDelegateTest : BaseSessionTest(
|
|||
"dom.security.credentialmanagement.identity.enabled" to true,
|
||||
),
|
||||
)
|
||||
sessionRule.setPrefsUntilTestEnd(
|
||||
mapOf(
|
||||
"dom.security.credentialmanagement.identity.heavyweight.enabled" to true,
|
||||
),
|
||||
)
|
||||
sessionRule.setPrefsUntilTestEnd(
|
||||
mapOf(
|
||||
"dom.security.credentialmanagement.identity.test_ignore_well_known" to true,
|
||||
|
|
|
@ -3852,6 +3852,18 @@
|
|||
value: false
|
||||
mirror: always
|
||||
|
||||
# pref controls "heavyweight" network discoverable `identity` credentials being exposed
|
||||
- name: dom.security.credentialmanagement.identity.heavyweight.enabled
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# pref controls storable "lightweight" `identity` credentials being exposed
|
||||
- name: dom.security.credentialmanagement.identity.lightweight.enabled
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# pref controls `identity` credential UI for testing. When true, UI is not shown and
|
||||
# the first option in the account and provider lists are chosen
|
||||
- name: dom.security.credentialmanagement.identity.select_first_in_ui_lists
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
head = "head.js"
|
||||
prefs = [
|
||||
"dom.security.credentialmanagement.identity.enabled=true",
|
||||
"dom.security.credentialmanagement.identity.heavyweight.enabled=true",
|
||||
"dom.security.credentialmanagement.identity.ignore_well_known=true",
|
||||
"privacy.antitracking.enableWebcompat=false",
|
||||
] # disables opener heuristic
|
||||
|
|
Загрузка…
Ссылка в новой задаче