Skip to content

Files

Latest commit

4613157 · Mar 4, 2022

History

History
367 lines (273 loc) · 14.1 KB

functions-bindings-signalr-service-input.md

File metadata and controls

367 lines (273 loc) · 14.1 KB
title description ms.topic ms.devlang ms.custom ms.date zone_pivot_groups
Azure Functions SignalR Service input binding
Learn to return a SignalR service endpoint URL and access token in Azure Functions.
reference
csharp, java, javascript, python
devx-track-csharp
03/04/2022
programming-languages-set-functions-lang-workers

SignalR Service input binding for Azure Functions

Before a client can connect to Azure SignalR Service, it must retrieve the service endpoint URL and a valid access token. The SignalRConnectionInfo input binding produces the SignalR Service endpoint URL and a valid token that are used to connect to the service. Because the token is time-limited and can be used to authenticate a specific user to a connection, you should not cache the token or share it between clients. An HTTP trigger using this binding can be used by clients to retrieve the connection information.

For more information on how this binding is used to create a "negotiate" function that can be consumed by a SignalR client SDK, see the Azure Functions development and configuration article in the SignalR Service concepts documentation.

For information on setup and configuration details, see the overview.

Example

::: zone pivot="programming-language-csharp"

[!INCLUDE functions-bindings-csharp-intro]

The following example shows a C# function that acquires SignalR connection information using the input binding and returns it over HTTP.

