0.2.0 • Published 3 years ago

mods-server v0.2.0

Weekly downloads
24
License
MIT
Repository
-
Last release
3 years ago

mods-server: MODS Server SDK library for JavaScript and TypeScript

The mods-server library is part of the Microsoft Office Developer Services SDK. It facilitates development of server-side components in Azure Functions for use with Teams applications. Use this SDK when you are developing an Azure Function that handles requests from a Teams app and needs to access the Microsoft Graph or other Azure services (for example, SQL Azure) using either the managed identity associated with the App Service or on-behalf-of the user performing the request.

Usage

run npm install mods-server at your project.

More Information

Find more information in the Microsoft documentation:

Creating a MODS Service Client

Before you can use any MODS functionality, you must configure the MODS service client. Here is an example basic Azure Function (in TypeScript) that shows how to configure the client:

import { Context, HttpRequest, Response } from '@azure/functions';
import * as MODS from 'mods-server';

export default async function(context: Context, req: HttpRequest, config: MODS.Configuration): Promise<Response> {
    const client = MODS.getInstance(modsConfig);
    let result; // Put the result of your operation here.

    // Your code here

    return { res: { status: 200, body: JSON.stringify(result) }};
}

Use the modsClient to access the functionality you require in your code.

Getting an Access Token

The most basic functionality is obtaining an Azure Active Directory access token that you can use to access other resources. The access token can be based on the managed identity that is configured for the Azure Function, or obtained on-behalf-of the connecting user. The MODS client library sends the appropriate authorization to the Azure Function that is then used for the on-behalf-of transaction.

Getting an Access Token as the managed identity

When using a managed identity, you configure the allowed permissions (scopes) in Azure Active Directory. The access token retrieved will contain all scopes that are allowed. For more information on configuring permissions for a managed identity, see the documentation.

To request an access token for Azure Key Vault using the managed identity:

try {
    const resourceUrl = "https://vault.azure.net";
    const accessToken = await modsClient.getAccessTokenWithAppIdentity(resourceUrl);
    // Use the accessToken here
} catch (err) {
    // Handle errors here
    return { res: { status: 400, body: JSON.stringify(err) }};
}

TIP If you are using managed (application) identities with Azure Functions to access Azure resources, check to see if there is a modern Azure SDK. Using a modern Azure SDK will simplify development and does not require the MODS service SDK.

Getting an Access Token as the connected user

When accessing data on behalf of the user, you want to obtain an access token using the user identity. In this case, you must specify the scopes you wish to use the access token for.

To request an access token for an Azure SQL database using the user identity:

try {
    const scopes = [ 'https://database.windows.net/.default' ];
    const accessToken = await modsClient.getAccessTokenWithUserIdentity(scopes);
    // Use the access token here
} catch (err) {
    // Handle errors here
    return { res: { status: 400, body: JSON.stringify(err) }};
}

You can now use the access token to request your resource.

Accessing Microsoft Graph

Access the Microsoft Graph is a common task. You will use it for sending email, accessing SharePoint lists, and more. The MODS server library makes it easy to get an authenticated Microsoft Graph client.

Getting a Microsoft Graph client as the connected user

The most common situation will be that you want to access data within the Microsoft Graph on behalf of the connected user. Use the following code:

try {
    const scopes = [ 'user.read' ]
    const graphClient = await modsClient.getMicrosoftGraphClientWithUserIdentity(scopes);

    // Use the graphClient here; for example - this obtains the users profile
    const result = await graphClient.api('/me').get();
} catch (err) {
    // Handle errors here
    return { res: { status: 400, body: JSON.stringify(err) }};
}

You do not need to pre-fetch an access token. The access token is retrieved transparently for you. You can only perform operations that are allowed through the approved scopes.

Getting a Microsoft Graph client as the managed identity

To connect to the Microsoft Graph with the managed identity:

try {
    const graphClient = await modsClient.getMicrosoftGraphClientWithApplicationPermission();

    // Use the graphClient here; for example - this obtains the first 10 items of a list
    const siteId = 'replace-with-site-id';
    const listId = 'replace-with-list-id';
    const listItems = await graphClient
        .api(`/sites/${siteId}/lists/${listId}?$top=10`)
        .get();
    result = { items: listItems };
} catch (err) {
    // Handle errors here
    return { res: { status: 400, body: JSON.stringify(err) }};
}

TIP You can find more Microsoft Graph sample code on developer.microsoft.com

Getting information on the connected user

When the Teams client SDK sends a request to the Azure Function, some basic information is sent along with the connection to identity the user. You can use getUserInfo() to obtain that information:

const { displayName, objectId, preferredUserName } = modsClient.getUserInfo();

The objectId is the object ID of the user within AAD and is guaranteed not to change even if the username or display name is changed. This allows it to be used as a primary key in database operations.

Accessing Azure SQL Database

Before using the Azure SQL samples, user should operate following steps. 1. Provision Functions. 2. Provision Azure SQL server. 3. Config Azure SQL with Active Directory admin. 3. Provision Azure SQL database. 4. Set firewall policy to allow function access database (Allow Azure services and resources to access) 4. Provision a user-assigned managed identity. 6. Add identity name to database (use T-SQL command in database CREATE USER [identity name] FROM EXTERNAL PROVIDER;). 7. Assign user-assigned managerd identity to the function.

try {
    // Initialize the mods server SDK.
    let client = MODS.getInstance(modsConfig);

    // Get conn. Make sure identityId, SqlEndpoint, database in modsConfig is configed
    let conn = await client.getSqlConnection()

    // your costumized code here to use connection for querying data.
    conn.close()
} catch (err) {
    return {res: { status: 400, body: JSON.stringfy(err)}};
}

Calling Azure Functions as connected user

const extraData = { arg1: 'some data' };
let result
try {
    result = modsClient.callFunctionWithUserIdentity("foo", "post", extraData);
} catch (err) {
    return {res: { status: 400, body: JSON.stringfy(err)}};
}

Calling Azure Functions as the managed identity

const extraData = { arg1: 'some data' };
let result
try {
    result = modsClient.callFunctionWithAppIdentity("foo", "post", extraData);
} catch (err) {
    return {res: { status: 400, body: JSON.stringfy(err)}};
}

Error Handling

Each method in the MODS service client will throw a MODSError when it encounters an error. The MODSError object contains the following fields:

  • errorCode (string) is a unique string for the error
  • errorMessage (string) is a human readable description of the error.

When checking for a specific error in code, use errorCode. When displaying the error, use errorMessage.