summaryrefslogtreecommitdiff
path: root/doc/webid-oidc.texi
diff options
context:
space:
mode:
authorVivien Kraus <vivien@planete-kraus.eu>2021-07-30 11:58:08 +0200
committerVivien Kraus <vivien@planete-kraus.eu>2021-08-01 15:25:08 +0200
commited64c545c4723dc0efdb1265b05d682e11e4c1f6 (patch)
tree4c4393adc62bff130840c41d9fb137c939f12246 /doc/webid-oidc.texi
parentc6f9d0a4878b2e94e92cc8fce5800fb43185be4d (diff)
Change the name!
Diffstat (limited to 'doc/webid-oidc.texi')
-rw-r--r--doc/webid-oidc.texi1495
1 files changed, 0 insertions, 1495 deletions
diff --git a/doc/webid-oidc.texi b/doc/webid-oidc.texi
deleted file mode 100644
index e7df400..0000000
--- a/doc/webid-oidc.texi
+++ /dev/null
@@ -1,1495 +0,0 @@
-\input texinfo @c -*-texinfo-*-
-@comment $Id@w{$}
-@documentlanguage en
-@comment %**start of header
-@include version.texi
-@settitle Webid-oidc manual
-@syncodeindex pg cp
-@syncodeindex fn cp
-@syncodeindex vr cp
-@syncodeindex tp cp
-@comment %**end of header
-
-@copying
-This is the manual of webid-oidc (version @value{VERSION}, @value{UPDATED}), an implementation of the Solid authentication protocol for guile, client and server.
-
-Copyright @copyright{} 2020, 2021 Vivien Kraus
-@quotation
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.3 or
-any later version published by the Free Software Foundation; with no
-Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
-Texts. A copy of the license is included in the section entitled ``GNU
-Free Documentation License''
-@end quotation
-@end copying
-
-@dircategory Software libraries
-
-@direntry
-* webid-oidc: (webid-oidc)Decentralized Authentication on the Web.
-@end direntry
-
-@titlepage
-@title Webid-oidc manual
-@subtitle for version @value{VERSION}, @value{UPDATED}
-@author Vivien Kraus (@email{vivien@@planete-kraus.eu})
-@page
-@vskip 0pt plus 1fill
-@insertcopying
-@end titlepage
-
-@contents
-@ifnottex
-@node Top
-@top Webid-oidc
-@end ifnottex
-
-@menu
-* Decentralized Authentication on the Web::
-* Invoking webid-oidc::
-* The Json Web Token::
-* Caching on server side::
-* Content negociation::
-* Running an Identity Provider::
-* Running a Resource Server::
-* Running a client::
-* Exceptional conditions::
-* GNU Free Documentation License::
-* Index::
-@end menu
-
-@node Decentralized Authentication on the Web
-@chapter Decentralized Authentication on the Web
-
-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 @var{useful-program} wants
-to authenticate @var{MegaCorp} users, then @var{useful-program} has to
-register to @var{MegaCorp} first, and get approved. This goes against
-the principle of permission-less innovation, which is at the heart of
-the web.
-
-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.
-
-@node Invoking webid-oidc
-@chapter Invoking webid-oidc
-
-The @samp{webid-oidc} program provides different modes of operations:
-
-@table @samp
-@item reverse-proxy
-Run an authenticating reverse proxy. With this command, you specify a
-backend server. When an authenticated user makes a request, you
-receive an additional header containing the user’s identity.
-@item identity-provider
-Run the identity provider only.
-@item client-service
-The client applications must serve some resources: namely, the client
-manifest and the redirect URI.
-@item server
-Run both an identity provider and a resource server.
-@end table
-
-The server is configured with command-line arguments, and environment
-variables.
-
-@menu
-* General options::
-* General server configuration::
-* Configuration for the resource server::
-* Configuration for the identity provider::
-* Configuration for the client service::
-@end menu
-
-@node General options
-@section General options
-The server will respond to @samp{-h} and @samp{-v} commands, to get
-the help output and the version information.
-
-The server output (command-line, logs) are localized for the system
-administrator. You can control it with the @samp{LANG} environment
-variable. So if your locale is not English, you can have the same
-commands as in this manual by running with @code{LANG=C}.
-
-The programs respect the @samp{XDG_DATA_HOME} and
-@samp{XDG_CACHE_HOME} to store persistent data and disposable
-data. The cache directory can be deleted at any time. If one of these
-variables is not set, its value is computed from the @samp{HOME}
-environment variable.
-
-@node General server configuration
-@section General server configuration
-All servers are published under the Affero GPL, which means that the
-service provider needs to publish all changes made to the program to
-users over the network. The @samp{webid-oidc} command provides a
-@samp{--complete-corresponding-source} option so that the system
-administrator can specify a means to download the source.
-
-The servers will add a @samp{Source:} header in each response,
-containing the value of this configuration option.
-
-The servers can be configured to redirect output and errors to a log
-file and an error file, with the @samp{--log-file} and
-@samp{--error-file} options.
-
-The server will listen to port 8080 by default, but this may be
-configured with @samp{--port}. Since the servers do not support TLS,
-and they only support HTTP/1.1, they are intended to run behind a
-reverse proxy (even for the authenticating reverse proxy).
-
-Finally, the servers are required to know their public name. This is
-configured with the @samp{--server-name} option.
-
-The server will make requests on the world-wide web, for instance to
-download client manifests. The requests can be redirected with XML
-Catalog, by setting the @samp{XML_CATALOG_FILES} to a space-separated
-list of URIs (can be @code{file:} URIs). The requests cannot be
-directed to the file system.
-
-@node Configuration for the resource server
-@section Configuration for the resource server
-The reverse proxy sets an identity header to authenticated
-requests. By default, it is @samp{XXX-Agent}, but it can be configured
-with @samp{--header}.
-
-The reverse proxy is configured to contact a backend URI with
-@samp{--backend-uri}. This backend URI should not be directly exposed,
-because a malicious user could set the identity header.
-
-@node Configuration for the identity provider
-@section Configuration for the identity provider
-The identity provider can only handle one user. If you want to handle
-multiple users, it is highly advised to use a different host name for
-each user, in case the server is accessed from a web browser. You can
-set the identity of the user with @samp{--subject}, and the user’s
-password with @samp{--encrypted-password}.
-
-The encrypted password format is defined by the crypt function in the
-C library. For glibc, it looks like this:
-@code{$@var{N}$@var{salt}$@var{hash}}, where @var{N} is the algorithm
-identifier, @var{salt} is the password salt annd @var{hash} is its
-hash.
-
-The server uses a key, which is not the same thing as the TLS
-certificate of the server (remember, the servers don’t support
-TLS). It is in the JWK format. You set its file name with
-@samp{--key-file}. If the key file does not exist, it will be
-generated.
-
-Finally, the public openid configuration requires you to set the JWKS
-URI (@samp{--jwks-uri}), authorization endpoint URI
-(@samp{--authorization-endpoint-uri}) and token endpoint URI
-(@samp{--token-endpoint-uri}). The identity provider will publish the
-full URIs, but will respond to their path, regardless of the host.
-
-@node Configuration for the client service
-@section Configuration for the client service
-The client will serve a stupid page for the redirect URI that will
-only display the authorization code. The redirect URI is set with
-@samp{--redirect-uri}.
-
-The client ID is set with @samp{--client-id}. This is the URI under
-which the client registrationn is served.
-
-Finally, you can set some cosmetic options, but since it can confuse
-the user, they are hidden by default by the identity provider.
-
-@table @samp
-@item --client-name
-set the name of the application.
-@item --client-uri
-set an URI where to find more information about the client.
-@end table
-
-@node The Json Web Token
-@chapter The Json Web Token
-
-The Json Web Token, or @dfn{JWT}, is a terse representation of a pair
-of JSON objects: the @dfn{header}, and the @dfn{payload}. The JWT can
-be @dfn{encoded} as a Json Web Signature (@dfn{JWS}), in which case
-the header is encoded to base64 with the URL alphabet, and without
-padding characters, the payload is also encoded to base64, and the
-concatenation of the encoding of the header, a dot, and the encoding
-of the payload is signed with some cryptography algorithm. In the
-following, we will only be interested by public-key cryptography. The
-concatenation of header, dot, payload, dot and signature in base64 is
-the encoding of the JWT.
-
-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
-@strong{symbols} to values, arrays are vectors. It is unfortunate that
-guile-json has a slightly different representation, where alist keys
-are @emph{strings}, but we hope that in the future SRFI-180 will be
-more closely respected.
-
-@menu
-* The ID token::
-* The access token::
-* The DPoP proof::
-* Generic JWTs::
-@end menu
-
-@node The ID token
-@section The ID token
-
-The ID token is a special JWT that the application keeps for
-itself. It is signed by the identity provider, and contains the
-following claims:
-
-@table @emph
-@item webid
-the URI of the user’s webid;
-@item iss
-the URI of the identity provider (issuer);
-@item sub
-the username (the webid-oidc issuer puts the webid again here, but it
-could be any string);
-@item aud
-the ID of the client application that is intended to receive the ID
-token;
-@item nonce
-some random data to change the signature;
-@item exp
-an UTC time (in seconds) for when the token expires;
-@item iat
-the time when it was issued.
-@end table
-
-There are functions to work with ID tokens in
-@emph{(webid-oidc oidc-id-token)}.
-
-@deffn function id-token? @var{object}
-Check that @var{object} is a decoded ID token.
-@end deffn
-
-The following helper functions convert URIs to the URIs from
-@emph{(web uri)} and times to @emph{(srfi srfi-19)} dates.
-
-@deffn function id-token-webid @var{token}
-@deffnx function id-token-iss @var{token}
-@deffnx function id-token-sub @var{token}
-@deffnx function id-token-aud @var{token}
-@deffnx function id-token-nonce @var{token}
-@deffnx function id-token-exp @var{token}
-@deffnx function id-token-iat @var{token}
-Get the suitable field from the payload of @var{token}.
-@end deffn
-
-ID tokens can be signed and encoded as a string, or decoded.
-
-@deffn function id-token-decode @var{token} @var{[#http-get]}
-Decode @var{token}, as a string, into a decoded token. The signature
-verification will need to fetch the oidc configuration of the claimed
-issuer, and check the signature against the published keys. The
-@code{http-get} optional keyword argument can set a different
-implementation of @code{http-get} from @emph{(web client)}. Return
-@code{#f} if it failed, or the decoded token otherwise.
-@end deffn
-
-@deffn function id-token-encode @var{token} @var{key}
-Encode @var{token} and sign it with the issuer’s @var{key}.
-@end deffn
-
-@deffn function issue-id-token @var{issuer-key} @var{#alg} @var{#webid} @var{#iss} @var{#sub} @var{#aud} @var{#exp} @var{#iat}
-Create an ID token, and encode it with @var{issuer-key}.
-@end deffn
-
-@node The access token
-@section The access token
-
-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 @emph{(webid-oidc access-token)}.
-
-@deffn function access-token? @var{object}
-Check that @var{object} is a decoded access token.
-@end deffn
-
-There are field getters for the access token:
-
-@deffn function access-token-webid @var{token}
-@deffnx function access-token-iss @var{token}
-@deffnx function access-token-aud @var{token}
-@deffnx function access-token-exp @var{token}
-@deffnx function access-token-iat @var{token}
-@deffnx function access-token-cnf/jkt @var{token}
-@deffnx function access-token-client-id @var{token}
-Get the suitable field from the payload of @var{token}.
-@end deffn
-
-Access tokens can be signed and encoded as a string, or decoded.
-
-@deffn function access-token-decode @var{token} @var{[#http-get]}
-Decode @var{token}, as a string, into a decoded token. As with the ID
-token, the signature verification will need to fetch the oidc
-configuration of the claimed issuer, and check the signature against
-the published keys. The @code{http-get} optional keyword argument can
-set a different implementation of @code{http-get} from
-@emph{(web client)}, for instance to re-use the what has been obtained
-by the ID token validation. Return @code{#f} if it failed, or the
-decoded token otherwise.
-@end deffn
-
-@deffn function access-token-encode @var{token} @var{key}
-Encode @var{token} and sign it with the issuer’s @var{key}.
-@end deffn
-
-@deffn function issue-access-token @var{issuer-key} @var{#alg} @var{#webid} @var{#iss} @var{#exp} @var{#iat} @var{[#client-key} @var{|} @var{#cnf/jkt]} @var{#client-id}
-Create an access token, and encode it with @var{issuer-key}. You can
-either set the @code{#:cnf/jkt} keyword argument with the fingerprint
-of the client key, or set @code{#:client-key} directly, in which case
-the fingerprint will be computed for you.
-@end deffn
-
-@node The DPoP proof
-@section The DPoP proof
-
-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.
-
-@deffn function dpop-proof? @var{proof}
-Check that the @var{proof} is a decoded DPoP proof. The validity of
-the proof is not checked by this function.
-@end deffn
-
-@deffn function dpop-proof-alg @var{proof}
-@deffnx function dpop-proof-jwk @var{proof}
-@deffnx function dpop-proof-jti @var{proof}
-@deffnx function dpop-proof-htm @var{proof}
-@deffnx function dpop-proof-htu @var{proof}
-@deffnx function dpop-proof-iat @var{proof}
-@deffnx function dpop-proof-ath @var{proof}
-Get the corresponding field of the proof.
-@end deffn
-
-@deffn function dpop-proof-decode @var{current-time} @var{jti-list} @var{method} @var{uri} @var{str} @var{cnf/check} @var{[#:access-token]}
-Check and decode a DPoP proof encoded as @var{str}.
-
-The @var{current-time} is passed as a date, time or number (of
-seconds).
-
-In order to prevent replay attacks, each proof has a unique random
-string that is remembered in @var{jti-list} until its expiration date
-is reached. See the @code{make-jti-list} function.
-
-The proof is limited to the scope of one @var{uri} and one
-@var{method} (@code{'GET}, @code{'POST} and so on).
-
-The key that is used to sign the proof should be confirmed by the
-identity provider. To this end, the @var{cnf/check} function is called
-with the fingerprint of the key. The function should check that the
-fingerprint is OK (return a boolean).
-
-Finally, when the DPoP proof is tied to an access token (so, for all
-uses except requesting an access token or a refresh token), it must be
-bound to an @var{access-token}.
-@end deffn
-
-@deffn function make-jti-list
-This function in @emph{(webid-oidc jti-list)} creates an in-memory,
-async-safe, thread-safe cache for the proof IDs.
-@end deffn
-
-@deffn function dpop-proof-encode @var{proof} @var{key}
-Encode the proof and sign it with @var{key}. To generate valid proofs,
-@var{key} should be the private key corresponding to the @code{jwk}
-field of the proof.
-@end deffn
-
-@deffn function issue-dpop-proof @var{client-key} @var{#alg} @var{#htm} @var{#htu} @var{#iat} {[#:@var{access-token}=#f]}
-Create a proof, sign it and encode it with
-@var{client-key}. @var{client-key} should contain both the private and
-public key, because the public part is written in the proof and the
-private part is used to sign it. For most uses, the DPoP proof should
-be encoded for a specific access token. Only token requests should
-omit the @samp{access-token} field.
-@end deffn
-
-@node Generic JWTs
-@section Generic JWTs
-
-You can parse generic JWTs signed with JWS with the following
-functions from @emph{(webid-oidc jws)}.
-
-@deffn function jws? @var{jwt}
-Check that @var{jwt} is a decoded JWT signed with JWS.
-@end deffn
-
-@deffn function jws-alg @var{jwt}
-Get the algorithm used to sign @var{jwt}.
-@end deffn
-
-@deffn function jws-decode @var{str} @var{lookup-keys}
-Check and decode a JWT signed with JWS and encoded as @var{str}.
-
-Since the decoding and signature verification happen at the same time
-(for user friendliness), the @var{lookup-keys} function is used. It is
-passed as arguments the decoded JWT (but the signature is not checked
-yet), and it should return a public key, a public key set or a list of
-public keys. If the key lookup failed, this function should raise an
-exception.
-@end deffn
-
-@deffn function jws-encode @var{jwt} @var{key}
-Encode the JWT and sign it with @var{key}.
-@end deffn
-
-@node Caching on server side
-@chapter Caching on server side
-
-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 @emph{XDG_CACHE_HOME}. Each store has a 5% chance of
-triggering a cleanup of the cache. When a cleanup occurs, each cached
-response has a 5% chance of being dropped, including responses that
-are indicated as valid. This way, a malicious cache response that has
-a maliciously long validity will not stay too long in the cache. A log
-line will indicate which items are dropped.
-
-The @emph{(webid-oidc cache)} module exports two functions to deal
-with the cache.
-
-@deffn function clean-cache @var{[#percents]} @var{[#dir]}
-Drop @var{percents}% of the cache right now, in @var{dir} (defaults to
-some place within @emph{XDG_CACHE_HOME}).
-@end deffn
-
-@deffn function with-cache @var{[#current-time]} @var{[#http-get]} @var{[#dir]}
-Return a function acting as @emph{http-get} from @emph{(web client)}
-(takes an URI as the first parameter, and an optional @var{#:headers}
-set, and returns 2 values, the response and its body).
-
-The cache will be read and written in @var{dir} (defaults to some
-place within @emph{XDG_CACHE_HOME}), and the @var{current-time} number
-of seconds, SRFI-19 time or date, or time-returning thunk will be used
-to check for the validity of responses.
-
-The back-end function, @var{http-get}, defaults to that of
-@emph{(web client)}.
-@end deffn
-
-@node Content negociation
-@chapter Content negociation
-There are a number of different available syntaxes for RDF, some being
-simple and human readable like @emph{turtle}, and others more adapted
-to the JavaScript ecosystem like @emph{json-ld}. To help clients both
-from and outside of the JS ecosystem, the server needs to perform
-@dfn{content negociation}, i.e. convert from one content-type to
-another.
-
-@deffn {function from @code{(webid-oidc serve)}} convert @var{client-accepts} @var{server-name} @var{path} @var{content-type} @var{content}
-Convert the resource representation under @var{path} on
-@var{server-name}, which has a given @var{content-type} and
-@var{content}, to a content-type that the @var{client accepts}.
-
-Return 2 values:
-@enumerate
-@item
-the accepted content-type;
-@item
-the content in the given content-type.
-@end enumerate
-
-Currently, the only conversions are from and to @emph{Turtle} and
-@emph{N-Quads}.
-@end deffn
-
-@node Running an Identity Provider
-@chapter Running an Identity Provider
-
-This project is packaged with a barebones identity provider. It has an
-authorization endpoint and a token endpoint (and it serves its public
-keys), but it is only intended for one specific person.
-
-You can start it by invoking the @code{webid-oidc} program with the
-@code{issuer} command, with the following options:
-
-@table @asis
-@item @code{-h}, or @code{--help}
-prints a summary of options and exit.
-@item @code{-v}, or @code{--version}
-prints the version of the program and exits.
-@item @code{-n @var{URI}}, or @code{--server-name=@var{URI}}
-sets the global server name of the identity provider. It should have
-an empty path.
-@item @code{-k @var{FILE.jwk}}, or @code{--key-file=@var{FILE.jwk}}
-sets the file name where to read or generate a key for the identity
-provider. This file should be JSON, containing the representation of a
-JWK key pair.
-@item @code{-s @var{WEBID}}, or @code{--subject=@var{WEBID}}
-sets the webid of the only user of the identity provider. This is an
-URI, pointing to a RDF node corresponding to the user’s profile.
-@item @code{-w @var{PASSWORD}}, or @code{--password=@var{PASSWORD}}
-sets the password that the user must enter to authorize an
-application.
-@item @code{-j @var{URI}}, or @code{--jwks-uri=@var{URI}}
-tells the server that requests to @var{URI} should be responded with
-the public key used to sign the tokens.
-@item @code{-a @var{URI}}, or @code{--authorization-endpoint-uri=@var{URI}}
-tells the server that requests to @var{URI} should be treated as
-authorization requests.
-@item @code{-t @var{URI}}, or @code{--token-endpoint-uri=@var{URI}}
-tells the server that requests to @var{URI} should be treated as token
-negociation requests.
-@item @code{-p @var{PORT}}, or @code{--port=@var{PORT}}
-change the port number used by the server. By default, it is set to
-8080.
-@item @code{-l @var{FILE.log}}, or @code{--log-file=@var{FILE.log}}
-let the server dump all its output to @var{FILE.log}. Since I don’t
-know how to deal with syslog, this is the only way to keep logs with a
-shepherd service.
-@item @code{-e @var{FILE.err}}, or @code{--error-file=@var{FILE.err}}
-let the server dump all its errors to @var{FILE.err}.
-@end table
-
-The program is sensitive to the environment variables. The most
-important one is @emph{LANG}, which influences how the program is
-internationalized to the server administrator (the pages served to the
-user use the user agent’s locale). This changes the long form of the
-options, and the language in the log files.
-
-The @emph{XDG_DATA_HOME} should point to some place where the program
-will store refresh tokens, under the @code{webid-oidc} directory. For
-a system service, you might want to define that environment to
-@code{/var/lib}, for instance.
-
-The @emph{XDG_CACHE_HOME} should point to a directory where to store
-the seed of the random number generator (under a @code{webid-oidc}
-directory, again). Changing the seed only happens when a program
-starts to require the random number generator. You can safely delete
-this directory, but you need to restart the program to actually change
-the seed.
-
-@node Running a Resource Server
-@chapter Running a Resource Server
-
-@menu
-* Running webid-oidc reverse-proxy::
-* The authenticator::
-* The full server::
-* Resources stored on the server::
-@end menu
-
-A Solid server is the server that manages your data. It needs to check
-that the proofs of possession are correct, and the possessed key is
-signed by the identity provider.
-
-@node Running webid-oidc reverse-proxy
-@section Running webid-oidc reverse-proxy
-
-The @code{webid-oidc} program comes with a reverse proxy command,
-aptly named @code{reverse-proxy}, to listen to an interface, take
-requests, authenticate them, and pass them to a backend with an
-additional header containing the webid of the agent, if authenticated.
-
-The reverse proxy is invoked with the following arguments:
-
-@table @asis
-@item @code{-p}@var{PORT}, @code{--port=}@var{PORT}
-the port on which the reverse proxy listens;
-@item @code{-n}@var{URI}, @code{--server-name=}@var{URI}
-the public name of the server;
-@item @code{-b}@var{URI}, @code{--backend-uri=}@var{URI}
-the address of the backend;
-@item @code{-H}@var{HEADER}, @code{--header=}@var{HEADER}
-replace the name of the header that will contain the webid of the
-user. Defaults to @code{XXX-Agent}. Please note that this value should
-be ASCII, otherwise it’s not guaranteed that the reverse proxy will
-drop other capitalizations of the header in malicious requests;
-@item @code{-l @var{FILE.log}}, or @code{--log-file=@var{FILE.log}}
-let the server dump all its output to @var{FILE.log}. See the identity
-provider comment;
-@item @code{-e @var{FILE.err}}, or @code{--error-file=@var{FILE.err}}
-let the server dump all its errors to @var{FILE.err}.
-@end table
-
-You can localize the interface by setting the @var{LANG} environment
-variable.
-
-@node The authenticator
-@section The authenticator
-
-In @emph{(webid-oidc resource-server)}, the following function gives a
-simple API for a web server:
-
-@deffn function make-authenticator @var{jti-list} @var{[#server-uri]} @var{[#current-time]} @var{[#http-get]}
-Create an authenticator, i.e. a function that takes a request and
-request body and returns the webid of the authenticated user, or
-@code{#f} if it is not authenticated.
-
-To prevent replay attacks, each request is signed by the client with a
-different unique padding value. If such a value has already been seen,
-then the request must fail.
-
-The authenticator expects the client to demonstrate the possession of
-a key that the identity provider knows. So the client creates a DPoP
-proof, targetted to a specific URI. In order to check that the URI is
-correct, the authenticator needs the public URI of the service.
-
-The JTIs are checked within a small time frame. By default, the system
-time will be used. Otherwise, you can customize the
-@code{current-time} optional keyword argument, to pass a thunk
-returning a time from @emph{(srfi srfi-19)}.
-
-You may want to customize the @var{http-get} optional keyword argument
-to pass a function to replace @code{http-get} from @emph{(http
-client)}. This function takes an URI and optional @code{#:headers}
-arguments, makes the request, and return two values: the response, and
-the response body.
-
-This function, in @emph{(webid-oidc resource-server)}, returns a web
-request handler, taking the request and request body, and returning
-the subject of the access token. If an error happens, it is thrown;
-the function always returns a valid URI.
-@end deffn
-
-@node The full server
-@section The full server
-
-@deffn {function from @emph{(webid-oidc resource-server)}} make-server @var{[#:server-uri]} @var{[#:owner]} @var{[#:authenticator]} @var{[#:current-time]} @var{[#:http-get]}
-Return a server handler, a function taking 2 values, a request and a
-request body, and returning 2 values, the response and response body.
-
-The optional @var{[#:authenticator]} argument defaults to the
-webid-oidc authenticator, @var{[#:current-time]} defaults to a thunk
-returning the system time and @var{[#:http-get]} to the web client
-from @emph{(web client)}.
-@end deffn
-
-@node Resources stored on the server
-@section Resources stored on the server
-
-To store and serve resources, the server has two distinct
-mechanisms. A @dfn{content} is a read-only possible value for a
-resource, indexed by etags, and a @dfn{path} is a mutable value that
-indicates the etag of the resource, and of the auxiliary resources
-(description and ACL). With this separation, it is possible to
-atomically delete a resource and all associated auxiliary resources,
-by unlinking the corresponding @emph{path}. It is also possible to
-mutate separately the ACL and the resource itself without writing a
-copy for both.
-
-The @emph{content} API is contained in the
-@code{(webid-oidc server resource content)} module.
-
-@deffn function with-session @var{f} [@var{#:dir}]
-Call @var{f} with 5 arguments:
-@itemize
-@item
-a function to get the content-type of a given etag;
-@item
-a function to list the paths contained within the resource;
-@item
-a function to load the content of a given etag;
-@item
-a function to create a new content;
-@item
-a function to remove a content from the file system. It is still
-possible to query it with the first 3 functions, but new sessions will
-not see it.
-@end itemize
-
-Since the contents are read-only, it is possible to cache the value of
-the content in memory. This is why @var{f} should run within a session
-with memoization.
-
-Resources only store @emph{static} content, because the membership
-triples for containers is considered dynamic and not included in the
-representation.
-
-The first 3 functions as well as the last one are called with an etag,
-and the function to create a content is called with the content-type,
-list of contained paths, and (static) content.
-
-By default, the contents are stored within @var{XDG_DATA_HOME}, but it
-can be overriden by @var{#:dir}.
-@end deffn
-
-The @emph{path} API is defined in
-@code{(webid-oidc server resource path)}.
-
-@deffn function read-path @var{path}
-Read the resource at @var{path}, and return 2 values:
-@enumerate
-@item
-the ETag of the main resource;
-@item
-an alist where keys are auxiliary resource type URIs (the type is from
-@code{(web uri)}), and the values are ETags of the corresponding
-resource.
-@end enumerate
-
-If the resource is not found, raise an exception with type
-@code{&path-not-found}, and maybe @code{&uri-slash-semantics-error} if
-a resource with a different ending-in-slash exists.
-
-This function is safe to call when the path is being modified, either
-by another thread, process or else, as the returned values will always
-be consistent. However, once the function returns, an updating process
-may have deleted the returned ETags. If this is the case, then you
-must call this function again to read the updated path.
-@end deffn
-
-@deffn function update-path @var{path} @var{f} @var{content-type} @var{contained} @var{static-content} @var{create} @var{delete} [@var{#:create-intermediate-containers?}=@code{#f}]
-Read @var{path}, call @var{f} with two values: the ETag and the
-auxiliary ETags (as returned by @var{read-path}), and update the path
-accordingly. If @var{path} does not exist, then the first argument is
-@code{#f} and the second one is the empty list.
-
-If @var{f} returns @code{#f}, then the resource is deleted.
-
-If @var{f} returns an ETag as the first returned value and an alist of
-auxiliary resource ETags as the second value, then the resource is
-updated.
-
-The last functions are from the content API. Since creating or
-deleting children requires updating the parent, we need them.
-
-Some operations should create the intermediate containers for a given
-path, this is the case for the @code{PUT} HTTP verb. For @code{POST},
-the parent should exist. The @var{#:create-intermediate-containers?}
-switch lets you change the behavior. In any case, it is an error to
-delete a non-empty container.
-
-The update is atomic, meaning that at any point in time the file is
-fully written out. Concurrent access to the same resource is performed
-by locking the lock file named @var{X}/.lock, where @var{X} is the
-first character of the base64-url sha-256 hash of the
-path. @strong{The lock file is not meant to be removed} when the
-resource is unlocked. It should be locked with @code{flock}
-instead. @strong{Like other forms of lock-based synchronization, this
-function is not composable}. This means that you cannot call this
-function within @var{f}, otherwise a deadlock may ensue.
-
-If the resource is created or deleted, then the parent resource is
-updated as well. To avoid deadlocks with other processes, please
-follow the following rules: lock the path, then lock the parent path,
-then update the parent, then unlock the parent, and finally unlock the
-child path.
-@end deffn
-
-The Web Access Control specification defines an RDF vocabulary to
-check whether a given user is allowed to perform some operations. The
-@code{(webid-oidc server resource wac)} helps you do that.
-
-@deffn function wac-get-modes @var{server-name} @var{path} @var{user} @var{[#:http-get]}
-Return the list of modes that are allowed for @var{user} accessing
-@var{path}. The @var{server-name} URI is required to find the relevant
-triples in the ACL. If @var{user} is unauthenticated, pass @code{#f}.
-
-Please note that in any case, the data owner should have all rights
-whatsoever, bypassing WAC. Otherwise, it is possible to steal control
-away from the data owner.
-@end deffn
-
-@deffn function check-acl-can-read @var{server-name} @var{path} @var{owner} @var{user} @var{[#:http-get]}
-@deffnx function check-acl-can-write @var{server-name} @var{path} @var{owner} @var{user} @var{[#:http-get]}
-@deffnx function check-acl-can-append @var{server-name} @var{path} @var{owner} @var{user} @var{[#:http-get]}
-@deffnx function check-acl-can-control @var{server-name} @var{path} @var{owner} @var{user} @var{[#:http-get]}
-Assert that the resource at @var{path} on @var{server-name} is owned
-by @var{owner}, and check that @var{user} has the proper
-authorization. Otherwise, raise an exception of type
-@code{&forbidden}.
-@end deffn
-
-@node Running a client
-@chapter Running a client
-
-To run a client, you need to proceed in two steps. First, acquire an
-OIDC ID token and an access token from the identity provider, and then
-present the access token and a proof of possession of the linked key
-in each request, in a DPoP HTTP header.
-
-The first operation is performed by the @emph{(webid-oidc client)}
-module.
-
-@deffn function authorize @var{host/webid} @var{#client-id} @var{#redirect-uri} @var{[#state]} @var{[#http-get]}
-The user enters a valid webid or a host name, and then this function
-will query it (with the @var{http-get} parameter, by default the web
-client from @emph{(web client)}) to determine the authorization
-endpoint. The function will return an alist of authorization URIs,
-indexed by approved identity provider URIs, that the user should
-browse with a traditional web browser.
-
-Each application should have its own webid, or in that case
-@var{client-id}, that can be dereferenced by the identity provider.
-
-Once the user has given authorization, the user’s agent will be
-redirected to @var{redirect-uri}, with the authorization code as a GET
-parameter. It is possible to pass a @var{state}, but this is optional.
-@end deffn
-
-Once the client gets the authorization code, it is necessary to create
-an access token and ID token.
-
-@deffn function token @var{host} @var{client-key} @var{[#authorization-code]} @var{[#refresh-token]} @var{[#http-get]} @var{[#http-post]} @var{[#current-time]}
-Trade an @var{authorization-code}, or a @var{refresh-token}, for an ID
-token and an access token bound to the @var{client-key} issued by
-@var{host}, the identity provider.
-
-You can override the HTTP client used (@var{http-get} and
-@var{http-post}), and how to compute the time (@var{current-time}).
-@end deffn
-
-In an application, you would have a list of profiles in XDG_DATA_HOME,
-consisting of triples (webid, issuer, refresh token).
-
-@deffn function list-profiles @var{[#dir]}
-Read the list of available profiles. Returns a list of triples, webid,
-issuer, reresh token.
-
-By default, this function will look for the profiles file in
-@var{XDG_DATA_HOME}. You can bypass it by providing the @var{#dir}
-optional keyword argument.
-@end deffn
-
-@deffn function setup @var{get-host/webid} @var{choose-provider} @var{browse-authorization-uri} @var{#client-id} @var{#redirect-uri} @var{[#dir]} @var{[#http-get]} @var{[#http-post]} @var{[#current-time]}
-Negociate a refresh token, and save it. The function returns 3 values:
-the decoded ID token pyload, the encoded access token and the key
-pair.
-
-The @var{get-host/webid} thunk should ask the user’s webid or identity
-provider, and return it. @var{choose-provider} is called with a list
-of possible identity providers as host names (strings), and the user
-should choose one. The chosen one is returned. Finally,
-@var{browse-authorization-uri} should ask or let the user browse an
-URI as its argument, and return the authorization code taken from the
-redirect URI.
-
-The refresh token is saved to disk, as a profile, in
-XDG_DATA_HOME. Pass the optional @var{#dir} keyword argument to
-override the location.
-
-You need to set @var{client-id} to the public webid of the app, and
-@var{redirect-uri} to one of the approved redirection URIs for the
-application ID.
-@end deffn
-
-@deffn function login @var{webid} @var{issuer} @var{refresh-token} @var{key} @var{[#dir]} @var{[#http-get]} @var{[#http-post]} @var{[#current-time]}
-If you have already a known profile, you can use it to automatically
-log in. This function might update the refresh token if it changed, so
-you can again set @var{#dir}. Please note that the @var{refresh-token}
-is bound to the client @var{key} on server side, so you must always
-use the same @var{key}.
-@end deffn
-
-@deffn function refresh @var{id-token} @var{key} @var{[#dir]} @var{[#http-get]} @var{[#http-post]} @var{[#current-time]}
-If you have an ID token bound to a known profile, this helper function
-will look up the associated refresh token and log in.
-@end deffn
-
-@deffn function make-client @var{id-token} @var{access-token} @var{key} @var{[#dir]} @var{[#http-get]} @var{[#http-post]} @var{[#http-request]} @var{[#current-time]}
-Return a replacement of @code{http-request} from @emph{(web client)},
-that automatically signs requests and refresh the tokens when needed.
-
-@var{#http-get} and @var{#http-post} are only used to refresh the
-tokens, while @var{#http-request} is used as a back-end for the
-requests.
-
-@var{#current-time} is set to a thunk that returns the time. It is
-used to issue DPoP proofs.
-@end deffn
-
-An example application is provided as the
-@code{webid-oidc-example-app} program. It demonstrates how
-authentication is done. It should help you understand how webid-oidc
-works.
-
-The identity provider needs to call the application on the web. So,
-your client should have a public endpoint on the web.
-
-@deffn function serve-application @var{id} @var{redirect-uri} @var{[#client-name]} @var{[#client-uri]}
-Return a handler for web requests to serve the application manifest
-and the redirection to transmit the authorization code. You should set
-the @var{client-name} to your application name and @var{client-uri} to
-point to where to a presentation of your application.
-@end deffn
-
-The @code{webid-oidc} @code{client-service} command can run a server
-to serve these resources. It is invoked with the following options:
-
-@table @asis
-@item @code{-h}, or @code{--help}
-prints a summary of the options and exit.
-@item @code{-v}, or @code{--version}
-prints the version of the program and exits.
-@item @code{-c @var{URI}}, or @code{--client-id=@var{URI}}
-sets the global identitifier of the application, which is dereferenced
-to a semantic resource.
-@item @code{-r @var{URI}}, or @code{--redirect-uri=@var{URI}}
-sets the redirection URI.
-@item @code{-C @var{NAME}}, or @code{--client-name=@var{NAME}}
-sets the name of your application, so that it is shown when the user
-gets an authorization. The webid-oidc issuer program that comes with
-this package does not display it, because it could be dishonest, but
-other implementations might.
-@item @code{-u @var{URI}}, or @code{--client-uri=@var{URI}}
-sets an URI for the identity provider to learn more about your app.
-@item @code{-p @var{PORT}}, or @code{--port=@var{PORT}}
-change the port number used by the server. By default, it is set to
-8080.
-@item @code{-l @var{FILE.log}}, or @code{--log-file=@var{FILE.log}}
-let the server dump all its output to @var{FILE.log}.
-@item @code{-e @var{FILE.err}}, or @code{--error-file=@var{FILE.err}}
-let the server dump all its errors to @var{FILE.err}.
-@end table
-
-The command is sensitive to the environment variable @emph{LANG},
-which influences how the program is internationalized to the server
-administrator. This changes the long form of the options, and the
-language in the log files.
-
-@node Exceptional conditions
-@chapter Exceptional conditions
-
-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
-@code{(webid-oidc errors)}.
-
-@deffn function error->str @var{error} @var{[#depth]}
-Return a string explaining the @var{error}. You can limit the
-@var{depth} of the explanation as an integer.
-@end deffn
-
-@menu
-* Invalid data format::
-* Invalid JWT::
-* Cannot fetch data on the web::
-* Other errors in the protocol or from a reasonable implementation::
-* Server-side errors::
-@end menu
-
-@node Invalid data format
-@section Invalid data format
-There are a few JSON objects with required fields. This exceptions
-usually occur as the cause of a higher-level exception.
-
-@deftp {exception type} &not-base64 @var{value} @var{cause}
-This exception is raised when the base64 decoding function
-failed. @var{value} is the incorrect input, and @var{cause} is a
-low-level error.
-@end deftp
-
-@deftp {exception type} &not-json @var{value} @var{cause}
-Cannot decode @var{value} to a JSON object.
-@end deftp
-
-@deftp {exception type} &not-turtle @var{value} @var{cause}
-Cannot decode @var{value} to a RDF graph.
-@end deftp
-
-@deftp {exception type} &incorrect-webid-field @var{value}
-The @var{value} of the webid field in the JWT is missing (if
-@code{#f}), or not an acceptable value.
-@end deftp
-
-@deftp {exception type} &incorrect-iss-field @var{value}
-The @var{value} of the iss field is incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-aud-field @var{value}
-The @var{value} of the aud field is incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-iat-field @var{value}
-The @var{value} of the iat field is incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-exp-field @var{value}
-The @var{value} of the exp field is incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-cnf/jkt-field @var{value}
-The @var{value} of the cnf/jkt field is incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-client-id-field @var{value}
-The @var{value} of the client-id field is incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-typ-field @var{value}
-The @var{value} of the typ field in the DPoP proof header is
-incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-jwk-field @var{value} @var{cause}
-The @var{value} of the jwk field in the DPoP proof header is
-incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-jti-field @var{value}
-The @var{value} of the jti field in the DPoP proof is incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-htm-field @var{value}
-The @var{value} of the htm field in the DPoP proof is incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-htu-field @var{value}
-The @var{value} of the htu field in the DPoP proof is incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-ath-field @var{value}
-The @var{value} of the ath field is not the hash of the access token.
-@end deftp
-
-@deftp {exception type} &incorrect-redirect-uris-field @var{value}
-The @var{value} of the redirect-uris field of a client manifest is
-incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-typ-field @var{value}
-The @var{value} of the typ field in the DPoP proof header is
-incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-sub-field @var{value}
-The @var{value} of the sub field is incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-iss-field @var{value}
-The @var{value} of the iss field is incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-nonce-field @var{value}
-The @var{value} of the nonce field in the DPoP proof is incorrect.
-@end deftp
-
-@deftp {exception type} &incorrect-htm-field @var{value}
-The @var{value} of the htm field in the DPoP proof is incorrect.
-@end deftp
-
-@deftp {exception type} &not-a-client-manifest @var{value} @var{cause}
-The @var{client-manifest} is incorrect.
-@end deftp
-
-@node Invalid JWT
-@section Invalid JWT
-Each JWT type – access token, DPoP proof, ID token, authorization code
-(this is internal to the identity provider) has different validation
-rules, and can fail in different ways.
-
-@deftp {exception type} &unsupported-crv @var{crv}
-The identifier @var{crv} does not identify an elliptic curve.
-@end deftp
-
-@deftp {exception type} &not-a-jwk @var{value} @var{cause}
-@var{value} does not identify a JWK.
-@end deftp
-
-@deftp {exception type} &not-a-public-jwk @var{value} @var{cause}
-@var{value} does not identify a public JWK.
-@end deftp
-
-@deftp {exception type} &not-a-private-jwk @var{value} @var{cause}
-@var{value} does not identify a private JWK.
-@end deftp
-
-@deftp {exception type} &not-a-jwks @var{value} @var{cause}
-@var{value} does not identify a set of public keys.
-@end deftp
-
-@deftp {exception type} &unsupported-alg @var{value}
-@var{value} does not identify a valid hash algorithm.
-@end deftp
-
-@deftp {exception type} &invalid-signature @var{key} @var{payload} @var{signature}
-@var{key} has not signed @var{payload} with @var{signature}.
-@end deftp
-
-@deftp {exception type} &missing-alist-key @var{value} @var{key}
-@var{value} isn’t an alist, or is missing a value with @var{key}.
-@end deftp
-
-@deftp {exception type} &not-a-jws-header @var{value} @var{cause}
-@var{value} does not identify a decoded JWS header.
-@end deftp
-
-@deftp {exception type} &not-a-jws-payload @var{value} @var{cause}
-@var{value} does not identify a decoded JWS payload.
-@end deftp
-
-@deftp {exception type} &not-a-jws @var{value} @var{cause}
-@var{value} does not identify a decoded JWS.
-@end deftp
-
-@deftp {exception type} &not-in-3-parts @var{string} @var{separator}
-@var{string} cannot be split into 3 parts with @var{separator}.
-@end deftp
-
-@deftp {exception type} &no-matching-key @var{candidates} @var{alg} @var{payload} @var{signature}
-No key among @var{candidates} could verify @var{signature} signed with
-@var{alg} for @var{payload}, because the signature mismatched for all
-keys.
-@end deftp
-
-@deftp {exception type} &cannot-decode-jws @var{value} @var{cause}
-The @var{value} string is not an encoding of a valid JWS.
-@end deftp
-
-@deftp {exception type} &cannot-encode-jws @var{jws} @var{key} @var{cause}
-The @var{jws} cannot be signed.
-@end deftp
-
-@deftp {exception type} &not-an-access-token @var{value} @var{cause}
-The @var{value} is not an access token.
-@end deftp
-
-@deftp {exception type} &not-an-access-token-header @var{value} @var{cause}
-The @var{value} is not an access token header.
-@end deftp
-
-@deftp {exception type} &not-an-access-token-payload @var{value} @var{cause}
-The @var{value} is not an access token payload.
-@end deftp
-
-@deftp {exception type} &cannot-decode-access-token @var{value} @var{cause}
-The @var{value} string is not an encoding of a valid access token.
-@end deftp
-
-@deftp {exception type} &cannot-encode-access-token @var{access-token} @var{key} @var{cause}
-The @var{access-token} cannot be signed.
-@end deftp
-
-@deftp {exception type} &not-a-dpop-proof @var{value} @var{cause}
-The @var{value} is not a DPoP proof.
-@end deftp
-
-@deftp {exception type} &not-a-dpop-proof-header @var{value} @var{cause}
-The @var{value} is not a DPoP proof header.
-@end deftp
-
-@deftp {exception type} &not-a-dpop-proof-payload @var{value} @var{cause}
-The @var{value} is not a DPoP proof payload.
-@end deftp
-
-@deftp {exception type} &cannot-decode-dpop-proof @var{value} @var{cause}
-The @var{value} string is not an encoding of a valid DPoP proof.
-@end deftp
-
-@deftp {exception type} &cannot-encode-dpop-proof @var{dpop-proof} @var{key} @var{cause}
-The @var{dpop-proof} cannot be signed.
-@end deftp
-
-@deftp {exception type} &not-an-authorization-code @var{value} @var{cause}
-The @var{value} is not an authorization code.
-@end deftp
-
-@deftp {exception type} &not-an-authorization-code-header @var{value} @var{cause}
-The @var{value} is not an authorization code header.
-@end deftp
-
-@deftp {exception type} &not-an-authorization-code-payload @var{value} @var{cause}
-The @var{value} is not an authorization code payload.
-@end deftp
-
-@deftp {exception type} &cannot-decode-authorization-code @var{value} @var{cause}
-The @var{value} string is not an encoding of a valid authorization
-code.
-@end deftp
-
-@deftp {exception type} &cannot-encode-authorization-code @var{authorization-code} @var{key} @var{cause}
-The @var{authorization-code} cannot be signed.
-@end deftp
-
-@deftp {exception type} &not-an-id-token @var{value} @var{cause}
-The @var{value} is not an ID token.
-@end deftp
-
-@deftp {exception type} &not-an-id-token-header @var{value} @var{cause}
-The @var{value} is not an ID token header.
-@end deftp
-
-@deftp {exception type} &not-an-id-token-payload @var{value} @var{cause}
-The @var{value} is not an ID token payload.
-@end deftp
-
-@deftp {exception type} &cannot-decode-id-token @var{value} @var{cause}
-The @var{value} string is not an encoding of a valid ID token.
-@end deftp
-
-@deftp {exception type} &cannot-encode-id-token @var{id-token} @var{key} @var{cause}
-The @var{id-token} cannot be signed.
-@end deftp
-
-@node Cannot fetch data on the web
-@section Cannot fetch data on the web
-In the client (local and public parts), resource server and identity
-provider, the protocol requires to fetch data on the web.
-
-@deftp {exception type} &request-failed-unexpectedly @var{response-code} @var{response-reason-phrase}
-We expected the request to succeed, but the server sent a non-OK
-@var{response-code}.
-@end deftp
-
-@deftp {exception type} &unexpected-header-value @var{header} @var{value}
-We did not expect the server to respond with @var{header} set to
-@var{value}.
-@end deftp
-
-@deftp {exception type} &unexpected-response @var{response} @var{cause}
-The @var{response} (from @emph{(web response)}) is not appropriate.
-@end deftp
-
-@deftp {exception type} &not-an-oidc-configuration @var{value} @var{cause}
-The @var{value} is not appropriate an OIDC configuration.
-@end deftp
-
-@deftp {exception type} &cannot-fetch-issuer-configuration @var{issuer} @var{cause}
-It is impossible to fetch the configuration of @var{issuer}.
-@end deftp
-
-@deftp {exception type} &cannot-fetch-jwks @var{issuer} @var{uri} @var{cause}
-It is impossible to fetch the keys of @var{issuer} at @var{uri}.
-@end deftp
-
-@deftp {exception type} &cannot-fetch-linked-data @var{uri} @var{cause}
-Could not fetch the graph referenced by @var{uri}.
-@end deftp
-
-@deftp {exception type} &cannot-fetch-client-manifest @var{id} @var{cause}
-Could not fetch a client manifest at @var{id}.
-@end deftp
-
-@node Other errors in the protocol or from a reasonable implementation
-@section Other errors in the protocol or from a reasonable implementation
-The protocol does not rely solely on JWT validation, so these errors
-may happen too.
-
-@deftp {exception type} &dpop-method-mismatch @var{signed} @var{requested}
-The method value @var{signed} in the DPoP proof does not match the
-method that is @var{requested} on the server.
-@end deftp
-
-@deftp {exception type} &dpop-uri-mismatch @var{signed} @var{requested}
-The URI value @var{signed} in the DPoP proof does not match the URI
-that is @var{requested} on the server.
-@end deftp
-
-@deftp {exception type} &dpop-signed-in-future @var{signed} @var{current}
-The proof is @var{signed} for a date which is too much ahead of the
-@var{current} time.
-@end deftp
-
-@deftp {exception type} &dpop-too-old @var{signed} @var{current}
-The proof was @var{signed} at a past date of @var{current}.
-@end deftp
-
-@deftp {exception type} &dpop-unconfirmed-key @var{key} @var{expected} @var{cause}
-The confirmation of @var{key} is not what is @var{expected}, or (if a
-function was passed as @var{cnf/check}) the @var{cause} exception
-occurred while confirming.
-@end deftp
-
-@deftp {exception type} &dpop-invalid-access-token-hash @var{hash} @var{access-token}
-The @var{access-token} passed to the resource server does not match
-the @var{hash} provided in the DPoP proof.
-@end deftp
-
-@deftp {exception type} &jti-found @var{jti} @var{cause}
-The @var{jti} of the proof has already been issued in a recent past.
-@end deftp
-
-@deftp {exception type} &unauthorized-redirection-uri @var{manifest} @var{uri}
-The authorization @var{uri} is not advertised in @var{manifest}.
-@end deftp
-
-@deftp {exception type} &cannot-serve-public-manifest
-You cannot serve the public client manifest.
-@end deftp
-
-@deftp {exception type} &no-client-manifest-registration @var{id}
-The @var{id} client manifest does not have a registration triple in
-its document.
-@end deftp
-
-@deftp {exception type} &inconsistent-client-manifest-id @var{id} @var{advertised-id}
-The client @var{manifest} is being fetched at @var{id}, but it is
-valid for another client @var{advertised-id}.
-@end deftp
-
-@deftp {exception type} &authorization-code-expired @var{exp} @var{current-time}
-The authorization code has expired at @var{exp}, it is now
-@var{current-time}.
-@end deftp
-
-@deftp {exception type} &invalid-refresh-token @var{refresh-token}
-The @var{refresh-token} is unknown to the identity provider.
-@end deftp
-
-@deftp {exception type} &invalid-key-for-refresh-token @var{key} @var{jkt}
-The refresh token was issued for @var{jkt}, but it is used with
-@var{key}.
-@end deftp
-
-@deftp {exception type} &unknown-client-locale @var{web-locale} @var{c-locale}
-The @var{web-locale} of the client, translated to C as @var{c-locale},
-cannot be set. This exception is always continuable; if the handler
-returns, then the page will be served in the english locale.
-@end deftp
-
-@deftp {exception type} &unsupported-grant-type @var{value}
-The token request failed to indicate a @var{value} for the grant type,
-or indicated an unsupported grant type.
-@end deftp
-
-@deftp {exception type} &no-authorization-code
-The token request forgot to put an authorization code.
-@end deftp
-
-@deftp {exception type} &no-refresh-token
-The token request forgot to put a refresh token with the request.
-@end deftp
-
-@deftp {exception type} &unconfirmed-provider @var{subject} @var{provider}
-@var{provider} is not confirmed by @var{subject} as an identity
-provider.
-@end deftp
-
-@deftp {exception type} &no-provider-candidates @var{webid} @var{causes}
-The @var{webid} cannot be certified by any identity providers. The
-@var{causes} alist indicates an error for each candidates.
-@end deftp
-
-@deftp {exception type} &neither-identity-provider-nor-webid @var{uri} @var{why-not-identity-provider} @var{why-not-webid}
-The @var{uri} you passed to get an authorization code is neither an
-identity provider (because @var{why-not-identity-provider}) nor a
-webid (because @var{why-not-webid}).
-@end deftp
-
-@deftp {exception type} &token-request-failed @var{cause}
-The token request failed on the server.
-@end deftp
-
-@deftp {exception type} &profile-not-found @var{webid} @var{iss} @var{dir}
-The @var{webid}, as certified by @var{iss}, cannot be refreshed
-because we don’t have a refresh token stored in @var{dir}.
-@end deftp
-
-@node Server-side errors
-@section Server-side errors
-The resource server implementation may encounter some more exceptional
-conditions.
-
-@deftp {exception type} &path-not-found @var{path}
-There is no registered resource at @var{path}.
-@end deftp
-
-@deftp {exception type} &auxiliary-resource-absent @var{path} @var{kind}
-The auxiliary resource of given @var{kind} is not instanciated on the
-server for the base resource @var{path}.
-@end deftp
-
-@deftp {exception type} &uri-slash-semantics-error @var{path} @var{expected-path}
-While the resource at @var{path} does not exist, the resource at
-@var{expected-path} does, and @var{path} and @var{expected-path}
-differ only by a trailing slash. This exception may be raised along
-with @code{&path-not-found}.
-
-Beware that even if it is true at the time when the exception is
-created, maybe the resource has been created by the time it is
-handled.
-@end deftp
-
-@deftp {exception type} &cannot-delete-root
-There was a request to delete the root storage, which is an error.
-@end deftp
-
-@deftp {exception type} &container-not-empty @var{path}
-There was a request to delete a non-empty container.
-@end deftp
-
-@deftp {exception type} &cannot-fetch-group @var{group-uri} @var{cause}
-The access control could not fetch the group @var{group-uri} (with a
-known @var{cause}). This warning is continuable every time it is
-raised. If the handler returns, then the group will be considered
-empty.
-@end deftp
-
-@deftp {exception type} &incorrect-containment-triples @var{path}
-The client wanted to create or update a resource, and by that it tried
-to change the containment triples at @var{path}.
-@end deftp
-
-@deftp {exception type} &unsupported-media-type @var{content-type}
-The client wanted to create a resource with the given
-@var{content-type}, but it is not accepted, because @var{content-type}
-is not recognized as an RDF content type.
-@end deftp
-
-@deftp {exception type} &path-is-auxiliary @var{path}
-The client wanted to create a resource that targets an auxiliary
-resource, at @var{path}.
-@end deftp
-
-@deftp {exception type} &forbidden @var{path} @var{user} @var{owner} @var{mode}
-The @var{user} wanted to do something under @var{path} requiring
-@var{mode}, but it is not the @var{owner} and it is forbidden by WAC.
-@end deftp
-
-@deftp {exception type} &precondition-failed @var{path} @var{if-match} @var{if-none-match} @var{real-etag}
-The resource under @var{path} has a @var{real-etag} that does not
-match the request headers @var{if-match} and @var{if-none-match}.
-
-If the resource does not exist, @var{real-etag} is set to
-@code{#f}. In this case, an exception of type @code{&path-not-found}
-is also thrown.
-@end deftp
-
-@deftp {exception type} &not-acceptable @var{client-accepts} @var{path} @var{content-type}
-The client wanted a response with a specific set of
-@var{client-accept}ed content-types, but the real @var{content-type}
-of the resource under @var{path} cannot be converted to one of them.
-@end deftp
-@node GNU Free Documentation License
-@appendix GNU Free Documentation License
-
-@include fdl.texi
-
-@node Index
-@unnumbered Index
-
-@printindex cp
-
-@bye