Rayfin

Connections

Give Rayfin functions app-identity tokens for Fabric SQL, OneLake, Fabric REST, Azure AI Foundry, and Azure DevOps.

Changed in 1.36

Use a function connection when server-side code needs to call an external Azure or Fabric resource. In deployed Functions, these external calls use application authentication: Rayfin supplies resource-scoped tokens for the Fabric app identity through ctx.Tokens.

Note

Functions and function connections are generally available in Rayfin 1.36 and are not available in every Fabric region or tenant.

Declare audiences in RayfinContext

Add the resource audience as the second generic parameter of RayfinContext, then read the token from ctx.Tokens:

rayfin/functions/src/function_app.ts
import {
  AudienceType,
  UserDataFunctions,
  type RayfinContext,
} from '@microsoft/fabric-user-data-functions';

export type AppSchema = Record<string, never>;

const udf = new UserDataFunctions();

udf.func(
  'checkFabricAccess',
  async (
    ctx: RayfinContext<AppSchema, AudienceType.Fabric>,
  ): Promise<string> => {
    const token = ctx.Tokens.Fabric;
    return token.length > 0 ? 'ready' : 'missing';
  },
  [],
);

The annotation is the declaration. Keep the third argument to udf.func() as [].

Supported audiences

AudienceType in 1.36.2 contains only these members. Changed in 1.36

AudienceUse for
AudienceType.SqlFabric Lakehouse SQL analytics, Warehouse, SQL Database, Mirrored Database, and Azure SQL.
AudienceType.StorageFabric OneLake files and Azure Blob, Table, or Queue Storage.
AudienceType.FabricMicrosoft Fabric REST APIs.
AudienceType.AzureAIAzure AI Foundry endpoints.
AudienceType.ADOAzure DevOps APIs.

CosmosDB, KeyVault, EventGrid, Kusto, and WorkIQ are not public AudienceType members in 1.36.2. A Power BI semantic model is not reached through function connections; use the fabric-semanticmodel connector instead.

Tokens are typed and bounded

ctx.Tokens exposes only declared audiences:

rayfin/functions/src/function_app.ts
async (
  ctx: RayfinContext<AppSchema, AudienceType.Sql | AudienceType.Storage>,
) => {
  const sqlToken = ctx.Tokens.Sql;
  const storageToken = ctx.Tokens.Storage;
  return { sqlTokenLength: sqlToken.length, storageTokenLength: storageToken.length };
};

A direct read of a declared-but-unminted token throws:

No token available for audience '<Audience>'. Ensure a connection with this audience type is declared.

Declaring an audience does not grant resource permissions. Grant the external resource to the Fabric app identity. For current Fabric apps, that identity is the owner of the Fabric app item.

Rayfin data remains caller-scoped

services.functions.auth.type: application does not make ctx.getDataClient() use the app identity. Rayfin DB access uses the invocation's Rayfin token and preserves the signed-in caller's data permissions.

Code pathIdentity
ctx.getDataClient()Signed-in caller.
ctx.Tokens.Sql, ctx.Tokens.Storage, ctx.Tokens.Fabric, ctx.Tokens.AzureAI, ctx.Tokens.ADOFabric app identity.

Wrap a token for Azure SDK clients

Many Azure SDK clients expect a TokenCredential. Wrap the context token:

rayfin/functions/src/ContextTokenCredential.ts
import type { AccessToken, TokenCredential } from '@azure/identity';

export class ContextTokenCredential implements TokenCredential {
  constructor(private readonly token: string) {}

  async getToken(): Promise<AccessToken> {
    return { token: this.token, expiresOnTimestamp: Date.now() + 3600_000 };
  }
}

Find Fabric resource coordinates

Every connection needs a real endpoint. Resolve Fabric coordinates from the Fabric portal, a Fabric CLI/MCP tool when one is already available, or the Fabric REST API. Do not guess endpoints or use process.env as the primary source for resource coordinates.

You needFabric itemWhere to read it
Lakehouse SQL serverLakehouseproperties.sqlEndpointProperties.connectionString from GET /workspaces/{workspaceId}/lakehouses/{lakehouseId}.
Lakehouse OneLake pathLakehouseproperties.oneLakeFilesPath or properties.oneLakeTablesPath from the same Lakehouse GET.
Warehouse SQL serverWarehouseproperties.connectionString from GET /workspaces/{workspaceId}/warehouses/{warehouseId}.
SQL Database server and databaseSQL Databaseproperties.serverFqdn and properties.databaseName from GET /workspaces/{workspaceId}/sqlDatabases/{sqlDatabaseId}.
Item GUIDAny itemid from GET /workspaces/{workspaceId}/items?type={Type}.

Authoring-time lookup is separate from runtime access. Use your developer credentials to look up coordinates while writing the function; at runtime the deployed function uses ctx.Tokens.<Audience> from the app identity.

Call Fabric SQL

