Cómo: Validar un usuario que creó un contenedor

Al crear un contenedor en Azure Fluid Relay, el JWT proporcionado por ITokenProvider para la solicitud de creación solo se puede usar una vez. Después de crear un contenedor, el cliente debe generar un nuevo JWT que contenga el identificador de documento (que es realmente el identificador de contenedor) proporcionado por el servicio en tiempo de creación. Si una aplicación tiene un servicio de autorización que administra el control de acceso de contenedor, debe saber quién creó un contenedor con un identificador determinado para autorizar la generación de un nuevo JWT para el acceso a ese contenedor.

Informar a un servicio de autorización cuando se crea un contenedor

Una aplicación puede asociarse al ciclo de vida de creación de contenedores mediante la implementación de un método public documentPostCreateCallback() en su TokenProvider. (El nombre de esta función puede resultar confuso. Es realmente una devolución de llamada para la creación posterior al contenedor ). Esta devolución de llamada se desencadenará directamente después de crear el contenedor, antes de que un cliente solicite el nuevo JWT que necesita para obtener permisos de lectura y escritura en el contenedor que se creó.

documentPostCreateCallback() Recibe dos parámetros: 1) el identificador del contenedor que se creó (también denominado "id. de documento") y 2) un JWT firmado por el servicio sin ámbitos de permiso. El servicio de autorización puede comprobar el JWT especificado y usar la información del JWT para conceder los permisos de usuario correctos para el contenedor recién creado.

Creación de un punto de conexión para la devolución de llamada de creación de contenedores

El ejemplo siguiente es una función de Azure basada en el ejemplo del artículo procedimientos para escribir un TokenProvider con una función de Azure.

import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { ITokenClaims, IUser } from "@fluidframework/protocol-definitions";
import * as jwt from "jsonwebtoken";

// NOTE: retrieve the key from a secure location.
const key = "myTenantKey";

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
    const token = (req.query.token || (req.body && req.body.token)) as string;
    const documentId = (req.query.documentId || (req.body && req.body.documentId)) as string;

    if (!token) {
        context.res = {
            status: 400,
            body: "No token provided in request",
        };
        return;
    }
    if (!documentId) {
        context.res = {
            status: 400,
            body: "No documentId provided in request",
        };
        return;
    }
    
    const claims = jwt.decode(token) as ITokenClaims;
    if (!claims) {
        context.res = {
            status: 403,
            body: "Missing token claims",
        };
        return;
    }

    const tenantId = claims.tenantId;
    if (!claims) {
        context.res = {
            status: 400,
            body: "No tenantId provided in token claims",
        };
        return;
    }
    if (!key) {
        context.res = {
            status: 404,
            body: `No key found for the provided tenantId: ${tenantId}`,
        };
        return;
    }
    try {
        jwt.verify(token, key);
    } catch (e) {
        if (e instanceof jwt.TokenExpiredError) {
            context.res = {
                status: 401,
                body: `Token is expired`,
            };
            return
        }
        context.res = {
            status: 403,
            body: `Token signed with invalid key`,
        }
        return;
    }

    const user: IUser = claims.user;
    // Pseudo-function: implement according to your needs
    giveUserPermissionsForContainer(documentId, user);

    context.res = {
        status: 200,
        body: "OK",
    };
};

export default httpTrigger;

Implementación de documentPostCreateCallback

En esta implementación de ejemplo siguiente se amplía AzureFunctionTokenProvider y se usa la biblioteca axios para realizar una solicitud HTTP a la función de Azure que se usa para generar tokens.

import { AzureFunctionTokenProvider, AzureMember } from "@fluidframework/azure-client";
import axios from "axios";

/**
 * Token Provider implementation for connecting to an Azure Function endpoint for
 * Azure Fluid Relay token resolution.
 */
export class AzureFunctionTokenProviderWithContainerCreateCallback extends AzureFunctionTokenProvider {
    /**
     * Creates a new instance using configuration parameters.
     * @param azFunctionUrl - URL to Azure Function endpoint
     * @param user - User object
     */
    constructor(
        private readonly authAzFunctionUrl: string,
        azFunctionUrl: string,
        user?: Pick<AzureMember, "userId" | "userName" | "additionalDetails">,
    ) {
        super(azFunctionUrl, user);
    }

    // In this context, a document is another name for container, so you can think of this function
    // as if it were named containerPostCreateCallback.
    public async documentPostCreateCallback?(documentId: string, creationToken: string): Promise<void> {
        await axios.post(this.authAzFunctionUrl, {
            params: {
                documentId,
                token: creationToken,
            },
        });
    }
}

Consulte también