Share via


Nasıl yapılır: Kapsayıcı oluşturan kullanıcıyı doğrulama

Azure Fluid Relay'de bir kapsayıcı oluşturduğunuzda, oluşturma isteği için ITokenProvider tarafından sağlanan JWT yalnızca bir kez kullanılabilir. Kapsayıcı oluşturduktan sonra, istemcinin oluşturma zamanında hizmet tarafından sağlanan belge kimliğini (aslında kapsayıcı kimliğidir) içeren yeni bir JWT oluşturması gerekir. Bir uygulamanın kapsayıcı erişim denetimini yöneten bir yetkilendirme hizmeti varsa, bu kapsayıcıya erişim için yeni bir JWT oluşturulmasını yetkilendirmek için belirli bir kimliğe sahip bir kapsayıcı oluşturduğunu bilmesi gerekir.

Kapsayıcı oluşturulduğunda yetkilendirme hizmetini bilgilendirme

Bir uygulama, içinde bir ortak documentPostCreateCallback() yöntemi uygulayarak kapsayıcı oluşturma yaşam döngüsüne TokenProviderbağlanabilir. (Bu işlevin adı kafa karıştırıcı olabilir. Bu gerçekten kapsayıcı oluşturma sonrası için bir geri çağırmadır.) Bu geri çağırma, bir istemci yeni JWT'yi istemeden önce kapsayıcı oluşturulduktan sonra doğrudan tetiklenir ve oluşturulan kapsayıcıda okuma/yazma izinleri alması gerekir.

documentPostCreateCallback() iki parametre alır: 1) oluşturulan kapsayıcının kimliği ("belge kimliği" olarak da adlandırılır) ve 2) izin kapsamı olmayan hizmet tarafından imzalanan bir JWT. Yetkilendirme hizmeti verilen JWT'yi doğrulayabilir ve JWT'deki bilgileri kullanarak yeni oluşturulan kapsayıcı için doğru kullanıcı izinlerini verebilir.

Kapsayıcı oluşturma geri aramanız için uç nokta oluşturma

Aşağıdaki örnek, Nasıl yapılır: Azure İşlevi ile TokenProvider Yazma'daki örneği temel alan bir Azure İşlevidir.

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;

Uygulama: documentPostCreateCallback

Aşağıdaki örnek uygulama AzureFunctionTokenProvider'ı genişletir ve axios kitaplığını kullanarak belirteç oluşturmak için kullanılan Azure İşlevi'ne http isteğinde bulunur.

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

Ayrıca bkz.