Procedura: Convalidare un utente che ha creato un contenitore
Quando si crea un contenitore in Inoltro fluido di Azure, il token JWT fornito da ITokenProvider per la richiesta di creazione può essere usato una sola volta. Dopo aver creato un contenitore, il client deve generare un nuovo token JWT contenente l'ID documento (che è effettivamente l'ID contenitore) fornito dal servizio in fase di creazione. Se un'applicazione dispone di un servizio di autorizzazione che gestisce il controllo di accesso ai contenitori, deve conoscere chi ha creato un contenitore con un DETERMINATO ID per autorizzare la generazione di un nuovo token JWT per l'accesso a tale contenitore.
Informare un servizio di autorizzazione quando viene creato un contenitore
Un'applicazione può collegarsi al ciclo di vita di creazione del contenitore implementando un metodo public documentPostCreateCallback() nel relativo TokenProvider
. Il nome di questa funzione può generare confusione. È davvero un callback per la creazione di contenitori. Questo callback verrà attivato direttamente dopo la creazione del contenitore, prima che un client richieda il nuovo token JWT necessario per ottenere le autorizzazioni di lettura/scrittura per il contenitore creato.
documentPostCreateCallback()
Riceve due parametri: 1) l'ID del contenitore creato (detto anche "ID documento") e 2) un token JWT firmato dal servizio senza ambiti di autorizzazione. Il servizio di autorizzazione può verificare il token JWT specificato e usare le informazioni nel token JWT per concedere le autorizzazioni utente corrette per il contenitore appena creato.
Creare un endpoint per il callback di creazione del contenitore
Questo esempio seguente è una funzione di Azure basata sull'esempio in Procedura: Scrivere un tokenProvider con una funzione di 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;
Implementare documentPostCreateCallback
Questa implementazione di esempio seguente estende AzureFunctionTokenProvider e usa la libreria axios per effettuare una richiesta HTTP alla funzione di Azure usata per generare token.
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,
},
});
}
}