/* * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef TELODENDRIA_UIA_H #define TELODENDRIA_UIA_H /*** * @Nm Uia * @Nd User Interactive Authentication. * @Dd April 28 2023 * @Xr User Db Cron * * .Nm * takes care of all the logic for performing user interactive * authentication as defined by the Matrix specification. API endpoints * that require authentication via user interactive authentication * build up flows and add any necessary parameters, and pass them all * into * .Fn UiaComplete . * The goal is to make it easy for the numerous API endpoints that * utilize this authentication mechanism to implement it. */ #include #include #include #include /** * An opaque structure that represents a single stage, which consists * of the type and a JSON object that contains implementation-specific * parameters for completing the stage. */ typedef struct UiaStage UiaStage; /** * Build a single stage with the type and a JSON object of parameters * the client may require to complete it. Consult the Matrix * specification for the valid types. */ extern UiaStage * UiaStageBuild(char *, HashMap *); /** * Build a flow that consists only of a dummy stage. This is useful * when an endpoint is required by the specification to use user * interactive authentication, but doesn't want to actually require * the user to do anything. Since the dummy flow is a fairly common * flow, it seemed sensible to have a function for it. Other flows are * built manually by the caller that that wishes to perform user * interactive authentication. */ extern Array * UiaDummyFlow(void); /** * This function should be called periodically to purge old sessions. * Sessions are only valid for a few minutes after their last access. * After that, they should be purged so that the database doesn't fill * up with old session files. This function is specifically designed * to be called via the Cron API. */ extern void UiaCleanup(MatrixHttpHandlerArgs *); /** * Validate an auth object and maintain session state to track the * progress of a client through user interactive authentication flows. * The idea is that an API endpoint will not progress until user * interactive authentication has succeeded. * .Pp * This function does the bulk of the work for user interactive * authentication. It takes many parameters: * .Bl -bullet -offset indent * .It * An array of arrays of stages. Stages should be created with * .Fn UiaStageBuild * and then put into an array to create a flow. Those flows should then * be put into an array and passed as this parameter. It is important * to note here that because of the loose typing of the Array API, it * is very easy to make mistakes here; if you are implementing a new * endpoint that requires user interactive authentication, it is best * to refer to the source code of an existing endpoint to get a better * idea of how it works. * .It * An HTTP server context. This is required to set the response headers * in the even of an error. * .It * The database where user interactive authentication sessions are * persisted. * .It * The JSON request body that contains the client's auth object, which * will be read, parsed, and handled as appropriate. * .It * A pointer to a pointer where a JSON response can be placed if * necessary. If this function encounters a client error, such as a * failure to authenticate, or outstanding stages that have not yet * been completed, it will place a JSON response here that is expected * to be returned to the client. This response will include a * description of all the flows, stages, and the stage parameters. * .It * A valid configuration structure, because a few values are read from * the configuration during certain stages of authentication. * .El * .Pp * This function returns an integer value less than zero if it * experiences an internal failure, such as a failure to allocate * memory memory, or a corrupted database. It returns 0 if the client * has remaining stages to complete, including the current stage if * that one did not complete successfully. In this case, this function * will set the proper response headers and the passed response * pointer, so the caller should immediately return the response to * the client. This function returns 1 if and only if the client has * successfully completed all stages. Only in this latter case shall * the caller proceed with its logic. */ extern int UiaComplete(Array *, HttpServerContext *, Db *, HashMap *, HashMap **, Config *); /** * Free an array of flows, as described above. Even though the caller * constructs this array, it is convenient to free it in its * entirety in a single function call. */ extern void UiaFlowsFree(Array *); #endif