Bug 1782094 - Implement IdentityCredential.logoutRPs, r=timhuang,emilio

Specification is available here: https://fedidcg.github.io/FedCM/#browser-api-idp-sign-out

Implementation is similar to other Fetch* funcitons in this file and makes use of the network helper.

Tests omitted through the same "not exposed to users" justification. This is tracked by Bug 1800687.

Differential Revision: https://phabricator.services.mozilla.com/D162125
This commit is contained in:
Benjamin VanderSloot 2022-12-03 18:50:31 +00:00
Родитель 98cbae5614
Коммит 9fe517527e
3 изменённых файлов: 82 добавлений и 4 удалений

Просмотреть файл

@ -15,7 +15,9 @@
#include "mozilla/ExpandedPrincipal.h"
#include "mozilla/NullPrincipal.h"
#include "nsEffectiveTLDService.h"
#include "nsIGlobalObject.h"
#include "nsIIdentityCredentialPromptService.h"
#include "nsIIdentityCredentialStorageService.h"
#include "nsITimer.h"
#include "nsIXPConnect.h"
#include "nsNetUtil.h"
@ -310,7 +312,7 @@ IdentityCredential::CheckRootManifest(nsIPrincipal* aPrincipal,
}
// Create a new request
nsCString fragment = ""_ns;
constexpr auto fragment = ""_ns;
auto internalRequest =
MakeSafeRefPtr<InternalRequest>(manifestURIString, fragment);
internalRequest->SetCredentialsMode(RequestCredentials::Omit);
@ -375,7 +377,7 @@ IdentityCredential::FetchInternalManifest(nsIPrincipal* aPrincipal,
}
// Create a new request
nsCString fragment = ""_ns;
constexpr auto fragment = ""_ns;
auto internalRequest =
MakeSafeRefPtr<InternalRequest>(configLocation, fragment);
internalRequest->SetRedirectMode(RequestRedirect::Error);
@ -442,7 +444,7 @@ IdentityCredential::FetchAccountList(
}
// Create a new request
nsCString fragment = ""_ns;
constexpr auto fragment = ""_ns;
auto internalRequest =
MakeSafeRefPtr<InternalRequest>(configLocation, fragment);
internalRequest->SetRedirectMode(RequestRedirect::Error);
@ -497,7 +499,7 @@ RefPtr<IdentityCredential::GetTokenPromise> IdentityCredential::FetchToken(
}
// Create a new request
nsCString fragment = ""_ns;
constexpr auto fragment = ""_ns;
auto internalRequest =
MakeSafeRefPtr<InternalRequest>(tokenLocation, fragment);
internalRequest->SetMethod("POST"_ns);
@ -674,4 +676,67 @@ void IdentityCredential::CloseUserInterface(BrowsingContext* aBrowsingContext) {
icPromptService->Close(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;
}
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;
}
nsCOMPtr<nsIPrincipal> idpPrincipal = BasePrincipal::CreateContentPrincipal(
idpURI, rpPrincipal->OriginAttributesRef());
bool registered, allowLogout;
icStorageService->GetState(rpPrincipal, idpPrincipal, request.mAccountId,
&registered, &allowLogout);
// Ignore this request if it isn't permitted
if (!(registered && allowLogout)) {
continue;
}
// 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);
RequestOrUSVString 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();
}
} // namespace mozilla::dom

Просмотреть файл

@ -51,6 +51,11 @@ class IdentityCredential final : public Credential {
void GetToken(nsAString& aToken) const;
void SetToken(const nsAString& aToken);
static already_AddRefed<Promise> LogoutRPs(
GlobalObject& aGlobal,
const Sequence<IdentityCredentialLogoutRPsRequest>& aLogoutRequests,
ErrorResult& aRv);
static RefPtr<GetIdentityCredentialPromise> DiscoverFromExternalSource(
nsPIDOMWindowInner* aParent, const CredentialRequestOptions& aOptions,
bool aSameOriginWithAncestors);

Просмотреть файл

@ -12,6 +12,8 @@
Pref="dom.security.credentialmanagement.identity.enabled"]
interface IdentityCredential : Credential {
readonly attribute USVString? token;
[Throws]
static Promise<undefined> logoutRPs(sequence<IdentityCredentialLogoutRPsRequest> logoutRequests);
};
dictionary IdentityCredentialRequestOptions {
@ -80,3 +82,9 @@ dictionary IdentityClientMetadata {
dictionary IdentityToken {
required USVString token;
};
// https://fedidcg.github.io/FedCM/#browser-api-idp-sign-out
dictionary IdentityCredentialLogoutRPsRequest {
required UTF8String url;
required UTF8String accountId;
};