Bug 1911634 - Plumb throug token and effectiveType parameters, enabling IndieAuth use case - r=anti-tracking-reviewers,webidl,smaug,pbz

This stack adds a couple of parameters to the Lightweight FedCM prototype:

token: This allows a created credential to have some data associated. This can then be stored and retrieved by the RP

effectiveType: This allows a RP and IDP to agree on an arbitrary string that makes a credential from the IDP work on the RP. The IDP tags onto the credential and RP puts on the request the same string to let it appear in the browser dialog, as an alternative to the IDP origin or query URL.

Differential Revision: https://phabricator.services.mozilla.com/D218638
This commit is contained in:
Benjamin VanderSloot 2024-08-22 11:41:41 +00:00
Родитель 5a644e638e
Коммит 0e29fccc0a
5 изменённых файлов: 90 добавлений и 23 удалений

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

@ -22,6 +22,7 @@ struct IPCIdentityCredential
nsCString? iconURL;
nsCString[] effectiveOrigins;
nsCString? effectiveQueryURL;
nsCString? effectiveType;
uint64_t? infoExpiresAt;
nullable nsIPrincipal identityProvider;
};

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

@ -4,14 +4,12 @@
* 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 "js/MapAndSet.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/Fetch.h"
#include "mozilla/dom/IdentityCredential.h"
#include "mozilla/dom/IdentityNetworkHelpers.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/Promise-inl.h"
#include "mozilla/dom/Request.h"
#include "mozilla/dom/WindowGlobalChild.h"
#include "mozilla/Components.h"
@ -77,6 +75,9 @@ void IdentityCredential::CopyValuesFrom(const IPCIdentityCredential& aOther) {
creationOptions.mEffectiveOrigins.Construct(
Sequence(aOther.effectiveOrigins().Clone()));
}
if (aOther.effectiveType().isSome()) {
creationOptions.mEffectiveType.Construct(aOther.effectiveType().value());
}
creationOptions.mId = aOther.id();
IdentityCredentialUserData userData;
if (aOther.name().isSome()) {
@ -114,6 +115,10 @@ IPCIdentityCredential IdentityCredential::MakeIPCIdentityCredential() const {
result.effectiveOrigins() =
this->mCreationOptions->mEffectiveOrigins.Value();
}
if (this->mCreationOptions->mEffectiveType.WasPassed()) {
result.effectiveType() =
Some(this->mCreationOptions->mEffectiveType.Value());
}
if (this->mCreationOptions->mUiHint.WasPassed() &&
!this->mCreationOptions->mUiHint.Value().mIconURL.IsEmpty()) {
result.iconURL() = Some(this->mCreationOptions->mUiHint.Value().mIconURL);

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

@ -26,6 +26,7 @@ struct ParamTraits<mozilla::dom::IdentityProviderConfig> {
WriteParam(aWriter, aParam.mLoginURL);
WriteParam(aWriter, aParam.mLoginTarget);
WriteParam(aWriter, aParam.mEffectiveQueryURL);
WriteParam(aWriter, aParam.mEffectiveType);
}
static bool Read(MessageReader* aReader, paramType* aResult) {
@ -35,7 +36,8 @@ struct ParamTraits<mozilla::dom::IdentityProviderConfig> {
ReadParam(aReader, &aResult->mOrigin) &&
ReadParam(aReader, &aResult->mLoginURL) &&
ReadParam(aReader, &aResult->mLoginTarget) &&
ReadParam(aReader, &aResult->mEffectiveQueryURL);
ReadParam(aReader, &aResult->mEffectiveQueryURL) &&
ReadParam(aReader, &aResult->mEffectiveType);
}
};

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

@ -38,7 +38,7 @@ dictionary IdentityProviderConfig {
[Pref="dom.security.credentialmanagement.identity.lightweight.enabled"]
UTF8String effectiveQueryURL;
[Pref="dom.security.credentialmanagement.identity.lightweight.enabled"]
UTF8String data;
UTF8String effectiveType;
};
// Lightweight only
@ -54,6 +54,7 @@ dictionary IdentityCredentialInit {
UTF8String token;
sequence<UTF8String> effectiveOrigins;
UTF8String effectiveQueryURL;
UTF8String effectiveType;
IdentityCredentialUserData uiHint;
};

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

@ -34,7 +34,7 @@
#include "prtime.h"
#define ACCOUNT_STATE_FILENAME "credentialstate.sqlite"_ns
#define SCHEMA_VERSION 1
#define SCHEMA_VERSION 2
#define MODIFIED_NOW PR_Now()
namespace mozilla {
@ -315,11 +315,8 @@ nsresult IdentityCredentialStorageService::EnsureTable(
tableExists = false;
aDatabase->TableExists("lightweight_identity"_ns, &tableExists);
if (!tableExists) {
// Currently there is only one schema version, so we just need to create the
// table. The definition uses no explicit rowid column, instead primary
// keying on the tuple defined in the spec. We store two bits and some
// additional data to make integration with the ClearDataService
// easier/possible.
// The definition uses no explicit rowid column, instead primary
// keying on the tuple defined in the spec.
nsresult rv = aDatabase->SetSchemaVersion(SCHEMA_VERSION);
NS_ENSURE_SUCCESS(rv, rv);
rv = aDatabase->ExecuteSimpleSQL(
@ -331,11 +328,32 @@ nsresult IdentityCredentialStorageService::EnsureTable(
",originAllowlist TEXT"
",dynamicAllowEndpoint TEXT"
",userDataExpireTime INTEGER"
",token TEXT"
",effectiveType TEXT"
",modificationTime INTEGER"
",idpBaseDomain TEXT"
",PRIMARY KEY (idpOrigin, credentialId)"
")"_ns);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
// Ensure the schema is up to date if the table already exists
int32_t schema;
nsresult rv = aDatabase->GetSchemaVersion(&schema);
NS_ENSURE_SUCCESS(rv, rv);
switch (schema) {
case 1:
rv = aDatabase->ExecuteSimpleSQL(
"ALTER TABLE lightweight_identity ADD COLUMN token TEXT;"_ns);
NS_ENSURE_SUCCESS(rv, rv);
rv = aDatabase->ExecuteSimpleSQL(
"ALTER TABLE lightweight_identity ADD COLUMN effectiveType TEXT;"_ns);
NS_ENSURE_SUCCESS(rv, rv);
[[fallthrough]];
default:
rv = aDatabase->SetSchemaVersion(SCHEMA_VERSION);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
@ -347,14 +365,16 @@ IdentityCredentialStorageService::LoadLightweightMemoryTableFromDisk() {
auto constexpr selectAllQuery =
"SELECT idpOrigin, credentialId, name, iconDataURL, "
"originAllowlist, dynamicAllowEndpoint, userDataExpireTime,"
"token, effectiveType,"
"modificationTime, idpBaseDomain FROM lightweight_identity;"_ns;
auto constexpr insertQuery =
"INSERT INTO lightweight_identity(idpOrigin, credentialId, "
"name, iconDataURL, originAllowlist, dynamicAllowEndpoint, "
"userDataExpireTime,"
"userDataExpireTime, token, effectiveType,"
"modificationTime, idpBaseDomain) VALUES (:idpOrigin, :credentialId, "
":name, "
":iconDataURL, :originAllowlist, :dynamicAllowEndpoint, :userDataExpireTime, :modificationTime, :idpBaseDomain);"_ns;
":name, :iconDataURL, :originAllowlist, :dynamicAllowEndpoint, "
":userDataExpireTime,"
":token, :effectiveType, :modificationTime, :idpBaseDomain);"_ns;
nsCOMPtr<mozIStorageStatement> writeStmt;
nsresult rv = mMemoryDatabaseConnection->CreateStatement(
@ -370,7 +390,7 @@ IdentityCredentialStorageService::LoadLightweightMemoryTableFromDisk() {
while (NS_SUCCEEDED(readStmt->ExecuteStep(&hasResult)) && hasResult) {
nsCOMPtr<nsIVariant> modificationTime, userDataExpireTime, idpOrigin,
credentialId, idpBaseDomain, name, iconDataURL, originAllowlist,
dynamicAllowEndpoint;
dynamicAllowEndpoint, token, effectiveType;
// Read values from disk query
rv = readStmt->GetVariant(0, getter_AddRefs(idpOrigin));
@ -387,9 +407,13 @@ IdentityCredentialStorageService::LoadLightweightMemoryTableFromDisk() {
NS_ENSURE_SUCCESS(rv, rv);
rv = readStmt->GetVariant(6, getter_AddRefs(userDataExpireTime));
NS_ENSURE_SUCCESS(rv, rv);
rv = readStmt->GetVariant(7, getter_AddRefs(modificationTime));
rv = readStmt->GetVariant(7, getter_AddRefs(token));
NS_ENSURE_SUCCESS(rv, rv);
rv = readStmt->GetVariant(8, getter_AddRefs(idpBaseDomain));
rv = readStmt->GetVariant(8, getter_AddRefs(effectiveType));
NS_ENSURE_SUCCESS(rv, rv);
rv = readStmt->GetVariant(9, getter_AddRefs(modificationTime));
NS_ENSURE_SUCCESS(rv, rv);
rv = readStmt->GetVariant(10, getter_AddRefs(idpBaseDomain));
NS_ENSURE_SUCCESS(rv, rv);
// Write values to memory database
@ -407,6 +431,10 @@ IdentityCredentialStorageService::LoadLightweightMemoryTableFromDisk() {
NS_ENSURE_SUCCESS(rv, rv);
rv = writeStmt->BindByName("userDataExpireTime"_ns, userDataExpireTime);
NS_ENSURE_SUCCESS(rv, rv);
rv = writeStmt->BindByName("token"_ns, token);
NS_ENSURE_SUCCESS(rv, rv);
rv = writeStmt->BindByName("effectiveType"_ns, effectiveType);
NS_ENSURE_SUCCESS(rv, rv);
rv = writeStmt->BindByName("modificationTime"_ns, modificationTime);
NS_ENSURE_SUCCESS(rv, rv);
rv = writeStmt->BindByName("idpBaseDomain"_ns, idpBaseDomain);
@ -589,17 +617,20 @@ nsresult IdentityCredentialStorageService::UpsertLightweightData(
constexpr auto upsertQuery =
"INSERT INTO lightweight_identity(idpOrigin, credentialId, "
"name, iconDataURL, originAllowlist, dynamicAllowEndpoint, "
"userDataExpireTime,"
"userDataExpireTime, token, effectiveType,"
"modificationTime, idpBaseDomain) VALUES (:idpOrigin, :credentialId, "
":name, "
":iconDataURL, :originAllowlist, :dynamicAllowEndpoint, "
":userDataExpireTime, :modificationTime, :idpBaseDomain)"
":userDataExpireTime, :token, :effectiveType,"
":modificationTime, :idpBaseDomain)"
"ON CONFLICT(idpOrigin, credentialId)"
"DO UPDATE SET name=excluded.name, "
"iconDataURL=excluded.iconDataURL, "
"originAllowlist=excluded.originAllowlist, "
"dynamicAllowEndpoint=excluded.dynamicAllowEndpoint, "
"userDataExpireTime=excluded.userDataExpireTime, "
"token=excluded.token, "
"effectiveType=excluded.effectiveType, "
"modificationTime=excluded.modificationTime"_ns;
nsCOMPtr<mozIStorageStatement> stmt;
@ -642,6 +673,20 @@ nsresult IdentityCredentialStorageService::UpsertLightweightData(
rv = stmt->BindNullByName("dynamicAllowEndpoint"_ns);
}
NS_ENSURE_SUCCESS(rv, rv);
if (aData.effectiveType().isSome()) {
rv = stmt->BindUTF8StringByName("effectiveType"_ns,
aData.effectiveType().value());
} else {
rv = stmt->BindNullByName("effectiveType"_ns);
}
NS_ENSURE_SUCCESS(rv, rv);
if (aData.token().isSome()) {
rv = stmt->BindUTF8StringByName(
"token"_ns, NS_ConvertUTF16toUTF8(aData.token().value()));
} else {
rv = stmt->BindNullByName("token"_ns);
}
NS_ENSURE_SUCCESS(rv, rv);
if (aData.infoExpiresAt().isSome() &&
aData.infoExpiresAt().value() <= INT64_MAX) {
rv = stmt->BindInt64ByName(
@ -953,7 +998,7 @@ NS_IMETHODIMP IdentityCredentialStorageService::
nsresult rv = WaitForInitialization();
NS_ENSURE_SUCCESS(rv, rv);
auto constexpr selectQuery =
"SELECT credentialId, name, iconDataURL, userDataExpireTime, originAllowList, dynamicAllowEndpoint FROM lightweight_identity WHERE idpOrigin=?1"_ns;
"SELECT credentialId, name, iconDataURL, userDataExpireTime, originAllowList, dynamicAllowEndpoint, effectiveType, token FROM lightweight_identity WHERE idpOrigin=?1"_ns;
nsCOMPtr<mozIStorageStatement> stmt;
rv = mMemoryDatabaseConnection->CreateStatement(selectQuery,
getter_AddRefs(stmt));
@ -973,7 +1018,8 @@ NS_IMETHODIMP IdentityCredentialStorageService::
bool hasResult;
// For each result, we append it to the array to return
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
nsAutoString id, name, iconDataURL, originAllowList, dynamicAllowEndpoint;
nsAutoString id, name, iconDataURL, originAllowList, dynamicAllowEndpoint,
effectiveType, token;
int64_t userDataExpireTime;
rv = stmt->GetString(0, id);
NS_ENSURE_SUCCESS(rv, rv);
@ -987,9 +1033,14 @@ NS_IMETHODIMP IdentityCredentialStorageService::
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->GetString(5, dynamicAllowEndpoint);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->GetString(6, effectiveType);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->GetString(7, token);
NS_ENSURE_SUCCESS(rv, rv);
Maybe<nsCString> resultName, resultIconDataURL,
resultDynamicAllowEndpoint;
resultDynamicAllowEndpoint, resultEffectiveType;
Maybe<nsString> resultToken;
nsTArray<nsCString> allowListArray;
Maybe<int64_t> resultUserDataExpireTime;
if (!name.IsVoid() && name.Length()) {
@ -998,6 +1049,12 @@ NS_IMETHODIMP IdentityCredentialStorageService::
if (!iconDataURL.IsVoid() && iconDataURL.Length()) {
resultIconDataURL = Some(NS_ConvertUTF16toUTF8(iconDataURL));
}
if (!effectiveType.IsVoid() && effectiveType.Length()) {
resultEffectiveType = Some(NS_ConvertUTF16toUTF8(effectiveType));
}
if (!token.IsVoid() && token.Length()) {
resultToken = Some(token);
}
for (const auto& origin : originAllowList.Split('|')) {
allowListArray.AppendElement(NS_ConvertUTF16toUTF8(origin));
}
@ -1009,8 +1066,9 @@ NS_IMETHODIMP IdentityCredentialStorageService::
resultUserDataExpireTime = Some(userDataExpireTime);
}
dom::IPCIdentityCredential result(
id, Nothing(), resultName, resultIconDataURL, allowListArray,
resultDynamicAllowEndpoint, resultUserDataExpireTime, idpPrincipal);
id, resultToken, resultName, resultIconDataURL, allowListArray,
resultDynamicAllowEndpoint, resultEffectiveType,
resultUserDataExpireTime, idpPrincipal);
aResult.AppendElement(result);
}
}