OPRF OIDC
Sam Goto
This is an early exploration of a protocol that uses OPRF to enable identity federation on the Web.
The protocol assumes:
- An
IDP
with a logged in useruser_id
. - An
RP
with aorigin
. - A user agent that is trusted by the RP and the IDP.
At the end of the protocol:
- The RP gets a sharded identifier
sub
without learning about the IDP's globaluser_id
- The IDP never learns the RP's
origin
in the exchange - The user is able to reconstruct
sub
to recover their account without the original user agent.
The core idea is to run an OPRF between the user agent and the RP to construct a masking of the RP's origin to generate an aud
= OPRFᴿᴾ
(origin
) which is guaranteed to have the following properties:
- the user agent knows that it is a function of the RP's origin
- the user agent knows that the IDP can't invert it back to the original origin
With a masked aud
, a sharded identifier sub
is constructed by hashing the global user_id
with the aud
in such a way that it can be verified by the user agent.
Sign-in
- The procotol starts with the IDP sending the signed
metadata
(e.g. name, trustworthyness) about the RP to the RP - When a user initiates a sign-in flow at the RP,
- The RP sends to the user agent its signed
metadata
- The user agent constructs a prompt with the
metadata
available and gathers the user's consent to sign-in - Upon consent, the user agent starts constructing the masked
aud
by starting an OPRF:- The user agent uses the RP's
x = origin
as the OPRF input - The user agent selects a random number
r
- The user agent computes
a = H(x) ^ r
and - The user agent sends
a
to the RP
- The user agent uses the RP's
- The RP takes its pass at the OPRF:
- The RP selects its secret key
k
- The RP computes
b = a ^ k
- The RP sends
b
to the user agent
- The RP selects its secret key
- The user agent calculates
b ^ (1 / r)
which is guaranteed to beH(origin) ^ k
and uses it as the maskedaud
- The user agent proceeds to send the
aud
(which represents the RP but isn't invertible) to the IDP - The IDP constructs a sharded identifier
sub
by computingH(user_id, aud)
- The IDP signs an idtoken for
sub
(which is guaranteed a function of theuser_id
) andaud
(which is guaranteed a function of the RP) and sends both the idtoken and theuser_id
to the user agent - The user agent checks if the
sub
is in fact sharded by theaud
by comparing it withH(user_id, aud)
- If it checks out, the user agent sends the idtoken to the RP
- The RP checks if the idtoken is addressed to it, by checking if the
aud
matchesH(origin) ^ k
- If so, the RP logs the user in as
sub
Recovery
The sub
is a hash of of the user_id
and the aud
, which in turn is a function of the RP's secret key k
and the RP's origin. In a new user agent, where the user is logged in as user_id
, and a consistent RP you can reconstruct sub
.