All Fabric SQL resources share the same requirements:

  • Install mssql@^12.6.0 in the functions package. That version pulls a tedious release with the Fabric LOGIN7 fixes.
  • Use encrypt: true, not encrypt: 'strict'.
  • Use azure-active-directory-access-token with ctx.Tokens.Sql.
  • Ask for the actual SQL endpoint and database or item GUID from Fabric. Do not invent endpoints.
ResourceWhat to ask fordatabase value
Lakehouse SQL analyticsSQL analytics endpoint and item GUID from the Fabric portalItem GUID
WarehouseSQL endpoint and item GUID from the Fabric portalItem GUID
SQL DatabaseFull connection string from the Fabric portalDatabase name from the connection string
Mirrored DatabaseSQL analytics endpoint and item GUID from the Fabric portalItem GUID

For Lakehouse, Warehouse, and Mirrored Database connections, pass the Fabric item GUID as database. Multi-item workspaces cannot route the connection reliably without it.

rayfin/functions/src/function_app.ts
import sql from 'mssql';
import {
  AudienceType,
  UserDataFunctions,
  type RayfinContext,
} from '@microsoft/fabric-user-data-functions';

export type AppSchema = Record<string, never>;

const udf = new UserDataFunctions();
const SQL_SERVER = '<endpoint>.datawarehouse.fabric.microsoft.com';
const DATABASE = '<item-guid-or-database-name>';

udf.func(
  'queryWarehouse',
  async (
    ctx: RayfinContext<AppSchema, AudienceType.Sql>,
    query: string,
  ): Promise<Record<string, unknown>[]> => {
    const pool = await sql.connect({
      server: SQL_SERVER,
      database: DATABASE,
      options: { encrypt: true, trustServerCertificate: false },
      authentication: {
        type: 'azure-active-directory-access-token',
        options: { token: ctx.Tokens.Sql },
      },
    });
    const result = await pool.request().query(query);
    await pool.close();
    return result.recordset;
  },
  [],
);

Call OneLake files

Use AudienceType.Storage for OneLake DFS URLs.

For OneLake, ask for the file URL from the Fabric portal: Lakehouse → file → Properties → URL. It has this shape:

https://onelake.dfs.fabric.microsoft.com/<workspaceId>/<itemId>/Files/<path>

A OneLake example:

rayfin/functions/src/function_app.ts
import {
  AudienceType,
  UserDataFunctions,
  type RayfinContext,
} from '@microsoft/fabric-user-data-functions';

export type AppSchema = Record<string, never>;

const udf = new UserDataFunctions();

udf.func(
  'readOneLakeFile',
  async (
    ctx: RayfinContext<AppSchema, AudienceType.Storage>,
    fileUrl: string,
  ): Promise<string> => {
    const response = await fetch(fileUrl, {
      headers: { Authorization: ['Bearer', ctx.Tokens.Storage].join(' ') },
    });
    if (!response.ok) {
      throw new Error(`OneLake read failed: ${response.status}`);
    }
    return await response.text();
  },
  [],
);

Call Fabric REST APIs

Use AudienceType.Fabric for Microsoft Fabric REST APIs.

Grant the app identity access to the workspace, item, or Fabric API you call. Check the specific API because not every Fabric endpoint supports application identities.

rayfin/functions/src/function_app.ts
import {
  AudienceType,
  UserDataFunctions,
  type RayfinContext,
} from '@microsoft/fabric-user-data-functions';

export type AppSchema = Record<string, never>;

const udf = new UserDataFunctions();
const FABRIC_API = 'https://api.fabric.microsoft.com/v1';

udf.func(
  'listWorkspaceItems',
  async (
    ctx: RayfinContext<AppSchema, AudienceType.Fabric>,
    workspaceId: string,
  ): Promise<unknown> => {
    const response = await fetch(`${FABRIC_API}/workspaces/${workspaceId}/items`, {
      headers: { Authorization: ['Bearer', ctx.Tokens.Fabric].join(' ') },
    });
    if (!response.ok) {
      throw new Error(`Fabric API returned ${response.status}`);
    }
    return await response.json();
  },
  [],
);

Call Azure Blob Storage

Use AudienceType.Storage for Azure Blob, Table, or Queue Storage.

Grant the app identity the Azure Storage data role required by your operation, such as Storage Blob Data Reader for listing and reading blobs or Storage Blob Data Contributor for writes. Install SDK packages in the functions package:

cd rayfin/functions
npm install @azure/storage-blob @azure/identity
rayfin/functions/src/function_app.ts
import { BlobServiceClient } from '@azure/storage-blob';
import {
  AudienceType,
  UserDataFunctions,
  type RayfinContext,
} from '@microsoft/fabric-user-data-functions';
import { ContextTokenCredential } from './ContextTokenCredential.js';

export type AppSchema = Record<string, never>;

const udf = new UserDataFunctions();

