Authentication on the web is currently handled in the following
way: anyone can install a server that will authenticate users on
the web. The problem is interoperability. If a client (an
application) wants to authenticate a user, it has to be approved
by the authentication server. In other words, if
In the decentralized authentication web, the best attempt so far is that of ActivityPub. All servers are interoperable with respect to authentication: if user A emits an activity, it is forwarded by A's server to its recipients, and A's server is responsible for A's identity.
The problem with that approach is that the data is tied to the application. It is not possible to use another application to process the data differently, or to use multiple data sources, in an interoperable way (without the ActivityPub server knowing). This means that on Activitypub, microblogging applications will not present different activities correctly. This also means that it is difficult to write a free replacement to a non-free application program, because it would need to manage the data.
In the Solid ecosystem, there is a clear distinction between servers and applications. An application is free to read data from all places at the same time, using a permission-less authentication system. Since the applications do not need to store data, the cost of having users is neglectible, so users do not need prior approval before using them (making captchas and the like a thing of the past). Servers do not have a say in which applications the user uses.
The authentication used is a slight modification of the well-established OpenID Connect. It is intended to work in a web browser, but this package demonstrates that it also works without a web browser.
The Json Web Token, or
Decoded JWT are represented as a pair. The car of the pair is
the header, and the cdr is the payload. Both the header and the
payload use the JSON representation from srfi-180: objects are
alists of symbols to values, arrays are
vectors. It is unfortunate that guile-json has a slightly
different representation, where alist keys are
The access token is obtained by the client through a token request, and is presented to the server on each authenticated request. It is signed by the identity provider, and it contains enough information so that the server knows who the user is and who the agent is, and most importantly the fingerprint of the key that the client should use in a DPoP proof.
The API is defined in
Check that
There are field getters for the access token:
Get the suitable field from the payload
of
Access tokens can be signed and encoded as a string, or decoded.
Decode
http-getoptional keyword argument can set a different implementation of
http-getfrom
#fif it failed, or the decoded token otherwise.
Encode
Create an access token, and encode it with
#:cnf/jktkeyword argument with the fingerprint of the client key, or set
#:client-keydirectly, in which case the fingerprint will be computed for you.
This is a special JWT, that is signed by a key controlled by the application. The access token certifies that the key used to sign the proof is approved by the identity provider.
Check that the
Get the corresponding field of the proof.
Check and decode a DPoP proof encoded
as
The
In order to prevent replay attacks, each proof has a unique
random string that is remembered
in
make-jti-listfunction.
The proof is limited to the scope of
one
'GET,
'POSTand so on).
Finally, the key that is used to sign the proof should be
confirmed by the identity provider. To this end,
the
This function in
Encode the proof and sign it with
jwkfield of the proof.
Create a proof, sign it and encode it with
You can parse generic JWTs signed with JWS with the following
functions from
Check that
Get the algorithm used to sign
Check and decode a JWT signed with JWS and encoded
as
Since the decoding and signature verification happen at the
same time (for user friendliness), the
Encode the JWT and sign it with
Both the identity provider and the resource server need to cache things. The identity provider will cache application webids, and the resource server will cache the identity provider keys, for instance.
The solution is to use a file-system cache. Every response
(except those that have a cache-control policy of no-store) are
stored to a sub-directory of
The
Drop
Return a function acting as
The cache will be read and written in
The back-end function,
The library will raise an exception whenever something fishy
occurs. For instance, if a signature is invalid, or the
expiration date has passed. All exception types are defined in
Return a string explaining the
This exception is raised when the base64 decoding function
failed.
Cannot decode
Cannot decode
The identifier
No key among
The
The
We expected the request to succeed, but the server sent a
non-OK
We did not expect the server to respond with
The
The
The
#f), or not an acceptable value.
The
The
The
The
The
The
The
The
The
The
The
The
The
The
It is impossible to fetch the configuration of
It is impossible to fetch the keys of
The
The
The
The
The
The method value
The URI value
The proof is
The proof was
The confirmation of
The
The
The
Could not fetch the graph referenced by