UNPKG

@microsoft/teamsapp-cli

Version:

Teams Toolkit CLI is a text-based command line interface that can help scaffold, validate, and deploy applications for Microsoft Teams from the terminal or a CI/CD process.

179 lines (166 loc) 7.65 kB
<!--This file is auto generated by Teams Toolkit to provide you instructions and reference code to implement single sign on. --> <!--This file is used during the Teams Bot authentication flow to assist with retrieval of the access token.--> <!--If you're not familiar with this, do not alter or remove this file from your project.--> <html> <head> <title>Login Start Page</title> <meta charset="utf-8" /> </head> <body> <script type="text/javascript"> popUpSignInWindow(); async function popUpSignInWindow() { // Generate random state string and store it, so we can verify it in the callback let state = _guid(); localStorage.setItem("state", state); localStorage.removeItem("codeVerifier"); var currentURL = new URL(window.location); var clientId = currentURL.searchParams.get("clientId"); var tenantId = currentURL.searchParams.get("tenantId"); var loginHint = currentURL.searchParams.get("loginHint"); if (!loginHint) { loginHint = ""; } var scope = currentURL.searchParams.get("scope"); var originalCode = _guid(); var codeChallenge = await pkceChallengeFromVerifier(originalCode); localStorage.setItem("codeVerifier", originalCode); let queryParams = { client_id: clientId, response_type: "code", response_mode: "fragment", scope: scope, redirect_uri: window.location.origin + "/auth-end.html", nonce: _guid(), login_hint: loginHint, state: state, code_challenge: codeChallenge, code_challenge_method: "S256", }; let authorizeEndpoint = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/authorize?${toQueryString( queryParams )}`; window.location.assign(authorizeEndpoint); } // Build query string from map of query parameter function toQueryString(queryParams) { let encodedQueryParams = []; for (let key in queryParams) { encodedQueryParams.push(key + "=" + encodeURIComponent(queryParams[key])); } return encodedQueryParams.join("&"); } // Converts decimal to hex equivalent // (From ADAL.js: https://github.com/AzureAD/azure-activedirectory-library-for-js/blob/dev/lib/adal.js) function _decimalToHex(number) { var hex = number.toString(16); while (hex.length < 2) { hex = "0" + hex; } return hex; } // Generates RFC4122 version 4 guid (128 bits) // (From ADAL.js: https://github.com/AzureAD/azure-activedirectory-library-for-js/blob/dev/lib/adal.js) function _guid() { // RFC4122: The version 4 UUID is meant for generating UUIDs from truly-random or // pseudo-random numbers. // The algorithm is as follows: // Set the two most significant bits (bits 6 and 7) of the // clock_seq_hi_and_reserved to zero and one, respectively. // Set the four most significant bits (bits 12 through 15) of the // time_hi_and_version field to the 4-bit version number from // Section 4.1.3. Version4 // Set all the other bits to randomly (or pseudo-randomly) chosen // values. // UUID = time-low "-" time-mid "-"time-high-and-version "-"clock-seq-reserved and low(2hexOctet)"-" node // time-low = 4hexOctet // time-mid = 2hexOctet // time-high-and-version = 2hexOctet // clock-seq-and-reserved = hexOctet: // clock-seq-low = hexOctet // node = 6hexOctet // Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx // y could be 1000, 1001, 1010, 1011 since most significant two bits needs to be 10 // y values are 8, 9, A, B var cryptoObj = window.crypto || window.msCrypto; // for IE 11 if (cryptoObj && cryptoObj.getRandomValues) { var buffer = new Uint8Array(16); cryptoObj.getRandomValues(buffer); //buffer[6] and buffer[7] represents the time_hi_and_version field. We will set the four most significant bits (4 through 7) of buffer[6] to represent decimal number 4 (UUID version number). buffer[6] |= 0x40; //buffer[6] | 01000000 will set the 6 bit to 1. buffer[6] &= 0x4f; //buffer[6] & 01001111 will set the 4, 5, and 7 bit to 0 such that bits 4-7 == 0100 = "4". //buffer[8] represents the clock_seq_hi_and_reserved field. We will set the two most significant bits (6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively. buffer[8] |= 0x80; //buffer[8] | 10000000 will set the 7 bit to 1. buffer[8] &= 0xbf; //buffer[8] & 10111111 will set the 6 bit to 0. return ( _decimalToHex(buffer[0]) + _decimalToHex(buffer[1]) + _decimalToHex(buffer[2]) + _decimalToHex(buffer[3]) + "-" + _decimalToHex(buffer[4]) + _decimalToHex(buffer[5]) + "-" + _decimalToHex(buffer[6]) + _decimalToHex(buffer[7]) + "-" + _decimalToHex(buffer[8]) + _decimalToHex(buffer[9]) + "-" + _decimalToHex(buffer[10]) + _decimalToHex(buffer[11]) + _decimalToHex(buffer[12]) + _decimalToHex(buffer[13]) + _decimalToHex(buffer[14]) + _decimalToHex(buffer[15]) ); } else { var guidHolder = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"; var hex = "0123456789abcdef"; var r = 0; var guidResponse = ""; for (var i = 0; i < 36; i++) { if (guidHolder[i] !== "-" && guidHolder[i] !== "4") { // each x and y needs to be random r = (Math.random() * 16) | 0; } if (guidHolder[i] === "x") { guidResponse += hex[r]; } else if (guidHolder[i] === "y") { // clock-seq-and-reserved first hex is filtered and remaining hex values are random r &= 0x3; // bit and with 0011 to set pos 2 to zero ?0?? r |= 0x8; // set pos 3 to 1 as 1??? guidResponse += hex[r]; } else { guidResponse += guidHolder[i]; } } return guidResponse; } } // Calculate the SHA256 hash of the input text. // Returns a promise that resolves to an ArrayBuffer function sha256(plain) { const encoder = new TextEncoder(); const data = encoder.encode(plain); return window.crypto.subtle.digest("SHA-256", data); } // Base64-urlencodes the input string function base64urlencode(str) { // Convert the ArrayBuffer to string using Uint8 array to convert to what btoa accepts. // btoa accepts chars only within ascii 0-255 and base64 encodes them. // Then convert the base64 encoded to base64url encoded // (replace + with -, replace / with _, trim trailing =) return btoa(String.fromCharCode.apply(null, new Uint8Array(str))) .replace(/\+/g, "-") .replace(/\//g, "_") .replace(/=+$/, ""); } // Return the base64-urlencoded sha256 hash for the PKCE challenge async function pkceChallengeFromVerifier(v) { hashed = await sha256(v); return base64urlencode(hashed); } </script> </body> </html>