[FunctionName("negotiate")]
public static SignalRConnectionInfo Negotiate(
    [HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req,
    [SignalRConnectionInfo(HubName = "chat")]SignalRConnectionInfo connectionInfo)
{
    return connectionInfo;
}

The following example shows a SignalR trigger that reads a message string from one hub using a SignalR trigger and writes it to a second hub using an output binding. The data required to connect to the output binding is obtained as a MyConnectionInfo object from an input binding defined using a SignalRConnectionInfo attribute.

:::code language="csharp" source="~/azure-functions-dotnet-worker/samples/Extensions/SignalR/SignalRFunction.cs" range="12-31":::

The MyConnectionInfo and MyMessage classes are defined as follows:

:::code language="csharp" source="~/azure-functions-dotnet-worker/samples/Extensions/SignalR/SignalRFunction.cs" range="34-46":::

The following example shows a SignalR connection info input binding in a function.json file and a C# Script function that uses the binding to return the connection information.

Here's binding data in the function.json file:

Example function.json:

{
    "type": "signalRConnectionInfo",
    "name": "connectionInfo",
    "hubName": "chat",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "direction": "in"
}

Here's the C# Script code:

#r "Microsoft.Azure.WebJobs.Extensions.SignalRService"
using Microsoft.Azure.WebJobs.Extensions.SignalRService;

public static SignalRConnectionInfo Run(HttpRequest req, SignalRConnectionInfo connectionInfo)
{
    return connectionInfo;
}

::: zone-end
::: zone pivot="programming-language-javascript,programming-language-python,programming-language-powershell"

The following example shows a SignalR connection info input binding in a function.json file and a function that uses the binding to return the connection information.

Here's binding data for the example in the function.json file:

{
    "type": "signalRConnectionInfo",
    "name": "connectionInfo",
    "hubName": "chat",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "direction": "in"
}

::: zone-end ::: zone pivot="programming-language-javascript"

Here's the JavaScript code:

module.exports = async function (context, req, connectionInfo) {
    context.res.body = connectionInfo;
};

::: zone-end
::: zone pivot="programming-language-powershell"

Complete PowerShell examples are pending. ::: zone-end ::: zone pivot="programming-language-python"

The following example shows a SignalR connection info input binding in a function.json file and a Python function that uses the binding to return the connection information.

Here's the Python code:

def main(req: func.HttpRequest, connectionInfoJson: str) -> func.HttpResponse:
    return func.HttpResponse(
        connectionInfoJson,
        status_code=200,
        headers={
            'Content-type': 'application/json'
        }
    )

::: zone-end ::: zone pivot="programming-language-java"

The following example shows a Java function that acquires SignalR connection information using the input binding and returns it over HTTP.

@FunctionName("negotiate")
public SignalRConnectionInfo negotiate(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> req,
        @SignalRConnectionInfoInput(
            name = "connectionInfo",
            hubName = "chat") SignalRConnectionInfo connectionInfo) {
    return connectionInfo;
}

:::zone-end

Usage

Authenticated tokens

When the function is triggered by an authenticated client, you can add a user ID claim to the generated token. You can easily add authentication to a function app using App Service Authentication.

App Service authentication sets HTTP headers named x-ms-client-principal-id and x-ms-client-principal-name that contain the authenticated user's client principal ID and name, respectively.

::: zone pivot="programming-language-csharp"

You can set the UserId property of the binding to the value from either header using a binding expression: {headers.x-ms-client-principal-id} or {headers.x-ms-client-principal-name}.

[FunctionName("negotiate")]
public static SignalRConnectionInfo Negotiate(
    [HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req, 
    [SignalRConnectionInfo
        (HubName = "chat", UserId = "{headers.x-ms-client-principal-id}")]
        SignalRConnectionInfo connectionInfo)
{
    // connectionInfo contains an access key token with a name identifier claim set to the authenticated user
    return connectionInfo;
}

Sample code not available for isolated process.

You can set the userId property of the binding to the value from either header using a binding expression: {headers.x-ms-client-principal-id} or {headers.x-ms-client-principal-name}.

Example function.json:

{
    "type": "signalRConnectionInfo",
    "name": "connectionInfo",
    "hubName": "chat",
    "userId": "{headers.x-ms-client-principal-id}",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "direction": "in"
}

Here's the C# Script code:

#r "Microsoft.Azure.WebJobs.Extensions.SignalRService"
using Microsoft.Azure.WebJobs.Extensions.SignalRService;

public static SignalRConnectionInfo Run(HttpRequest req, SignalRConnectionInfo connectionInfo)
{
    // connectionInfo contains an access key token with a name identifier
    // claim set to the authenticated user
    return connectionInfo;
}

::: zone-end

::: zone pivot="programming-language-java" SignalR trigger isn't currently supported for Java. ::: zone-end

::: zone pivot="programming-language-javascript,programming-language-python,programming-language-powershell"

You can set the userId property of the binding to the value from either header using a binding expression: {headers.x-ms-client-principal-id} or {headers.x-ms-client-principal-name}.

Here's binding data in the function.json file:

{
    "type": "signalRConnectionInfo",
    "name": "connectionInfo",
    "hubName": "chat",
    "userId": "{headers.x-ms-client-principal-id}",
    "connectionStringSetting": "<name of setting containing SignalR Service connection string>",
    "direction": "in"
}

::: zone-end ::: zone pivot="programming-language-javascript"
Here's the JavaScript code:

module.exports = async function (context, req, connectionInfo) {
    // connectionInfo contains an access key token with a name identifier
    // claim set to the authenticated user
    context.res.body = connectionInfo;
};

::: zone-end
::: zone pivot="programming-language-powershell"

Complete PowerShell examples are pending. ::: zone-end ::: zone pivot="programming-language-python"

Here's the Python code:

def main(req: func.HttpRequest, connectionInfo: str) -> func.HttpResponse:
    # connectionInfo contains an access key token with a name identifier
    # claim set to the authenticated user
    return func.HttpResponse(
        connectionInfo,
        status_code=200,
        headers={
            'Content-type': 'application/json'
        }
    )

::: zone-end ::: zone pivot="programming-language-java"

You can set the userId property of the binding to the value from either header using a binding expression: {headers.x-ms-client-principal-id} or {headers.x-ms-client-principal-name}.

@FunctionName("negotiate")
public SignalRConnectionInfo negotiate(
        @HttpTrigger(
            name = "req",
            methods = { HttpMethod.POST },
            authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> req,
        @SignalRConnectionInfoInput(
            name = "connectionInfo",
            hubName = "chat",
            userId = "{headers.x-ms-client-principal-id}") SignalRConnectionInfo connectionInfo) {
    return connectionInfo;
}

::: zone-end

::: zone pivot="programming-language-csharp"

Attributes

Both in-process and isolated process C# libraries use attribute to define the function. C# script instead uses a function.json configuration file.

The following table explains the properties of the SignalRConnectionInfo attribute:

Attribute property Description
HubName This value must be set to the name of the SignalR hub for which the connection information is generated.
UserId Optional: The value of the user identifier claim to be set in the access key token.
ConnectionStringSetting The name of the app setting that contains the SignalR Service connection string, which defaults to AzureSignalRConnectionString.

The following table explains the properties of the SignalRConnectionInfoInput attribute:

Attribute property Description
HubName This value must be set to the name of the SignalR hub for which the connection information is generated.
UserId Optional: The value of the user identifier claim to be set in the access key token.
ConnectionStringSetting The name of the app setting that contains the SignalR Service connection string, which defaults to AzureSignalRConnectionString.

The following table explains the binding configuration properties that you set in the function.json file.

function.json property Description
type Must be set to signalRConnectionInfo.
direction Must be set to in.
name Variable name used in function code for connection info object.
hubName This value must be set to the name of the SignalR hub for which the connection information is generated.
userId Optional: The value of the user identifier claim to be set in the access key token.
connectionStringSetting The name of the app setting that contains the SignalR Service connection string, which defaults to AzureSignalRConnectionString.

::: zone-end ::: zone pivot="programming-language-java"

Annotations

The following table explains the supported settings for the SignalRConnectionInfoInput annotation.

Setting Description
name Variable name used in function code for connection info object.
hubName This value must be set to the name of the SignalR hub for which the connection information is generated.
userId Optional: The value of the user identifier claim to be set in the access key token.
connectionStringSetting The name of the app setting that contains the SignalR Service connection string, which defaults to AzureSignalRConnectionString.

::: zone-end
::: zone pivot="programming-language-javascript,programming-language-powershell,programming-language-python"

Configuration

The following table explains the binding configuration properties that you set in the function.json file.

function.json property Description
type Must be set to signalRConnectionInfo.
direction Must be set to in.
name Variable name used in function code for connection info object.
hubName This value must be set to the name of the SignalR hub for which the connection information is generated.
userId Optional: The value of the user identifier claim to be set in the access key token.
connectionStringSetting The name of the app setting that contains the SignalR Service connection string, which defaults to AzureSignalRConnectionString.

::: zone-end

Next steps