diff --git a/.eslintignore b/.eslintignore index 0a6b560..90fcaf2 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ dist +lib node_modules **/*.spec.* \ No newline at end of file diff --git a/.github/FUNDING.yaml b/.github/FUNDING.yml similarity index 100% rename from .github/FUNDING.yaml rename to .github/FUNDING.yml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index f6bfae2..8b77f6d 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -19,7 +19,6 @@ jobs: node-version: ${{ matrix.node-version }} - run: npm install - run: npm run lint - - run: npm run test - run: npm run build env: CI: true \ No newline at end of file diff --git a/.npmignore b/.npmignore index c81b082..213ae47 100644 --- a/.npmignore +++ b/.npmignore @@ -10,3 +10,4 @@ tsconfig.json .travis.yml tslint.json .eslintrc.json +.eslintignore diff --git a/README.md b/README.md index e9a879b..000bacb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # teams-simpleauth -A node.js Microsoft Teams simpleauth implementation +A node.js Microsoft Teams simpleauth implementation that works with the [@microsoft/teamsfx](https://www.npmjs.com/package/@microsoft/teamsfx) client side component. ## Installation @@ -15,12 +15,61 @@ Install with npm ### Prerequisites -### Installation +A Teams Tab project using [Express.js](http://expressjs.com/) as a server side implementation, for instance a project scaffolded with [Yo Teams](https://aka.ms/yoteams) -1. Install the `teams-simpleauth` package -2. Install the `"@microsoft/teamsfx` package -3. +### Installation and configuration +Start by installing the `teams-simpleauth` and `@microsoft/teamsfx` packages. The first one is used for the server side *exchange* of the token and the latter one is for the client side scripting. + +``` bash +npm install teams-simpleauth @microsoft/teamsfx --save +``` + +Next, in your server side component add the following import. For *yo teams* based applications this is in the `src/server/server.ts` file. + +``` Typescript +import { simpleAuthRouter } from "teams-simpleauth"; +``` + +And then after the express application is create add a statement like this to add and configure the router. + +`appId`, `appIdUri` and `appSecret` are retrieved from the AAD application that is used for the Teams SSO Tab. `scopes` is an array of delegated permission scopes you would like for the returned access token and finally `tenantId` is either the ID of the tenant or set to `common` for multi-tenant applications. + +``` Typescript +express.use("/auth/token", simpleAuthRouter({ + appId: process.env.TAB_APP_ID as string, + appIdUri: process.env.TAB_APP_URI as string, + appSecret: process.env.TAB_APP_SECRET as string, + scopes: ["Presence.Read"], + tenantId: "00000000-0000-0000-0000-000000000000" +})); +``` + +In the client side code (tab) you need to import the `teamsfx` package as follows, and you use the package as described in the [`teamsfx` documentation](https://www.npmjs.com/package/@microsoft/teamsfx). + +``` Typescript +import * as teamsFx from "@microsoft/teamsfx"; +``` + + +Example of tab using the `teamsfx` component in a *yo teams* based tab: + +``` TypeScript +teamsFx.loadConfiguration({ + authentication: { + initiateLoginEndpoint: `https://${process.env.PUBLIC_HOSTNAME}/ile`, + clientId: process.env.TAB_APP_ID, + tenantId: "00000000-0000-0000-0000-000000000000",, + authorityHost: "https://login.microsoftonline.com", + applicationIdUri: process.env.TAB_APP_URI, + simpleAuthEndpoint: `https://${process.env.PUBLIC_HOSTNAME}` + } +}); +const credential = new teamsFx.TeamsUserCredential(); +const graphClient = teamsFx.createMicrosoftGraphClient(credential, ["Presence.Read"]); +const result = await graphClient.api("/me/presence").get(); +setPresence(" is " + result.availability); +``` ## License diff --git a/package-lock.json b/package-lock.json index ac8c386..5462fc4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,9 +25,14 @@ "eslint": "^7.28.0", "eslint-config-standard": "^16.0.3", "eslint-plugin-import": "^2.23.4", + "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^5.1.0", "eslint-plugin-standard": "^5.0.0", "typescript": "^4.3.2" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/wictorwilen/" } }, "node_modules/@azure/msal-common": { @@ -1391,7 +1396,6 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", "dev": true, - "peer": true, "dependencies": { "eslint-utils": "^2.0.0", "regexpp": "^3.0.0" @@ -1467,7 +1471,6 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", "dev": true, - "peer": true, "dependencies": { "eslint-plugin-es": "^3.0.0", "eslint-utils": "^2.0.0", @@ -1488,7 +1491,6 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", "dev": true, - "peer": true, "engines": { "node": ">= 4" } @@ -1498,7 +1500,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, - "peer": true, "bin": { "semver": "bin/semver.js" } @@ -5179,7 +5180,6 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", "dev": true, - "peer": true, "requires": { "eslint-utils": "^2.0.0", "regexpp": "^3.0.0" @@ -5239,7 +5239,6 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", "dev": true, - "peer": true, "requires": { "eslint-plugin-es": "^3.0.0", "eslint-utils": "^2.0.0", @@ -5253,15 +5252,13 @@ "version": "5.1.8", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "peer": true + "dev": true }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "peer": true + "dev": true } } }, diff --git a/package.json b/package.json index caba710..9c4f511 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "teams-simpleauth", - "version": "1.0.0-preview", + "version": "1.0.0-preview2", "description": "", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -37,6 +37,7 @@ "eslint": "^7.28.0", "eslint-config-standard": "^16.0.3", "eslint-plugin-import": "^2.23.4", + "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^5.1.0", "eslint-plugin-standard": "^5.0.0", "typescript": "^4.3.2" diff --git a/src/ISimpleAuthRouterOptions.ts b/src/ISimpleAuthRouterOptions.ts index 63e64ba..0c80d2f 100644 --- a/src/ISimpleAuthRouterOptions.ts +++ b/src/ISimpleAuthRouterOptions.ts @@ -1,7 +1,27 @@ +// Copyright (c) Wictor Wilén. All rights reserved. +// Licensed under the MIT license. +/** + * Options for the Teams Simpleauth router + */ export interface ISimpleAuthRouterOptions { + /** + * The application/client id + */ appId: string; + /** + * The application/client id URI + */ appIdUri: string; + /** + * The appclication/client secret required for the on-behalf-of OAuth flow + */ appSecret: string; + /** + * Scopes requested + */ scopes: string[]; + /** + * Tenant id or "common" for multi-tenant applications + */ tenantId: string | "common"; }; diff --git a/src/index.ts b/src/index.ts index fec2447..d02fe3a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,4 @@ +// Copyright (c) Wictor Wilén. All rights reserved. +// Licensed under the MIT license. export { ISimpleAuthRouterOptions } from "./ISimpleAuthRouterOptions"; export { simpleAuthRouter } from "./simpleAuthRouter"; diff --git a/src/simpleAuthRouter.ts b/src/simpleAuthRouter.ts index 5504e7d..f0e13a9 100644 --- a/src/simpleAuthRouter.ts +++ b/src/simpleAuthRouter.ts @@ -1,9 +1,24 @@ +// Copyright (c) Wictor Wilén. All rights reserved. +// Licensed under the MIT license. import { Router } from "express"; import { Passport } from "passport"; import { BearerStrategy, IBearerStrategyOption, ITokenPayload, VerifyCallback } from "passport-azure-ad"; import { ConfidentialClientApplication } from "@azure/msal-node"; import { ISimpleAuthRouterOptions } from "./ISimpleAuthRouterOptions"; +/** + * Creates the Teams Simpleauth router + * @param options options for the router + * @returns an Express router + * @example + * express.use("/auth/token", simpleAuthRouter({ + * appId: process.env.TAB_APP_ID as string, + * appIdUri: process.env.TAB_APP_URI as string, + * appSecret: process.env.TAB_APP_SECRET as string, + * scopes: ["Presence.Read"], + * tenantId: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" +* })); + */ export const simpleAuthRouter = (options: ISimpleAuthRouterOptions): Router => { const router = Router();