diff options
author | Vivien Kraus <vivien@planete-kraus.eu> | 2021-07-30 11:58:08 +0200 |
---|---|---|
committer | Vivien Kraus <vivien@planete-kraus.eu> | 2021-08-01 15:25:08 +0200 |
commit | ed64c545c4723dc0efdb1265b05d682e11e4c1f6 (patch) | |
tree | 4c4393adc62bff130840c41d9fb137c939f12246 /doc/webid-oidc.texi | |
parent | c6f9d0a4878b2e94e92cc8fce5800fb43185be4d (diff) |
Change the name!
Diffstat (limited to 'doc/webid-oidc.texi')
-rw-r--r-- | doc/webid-oidc.texi | 1495 |
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} ¬-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} ¬-json @var{value} @var{cause} -Cannot decode @var{value} to a JSON object. -@end deftp - -@deftp {exception type} ¬-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} ¬-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} ¬-a-jwk @var{value} @var{cause} -@var{value} does not identify a JWK. -@end deftp - -@deftp {exception type} ¬-a-public-jwk @var{value} @var{cause} -@var{value} does not identify a public JWK. -@end deftp - -@deftp {exception type} ¬-a-private-jwk @var{value} @var{cause} -@var{value} does not identify a private JWK. -@end deftp - -@deftp {exception type} ¬-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} ¬-a-jws-header @var{value} @var{cause} -@var{value} does not identify a decoded JWS header. -@end deftp - -@deftp {exception type} ¬-a-jws-payload @var{value} @var{cause} -@var{value} does not identify a decoded JWS payload. -@end deftp - -@deftp {exception type} ¬-a-jws @var{value} @var{cause} -@var{value} does not identify a decoded JWS. -@end deftp - -@deftp {exception type} ¬-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} ¬-an-access-token @var{value} @var{cause} -The @var{value} is not an access token. -@end deftp - -@deftp {exception type} ¬-an-access-token-header @var{value} @var{cause} -The @var{value} is not an access token header. -@end deftp - -@deftp {exception type} ¬-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} ¬-a-dpop-proof @var{value} @var{cause} -The @var{value} is not a DPoP proof. -@end deftp - -@deftp {exception type} ¬-a-dpop-proof-header @var{value} @var{cause} -The @var{value} is not a DPoP proof header. -@end deftp - -@deftp {exception type} ¬-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} ¬-an-authorization-code @var{value} @var{cause} -The @var{value} is not an authorization code. -@end deftp - -@deftp {exception type} ¬-an-authorization-code-header @var{value} @var{cause} -The @var{value} is not an authorization code header. -@end deftp - -@deftp {exception type} ¬-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} ¬-an-id-token @var{value} @var{cause} -The @var{value} is not an ID token. -@end deftp - -@deftp {exception type} ¬-an-id-token-header @var{value} @var{cause} -The @var{value} is not an ID token header. -@end deftp - -@deftp {exception type} ¬-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} ¬-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} ¬-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 |