udf.func(
  'listBlobContainers',
  async (
    ctx: RayfinContext<AppSchema, AudienceType.Storage>,
    accountUrl: string,
  ): Promise<string[]> => {
    const credential = new ContextTokenCredential(ctx.Tokens.Storage);
    const service = new BlobServiceClient(accountUrl, credential);
    const names: string[] = [];
    for await (const container of service.listContainers()) {
      names.push(container.name);
    }
    return names;
  },
  [],
);

Pass an account URL such as https://<account>.blob.core.windows.net.

Call Azure AI Foundry

Use AudienceType.AzureAI for Azure AI Foundry or Azure OpenAI APIs.

Grant the app identity the role required by the Azure AI resource and API. Use the endpoint from Azure AI Foundry or the Azure portal, then send the token as a bearer token. Fill in the path and body for the specific API you call.

rayfin/functions/src/function_app.ts
import {
  AudienceType,
  UserDataFunctions,
  type RayfinContext,
} from '@microsoft/fabric-user-data-functions';

export type AppSchema = Record<string, never>;

const udf = new UserDataFunctions();
const AI_ENDPOINT = 'https://<resource>.services.ai.azure.com';

udf.func(
  'callAzureAi',
  async (
    ctx: RayfinContext<AppSchema, AudienceType.AzureAI>,
    prompt: string,
  ): Promise<unknown> => {
    const response = await fetch(`${AI_ENDPOINT}/<api-path>`, {
      method: 'POST',
      headers: {
        Authorization: 'Bearer ' + ctx.Tokens.AzureAI,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ prompt }),
    });
    if (!response.ok) {
      throw new Error(`Azure AI returned ${response.status}`);
    }
    return await response.json();
  },
  [],
);

Call Azure DevOps

Use AudienceType.ADO for Azure DevOps REST APIs.

Grant the app identity access to the Azure DevOps organization, project, and resource you call. Provide the organization URL, such as https://dev.azure.com/<org>.

rayfin/functions/src/function_app.ts
import {
  AudienceType,
  UserDataFunctions,
  type RayfinContext,
} from '@microsoft/fabric-user-data-functions';

export type AppSchema = Record<string, never>;

const udf = new UserDataFunctions();
const ADO_ORG = 'https://dev.azure.com/<org>';

udf.func(
  'listAdoProjects',
  async (ctx: RayfinContext<AppSchema, AudienceType.ADO>): Promise<unknown> => {
    const response = await fetch(`${ADO_ORG}/_apis/projects?api-version=7.1`, {
      headers: { Authorization: ['Bearer', ctx.Tokens.ADO].join(' ') },
    });
    if (!response.ok) {
      throw new Error(`Azure DevOps returned ${response.status}`);
    }
    return await response.json();
  },
  [],
);

Rules

  • Declare generic audiences in the RayfinContext annotation and read tokens from ctx.Tokens.<Audience>.
  • Keep the third argument to udf.func() as [] in new code.
  • Use real endpoints from Fabric or Azure. Do not use process.env as the primary source for resource coordinates.
  • Never return ctx.Tokens.* values to the frontend.
  • Grant external resource access to the Fabric app identity before testing deployed functions.
  • Install resource SDK packages in the functions package, not the project root.

Migrate from udf.connection() and ctx.getToken()

udf.connection({ audienceType }) and ctx.getToken(audienceType) still work at runtime, but they no longer give the preferred type-safe authoring model. Move the audience into the context annotation and read ctx.Tokens. Deprecated in 1.36

rayfin/functions/src/function_app.ts
// Before
udf.func(
  'before',
  async (ctx: RayfinContext): Promise<string> => {
    return ctx.getToken(AudienceType.Sql);
  },
  [udf.connection({ audienceType: AudienceType.Sql })],
);

// After
udf.func(
  'after',
  async (ctx: RayfinContext<AppSchema, AudienceType.Sql>): Promise<string> => {
    return ctx.Tokens.Sql;
  },
  [],
);

Both halves matter: the annotation registers the binding and narrows ctx.Tokens.

Local token identity

During npx rayfin dev and npx rayfin dev functions apply, external-resource tokens use the account the local Functions host signs in with. Deployed Functions use the application identity. Test deployed permissions even if local debugging works.

PromptAdd an app-identity connection to a Rayfin function
In my Rayfin project, add a function connection to <Fabric SQL, OneLake, Fabric REST, Azure AI Foundry, or Azure DevOps>. Use Rayfin 1.36 style. Declare the audience in the handler's context type, for example `RayfinContext<AppSchema, AudienceType.Sql>`, and read the token from `ctx.Tokens.Sql`. Keep the third argument to `udf.func()` as `[]`. Do not use `ctx.getToken()` or `udf.connection({ audienceType })` in new code. Use real resource endpoints from Fabric or Azure; do not invent URLs. Install resource SDK packages in rayfin/functions/package.json. Explain which identity must be granted access in deployed Functions and how local development differs.
Something wrong on this page?Report an issueEdit this page

On this page