3737namespace WebCore {
3838
3939static const char privateClickMeasurementTriggerAttributionPath[] = " /.well-known/private-click-measurement/trigger-attribution/" ;
40- static const char privateClickMeasurementTokenSignaturePath[] = " /.well-known/private-click-measurement/sign-unlinkable -token/" ;
40+ static const char privateClickMeasurementTokenSignaturePath[] = " /.well-known/private-click-measurement/sign-secret -token/" ;
4141static const char privateClickMeasurementTokenPublicKeyPath[] = " /.well-known/private-click-measurement/get-unlinkable-token-public-key/" ;
4242static const char privateClickMeasurementReportAttributionPath[] = " /.well-known/private-click-measurement/report-attribution/" ;
4343const size_t privateClickMeasurementAttributionTriggerDataPathSegmentSize = 2 ;
@@ -116,15 +116,15 @@ bool PrivateClickMeasurement::hasHigherPriorityThan(const PrivateClickMeasuremen
116116 return m_attributionTriggerData->priority > other.m_attributionTriggerData ->priority ;
117117}
118118
119- URL PrivateClickMeasurement::tokenSignatureURL () const
119+ URL PrivateClickMeasurement::attributionReportURL () const
120120{
121- if (!m_ephemeralSourceNonce || !m_ephemeralSourceNonce-> isValid ())
121+ if (!isValid ())
122122 return URL ();
123123
124124 StringBuilder builder;
125125 builder.appendLiteral (" https://" );
126126 builder.append (m_sourceSite.registrableDomain .string ());
127- builder.appendLiteral (privateClickMeasurementTokenSignaturePath );
127+ builder.appendLiteral (privateClickMeasurementReportAttributionPath );
128128
129129 URL url { URL (), builder.toString () };
130130 if (url.isValid ())
@@ -133,12 +133,51 @@ URL PrivateClickMeasurement::tokenSignatureURL() const
133133 return URL ();
134134}
135135
136- URL PrivateClickMeasurement::tokenPublicKeyURL () const
136+ Ref<JSON ::Object> PrivateClickMeasurement::attributionReportJSON () const
137+ {
138+ auto reportDetails = JSON::Object::create ();
139+ if (!m_attributionTriggerData || !isValid ())
140+ return reportDetails;
141+
142+ reportDetails->setString (" source_engagement_type" _s, " click" _s);
143+ reportDetails->setString (" source_site" _s, m_sourceSite.registrableDomain .string ());
144+ reportDetails->setInteger (" source_id" _s, m_sourceID.id );
145+ reportDetails->setString (" attributed_on_site" _s, m_attributeOnSite.registrableDomain .string ());
146+ reportDetails->setInteger (" trigger_data" _s, m_attributionTriggerData->data );
147+ reportDetails->setInteger (" version" _s, 1 );
148+ return reportDetails;
149+ }
150+
151+ // MARK: - Fraud Prevention
152+
153+ static constexpr uint32_t EphemeralSourceNonceRequiredNumberOfBytes = 16 ;
154+
155+ bool PrivateClickMeasurement::EphemeralSourceNonce::isValid () const
137156{
157+ // FIXME: Investigate if we can do with a simple length check instead of decoding.
158+ // https://bugs.webkit.org/show_bug.cgi?id=221945
159+ Vector<uint8_t > digest;
160+ if (!base64URLDecode (nonce, digest))
161+ return false ;
162+ return digest.size () == EphemeralSourceNonceRequiredNumberOfBytes;
163+ }
164+
165+ void PrivateClickMeasurement::setEphemeralSourceNonce (EphemeralSourceNonce&& nonce)
166+ {
167+ if (!nonce.isValid ())
168+ return ;
169+ m_ephemeralSourceNonce = WTFMove (nonce);
170+ }
171+
172+ URL PrivateClickMeasurement::tokenSignatureURL () const
173+ {
174+ if (!m_ephemeralSourceNonce || !m_ephemeralSourceNonce->isValid ())
175+ return URL ();
176+
138177 StringBuilder builder;
139178 builder.appendLiteral (" https://" );
140179 builder.append (m_sourceSite.registrableDomain .string ());
141- builder.appendLiteral (privateClickMeasurementTokenPublicKeyPath );
180+ builder.appendLiteral (privateClickMeasurementTokenSignaturePath );
142181
143182 URL url { URL (), builder.toString () };
144183 if (url.isValid ())
@@ -147,28 +186,12 @@ URL PrivateClickMeasurement::tokenPublicKeyURL() const
147186 return URL ();
148187}
149188
150- Ref<JSON ::Object> PrivateClickMeasurement::tokenSignatureJSON () const
151- {
152- auto reportDetails = JSON::Object::create ();
153- if (!m_ephemeralSourceNonce || !m_ephemeralSourceNonce->isValid ())
154- return reportDetails;
155-
156- reportDetails->setString (" source_engagement_type" _s, " click" _s);
157- reportDetails->setString (" source_nonce" _s, m_ephemeralSourceNonce->nonce );
158- reportDetails->setString (" unlinkable_token" _s, " TODO" _s);
159- reportDetails->setInteger (" version" _s, 2 );
160- return reportDetails;
161- }
162-
163- URL PrivateClickMeasurement::attributionReportURL () const
189+ URL PrivateClickMeasurement::tokenPublicKeyURL () const
164190{
165- if (!isValid ())
166- return URL ();
167-
168191 StringBuilder builder;
169192 builder.appendLiteral (" https://" );
170193 builder.append (m_sourceSite.registrableDomain .string ());
171- builder.appendLiteral (privateClickMeasurementReportAttributionPath );
194+ builder.appendLiteral (privateClickMeasurementTokenPublicKeyPath );
172195
173196 URL url { URL (), builder.toString () };
174197 if (url.isValid ())
@@ -177,19 +200,24 @@ URL PrivateClickMeasurement::attributionReportURL() const
177200 return URL ();
178201}
179202
180- Ref<JSON ::Object> PrivateClickMeasurement::attributionReportJSON () const
203+ Ref<JSON ::Object> PrivateClickMeasurement::tokenSignatureJSON ( const String& serverPublicKeyBase64URL)
181204{
182205 auto reportDetails = JSON::Object::create ();
183- if (!m_attributionTriggerData || !isValid ())
206+ if (!m_ephemeralSourceNonce || !m_ephemeralSourceNonce->isValid ())
207+ return reportDetails;
208+
209+ String token;
210+ #if PLATFORM(COCOA)
211+ token = sourceSecretToken (serverPublicKeyBase64URL);
212+ #endif
213+ if (token.isEmpty ())
184214 return reportDetails;
185215
186216 reportDetails->setString (" source_engagement_type" _s, " click" _s);
187- reportDetails->setString (" source_site" _s, m_sourceSite.registrableDomain .string ());
188- reportDetails->setInteger (" source_id" _s, m_sourceID.id );
189- reportDetails->setString (" attributed_on_site" _s, m_attributeOnSite.registrableDomain .string ());
190- reportDetails->setInteger (" trigger_data" _s, m_attributionTriggerData->data );
191- reportDetails->setInteger (" version" _s, 1 );
217+ reportDetails->setString (" source_nonce" _s, m_ephemeralSourceNonce->nonce );
218+ reportDetails->setString (" source_secret_token" _s, token);
219+ reportDetails->setInteger (" version" _s, 2 );
192220 return reportDetails;
193221}
194222
195- }
223+ } // namespace WebCore
0 commit comments