Instrukcje: weryfikowanie użytkownika, który utworzył kontener

Podczas tworzenia kontenera w usłudze Azure Fluid Relay zestaw JWT dostarczony przez dostawcę ITokenProvider dla żądania tworzenia może być używany tylko raz. Po utworzeniu kontenera klient musi wygenerować nowy zestaw JWT zawierający identyfikator dokumentu (który jest naprawdę identyfikatorem kontenera) dostarczonym przez usługę w czasie tworzenia. Jeśli aplikacja ma usługę autoryzacji, która zarządza kontrolą dostępu do kontenerów, musi wiedzieć, kto utworzył kontener o danym identyfikatorze, aby autoryzować generowanie nowego zestawu JWT w celu uzyskania dostępu do tego kontenera.

Informowanie usługi autoryzacji po utworzeniu kontenera

Aplikacja może powiązać cykl życia tworzenia kontenera, implementując metodę public documentPostCreateCallback() w pliku TokenProvider. (Nazwa tej funkcji może być myląca. To naprawdę wywołanie zwrotne do tworzenia kontenera po utworzeniu kontenera ). To wywołanie zwrotne zostanie wyzwolone bezpośrednio po utworzeniu kontenera, zanim klient zażąda nowego zestawu JWT, musi uzyskać uprawnienia odczytu/zapisu do utworzonego kontenera.

Otrzymuje documentPostCreateCallback() dwa parametry: 1) identyfikator utworzonego kontenera (nazywanego również "identyfikatorem dokumentu") i 2) zestaw JWT podpisany przez usługę bez zakresów uprawnień. Usługa autoryzacji może zweryfikować daną JWT i użyć informacji w JWT, aby udzielić odpowiednich uprawnień użytkownika dla nowo utworzonego kontenera.

Tworzenie punktu końcowego dla wywołania zwrotnego tworzenia kontenera

W poniższym przykładzie przedstawiono funkcję platformy Azure opartą na przykładzie w temacie How to: Write a TokenProvider with an Azure Function (Jak napisać tokenProvider za pomocą funkcji platformy 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;

Implementowanie documentPostCreateCallback

Poniższa przykładowa implementacja rozszerza element AzureFunctionTokenProvider i używa biblioteki axios do utworzenia żądania HTTP do funkcji platformy Azure używanej do generowania tokenów.

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,
            },
        });
    }
}

Zobacz też