diff --git a/.vs/GTF_Git/CopilotIndices/17.14.786.1071/CodeChunks.db b/.vs/GTF_Git/CopilotIndices/17.14.786.1071/CodeChunks.db deleted file mode 100644 index 353fa265..00000000 Binary files a/.vs/GTF_Git/CopilotIndices/17.14.786.1071/CodeChunks.db and /dev/null differ diff --git a/.vs/GTF_Git/CopilotIndices/17.14.786.1071/SemanticSymbols.db b/.vs/GTF_Git/CopilotIndices/17.14.786.1071/SemanticSymbols.db deleted file mode 100644 index 8e13816f..00000000 Binary files a/.vs/GTF_Git/CopilotIndices/17.14.786.1071/SemanticSymbols.db and /dev/null differ diff --git a/.vs/GTF_Git/v17/.wsuo b/.vs/GTF_Git/v17/.wsuo deleted file mode 100644 index ce73e6f5..00000000 Binary files a/.vs/GTF_Git/v17/.wsuo and /dev/null differ diff --git a/.vs/GTF_Git/v17/DocumentLayout.backup.json b/.vs/GTF_Git/v17/DocumentLayout.backup.json deleted file mode 100644 index baf7e598..00000000 --- a/.vs/GTF_Git/v17/DocumentLayout.backup.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Version": 1, - "WorkspaceRootPath": "C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\", - "Documents": [], - "DocumentGroupContainers": [ - { - "Orientation": 0, - "VerticalTabListWidth": 256, - "DocumentGroups": [] - } - ] -} \ No newline at end of file diff --git a/.vs/GTF_Git/v17/DocumentLayout.json b/.vs/GTF_Git/v17/DocumentLayout.json deleted file mode 100644 index 63708c14..00000000 --- a/.vs/GTF_Git/v17/DocumentLayout.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "Version": 1, - "WorkspaceRootPath": "C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\", - "Documents": [ - { - "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\GTF\\project\\backend\\config\\test-db.js||{14D17961-FE51-464D-9111-C4AF11D7D99A}", - "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:GTF\\project\\backend\\config\\test-db.js||{14D17961-FE51-464D-9111-C4AF11D7D99A}" - }, - { - "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\GTF\\project\\backend\\db.php||{3B902123-F8A7-4915-9F01-361F908088D0}", - "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:GTF\\project\\backend\\db.php||{3B902123-F8A7-4915-9F01-361F908088D0}" - } - ], - "DocumentGroupContainers": [ - { - "Orientation": 0, - "VerticalTabListWidth": 256, - "DocumentGroups": [ - { - "DockedWidth": 200, - "SelectedChildIndex": 1, - "Children": [ - { - "$type": "Bookmark", - "Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}" - }, - { - "$type": "Document", - "DocumentIndex": 0, - "Title": "test-db.js", - "DocumentMoniker": "C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\GTF\\project\\backend\\config\\test-db.js", - "RelativeDocumentMoniker": "GTF\\project\\backend\\config\\test-db.js", - "ToolTip": "C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\GTF\\project\\backend\\config\\test-db.js", - "RelativeToolTip": "GTF\\project\\backend\\config\\test-db.js", - "ViewState": "AgIAAAAAAAAAAAAAAAAAABcAAABMAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001646|", - "WhenOpened": "2025-09-15T08:03:52.452Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 1, - "Title": "db.php", - "DocumentMoniker": "C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\GTF\\project\\backend\\db.php", - "RelativeDocumentMoniker": "GTF\\project\\backend\\db.php", - "ToolTip": "C:\\Users\\oimer\\OneDrive - ENSUP\\GTF_Git\\GTF\\project\\backend\\db.php", - "RelativeToolTip": "GTF\\project\\backend\\db.php", - "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.002338|", - "WhenOpened": "2025-09-15T08:00:38.102Z", - "EditorCaption": "" - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json deleted file mode 100644 index f8b48885..00000000 --- a/.vs/ProjectSettings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "CurrentProjectSetting": null -} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json deleted file mode 100644 index 639661dd..00000000 --- a/.vs/VSWorkspaceState.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "ExpandedNodes": [ - "", - "\\GTF", - "\\GTF\\project", - "\\GTF\\project\\backend", - "\\GTF\\project\\backend\\config" - ], - "SelectedNode": "\\GTF\\project\\backend\\config\\test-db.js", - "PreviewInSolutionExplorer": false -} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite index 89981f26..a0a60e29 100644 Binary files a/.vs/slnx.sqlite and b/.vs/slnx.sqlite differ diff --git a/GTF/project/backend/config/.env b/GTF/project/backend/config/.env index e41ca4a4..97b40fd0 100644 --- a/GTF/project/backend/config/.env +++ b/GTF/project/backend/config/.env @@ -1,5 +1,7 @@ -DB_SERVER=Localhost +DB_SERVER=BONEMINE DB_DATABASE=GTF -DB_USER=ENSUP\oimer -DB_PASSWORD=Wijdane123@ +DB_USER=gtf_app +DB_PASSWORD=GTF2025!Secure +DB_ENCRYPT=true +DB_TRUST_SERVER_CERTIFICATE=true PORT=3001 \ No newline at end of file diff --git a/GTF/project/backend/config/server.js b/GTF/project/backend/config/server.js new file mode 100644 index 00000000..55da0418 --- /dev/null +++ b/GTF/project/backend/config/server.js @@ -0,0 +1,282 @@ +const express = require('express'); +const cors = require('cors'); +const sql = require('mssql'); +require('dotenv').config(); + +const app = express(); +const PORT = 3001; + +// Configuration base de données +const dbConfig = { + server: process.env.DB_SERVER, + database: process.env.DB_DATABASE, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + options: { + encrypt: true, + trustServerCertificate: true, + enableArithAbort: true + } +}; + +// Middleware +app.use(cors({ + origin: ['http://localhost:5173', 'http://localhost:3000', 'http://127.0.0.1:5173'], + credentials: true +})); +app.use(express.json()); + +// Log de toutes les requêtes +app.use((req, res, next) => { + console.log(`${new Date().toISOString()} - ${req.method} ${req.path} depuis ${req.get('origin') || 'inconnu'}`); + next(); +}); + +// Variable pour stocker la connexion +let pool = null; + +// Fonction pour se connecter à la base +async function connectDatabase() { + try { + pool = await sql.connect(dbConfig); + console.log('Base de données connectée'); + return true; + } catch (error) { + console.error('Erreur de connexion :', error.message); + return false; + } +} + +// Route de test +app.get('/api/test', (req, res) => { + res.json({ + message: 'Le serveur fonctionne !', + timestamp: new Date().toISOString() + }); +}); + +// Route pour tester la base de données +app.get('/api/db-test', async (req, res) => { + try { + if (!pool) { + return res.status(500).json({ error: 'Base non connectée' }); + } + + const result = await pool.request().query('SELECT COUNT(*) as total FROM FormateurSqy'); + res.json({ + message: 'Base OK', + formateurs: result.recordset[0].total + }); + } catch (error) { + res.status(500).json({ error: error.message }); + } +}); + +// Route pour lister les formateurs +app.get('/api/formateurs', async (req, res) => { + try { + const result = await pool.request().query(` + SELECT TOP 10 + NUMERO, + NOM_ENS as nom, + PRENOM_ENS as prenom, + EMAIL1 as email + FROM FormateurSqy + WHERE EMAIL1 IS NOT NULL + ORDER BY NOM_ENS + `); + + res.json({ + success: true, + data: result.recordset + }); + } catch (error) { + res.status(500).json({ + success: false, + error: error.message + }); + } +}); + +// Route pour sauvegarder une déclaration +app.post('/api/save_declaration', async (req, res) => { + try { + const { date, activityType, hours, description, user } = req.body; + + console.log('Données reçues:', { date, activityType, hours, description, user }); + + // Validation simple + if (!date || !activityType || !hours) { + return res.status(400).json({ + success: false, + error: 'Données manquantes' + }); + } + + let formateurNumero; + + if (user && user.email) { + // Chercher le formateur par email + const formateurResult = await pool.request() + .input('email', sql.VarChar, user.email) + .query('SELECT NUMERO FROM FormateurSqy WHERE EMAIL1 = @email'); + + if (formateurResult.recordset.length > 0) { + // Formateur trouvé + formateurNumero = formateurResult.recordset[0].NUMERO; + console.log('Formateur trouvé par email:', formateurNumero); + } else { + // Créer un nouveau formateur + const maxNumeroResult = await pool.request() + .query('SELECT ISNULL(MAX(NUMERO), 0) + 1 as nextNumero FROM FormateurSqy'); + + const nextNumero = maxNumeroResult.recordset[0].nextNumero; + + await pool.request() + .input('numero', sql.Int, nextNumero) + .input('nom', sql.VarChar, user.nom || 'Inconnu') + .input('prenom', sql.VarChar, user.prenom || 'Inconnu') + .input('email', sql.VarChar, user.email) + .input('department', sql.VarChar, user.department || 'Non défini') + .input('role', sql.VarChar, user.role || 'Employé') + .query(` + INSERT INTO FormateurSqy ( + NUMERO, NOM_ENS, PRENOM_ENS, EMAIL1, [Ecole - Pole], Contrat + ) VALUES ( + @numero, @nom, @prenom, @email, @department, @role + ) + `); + + formateurNumero = nextNumero; + console.log('Nouveau formateur créé:', formateurNumero); + } + } else { + // Fallback : utiliser un formateur par défaut + formateurNumero = 999; + console.log('Utilisation du formateur par défaut:', formateurNumero); + } + + // Récupérer l'ID du type de demande + const typeResult = await pool.request() + .input('activityType', sql.VarChar, activityType) + .query('SELECT id FROM types_demandes WHERE libelle = @activityType'); + + if (typeResult.recordset.length === 0) { + return res.status(400).json({ + success: false, + error: `Type d'activité invalide: ${activityType}` + }); + } + + const typeDemandeId = typeResult.recordset[0].id; + + // Vérifier si une déclaration existe déjà pour cette date + const existingResult = await pool.request() + .input('formateurNumero', sql.Int, formateurNumero) + .input('date', sql.Date, date) + .query('SELECT id FROM declarations WHERE formateur_numero = @formateurNumero AND date = @date'); + + if (existingResult.recordset.length > 0) { + // Mise à jour + await pool.request() + .input('utilisateurId', sql.Int, formateurNumero) + .input('typeDemandeId', sql.Int, typeDemandeId) + .input('hours', sql.Float, hours) + .input('description', sql.NVarChar, description || null) + .input('formateurNumero', sql.Int, formateurNumero) + .input('date', sql.Date, date) + .query(` + UPDATE declarations + SET utilisateur_id = @utilisateurId, type_demande_id = @typeDemandeId, duree = @hours, description = @description + WHERE formateur_numero = @formateurNumero AND date = @date + `); + + console.log('Déclaration mise à jour'); + } else { + // Création + await pool.request() + .input('utilisateurId', sql.Int, formateurNumero) + .input('formateurNumero', sql.Int, formateurNumero) + .input('typeDemandeId', sql.Int, typeDemandeId) + .input('date', sql.Date, date) + .input('hours', sql.Float, hours) + .input('description', sql.NVarChar, description || null) + .query(` + INSERT INTO declarations (utilisateur_id, formateur_numero, type_demande_id, date, duree, description) + VALUES (@utilisateurId, @formateurNumero, @typeDemandeId, @date, @hours, @description) + `); + + console.log('Nouvelle déclaration créée'); + } + + res.json({ + success: true, + message: 'Déclaration sauvegardée avec succès' + }); + + } catch (error) { + console.error('Erreur lors de la sauvegarde:', error); + res.status(500).json({ + success: false, + error: error.message + }); + } +}); + +// Route pour récupérer les déclarations +app.get('/api/get_declarations', async (req, res) => { + try { + const result = await pool.request().query(` + SELECT + d.id, + d.formateur_numero as utilisateur_id, + td.id as type_demande_id, + d.date, + d.duree, + d.description, + d.formateur_numero, + td.libelle as activityType + FROM declarations d + INNER JOIN types_demandes td ON d.type_demande_id = td.id + ORDER BY d.date DESC + `); + + res.json(result.recordset); + + } catch (error) { + console.error('Erreur lors de la récupération:', error); + res.status(500).json({ error: error.message }); + } +}); + +// Démarrage du serveur +async function startServer() { + const dbConnected = await connectDatabase(); + + if (!dbConnected) { + console.log('Impossible de démarrer sans base de données'); + return; + } + + app.listen(PORT, () => { + console.log(`Serveur démarré sur http://localhost:${PORT}`); + console.log('Routes disponibles :'); + console.log('- GET /api/test'); + console.log('- GET /api/db-test'); + console.log('- GET /api/formateurs'); + console.log('- POST /api/save_declaration'); + console.log('- GET /api/get_declarations'); + }); +} + +// Arrêt propre +process.on('SIGINT', async () => { + console.log('Arrêt du serveur...'); + if (pool) { + await pool.close(); + } + process.exit(0); +}); + +// Démarrer +startServer(); \ No newline at end of file diff --git a/GTF/project/backend/config/test-db.js b/GTF/project/backend/config/test-db.js index 50bbf5c2..ec322da5 100644 --- a/GTF/project/backend/config/test-db.js +++ b/GTF/project/backend/config/test-db.js @@ -1,36 +1,59 @@ -// Test avec authentification Windows +// Test avec authentification SQL Server const sql = require('mssql'); const config = { - server: '16.0.1000.6', + server: 'BONEMINE', database: 'GTF', + user: 'gtf_app', + password: 'GTF2025!Secure', options: { encrypt: true, trustServerCertificate: true, - trustedConnection: true, // Utilise votre compte Windows actuel enableArithAbort: true } }; async function testConnection() { try { - console.log('🔄 Test avec authentification Windows...'); - console.log('Utilisateur Windows actuel:', process.env.USERNAME); + console.log('Test avec authentification SQL Server...'); + console.log('Serveur:', config.server); + console.log('Base:', config.database); + console.log('Utilisateur:', config.user); await sql.connect(config); - console.log('✅ Connexion réussie avec Windows Auth !'); + console.log('Connexion réussie avec SQL Server Auth !'); - const result = await sql.query('SELECT COUNT(*) as total FROM FormateurSqy'); - console.log('📊 Nombre de formateurs :', result.recordset[0].total); + // Test des tables + const result1 = await sql.query('SELECT COUNT(*) as total FROM FormateurSqy'); + console.log('Nombre de formateurs :', result1.recordset[0].total); const result2 = await sql.query('SELECT COUNT(*) as total FROM declarations'); - console.log('📊 Nombre de déclarations :', result2.recordset[0].total); + console.log('Nombre de déclarations :', result2.recordset[0].total); - console.log('🎉 Parfait ! Votre authentification Windows fonctionne.'); + const result3 = await sql.query('SELECT COUNT(*) as total FROM types_demandes'); + console.log('Nombre de types de demandes :', result3.recordset[0].total); + + // Test d'insertion/lecture (pour vérifier les permissions) + const testResult = await sql.query(` + SELECT + id, + libelle + FROM types_demandes + `); + console.log('Types de demandes disponibles :'); + testResult.recordset.forEach(t => { + console.log(`- ${t.id}: ${t.libelle}`); + }); + + console.log('Configuration SQL Server validée !'); } catch (error) { - console.error('⌠Erreur :', error.message); - console.log('💡 Suggestion : Vérifiez que votre utilisateur Windows a accès à la base GTF'); + console.error('Erreur :', error.message); + console.log('Code d\'erreur:', error.code); + + if (error.code === 'ELOGIN') { + console.log('Vérifiez que l\'utilisateur gtf_app a été créé dans SQL Server'); + } } finally { await sql.close(); } diff --git a/GTF/project/backend/db.php b/GTF/project/backend/db.php deleted file mode 100644 index e5182eeb..00000000 --- a/GTF/project/backend/db.php +++ /dev/null @@ -1,16 +0,0 @@ - "GTF", - "Uid" => "oimer", - "PWD" => "Wijdane123@", - "CharacterSet" => "UTF-8" -]; - -$conn = sqlsrv_connect($serverName, $connectionOptions); - -if ($conn === false) { - die(print_r(sqlsrv_errors(), true)); -} -?> diff --git a/GTF/project/backend/get_declarations.php b/GTF/project/backend/get_declarations.php deleted file mode 100644 index 29ce17b9..00000000 --- a/GTF/project/backend/get_declarations.php +++ /dev/null @@ -1,20 +0,0 @@ - sqlsrv_errors()])); -} - -$sql = "SELECT id, utilisateur_id, type_demande_id, CONVERT(varchar, date, 23) as date, duree, description, formateur_numero FROM declarations"; -$stmt = sqlsrv_query($conn, $sql); - -$data = []; -while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { - $data[] = $row; -} - -echo json_encode($data); diff --git a/GTF/project/backend/node_modules/.package-lock.json b/GTF/project/backend/node_modules/.package-lock.json index 2f862dd2..5cc08b2f 100644 --- a/GTF/project/backend/node_modules/.package-lock.json +++ b/GTF/project/backend/node_modules/.package-lock.json @@ -523,6 +523,19 @@ "node": ">=6.6.0" } }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -1196,6 +1209,15 @@ "node": ">= 0.6" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", diff --git a/GTF/project/backend/node_modules/cors/CONTRIBUTING.md b/GTF/project/backend/node_modules/cors/CONTRIBUTING.md new file mode 100644 index 00000000..591b09a1 --- /dev/null +++ b/GTF/project/backend/node_modules/cors/CONTRIBUTING.md @@ -0,0 +1,33 @@ +# contributing to `cors` + +CORS is a node.js package for providing a [connect](http://www.senchalabs.org/connect/)/[express](http://expressjs.com/) middleware that can be used to enable [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) with various options. Learn more about the project in [the README](README.md). + +## The CORS Spec + +[http://www.w3.org/TR/cors/](http://www.w3.org/TR/cors/) + +## Pull Requests Welcome + +* Include `'use strict';` in every javascript file. +* 2 space indentation. +* Please run the testing steps below before submitting. + +## Testing + +```bash +$ npm install +$ npm test +``` + +## Interactive Testing Harness + +[http://node-cors-client.herokuapp.com](http://node-cors-client.herokuapp.com) + +Related git repositories: + +* [https://github.com/TroyGoode/node-cors-server](https://github.com/TroyGoode/node-cors-server) +* [https://github.com/TroyGoode/node-cors-client](https://github.com/TroyGoode/node-cors-client) + +## License + +[MIT License](http://www.opensource.org/licenses/mit-license.php) diff --git a/GTF/project/backend/node_modules/cors/HISTORY.md b/GTF/project/backend/node_modules/cors/HISTORY.md new file mode 100644 index 00000000..5762bce9 --- /dev/null +++ b/GTF/project/backend/node_modules/cors/HISTORY.md @@ -0,0 +1,58 @@ +2.8.5 / 2018-11-04 +================== + + * Fix setting `maxAge` option to `0` + +2.8.4 / 2017-07-12 +================== + + * Work-around Safari bug in default pre-flight response + +2.8.3 / 2017-03-29 +================== + + * Fix error when options delegate missing `methods` option + +2.8.2 / 2017-03-28 +================== + + * Fix error when frozen options are passed + * Send "Vary: Origin" when using regular expressions + * Send "Vary: Access-Control-Request-Headers" when dynamic `allowedHeaders` + +2.8.1 / 2016-09-08 +================== + +This release only changed documentation. + +2.8.0 / 2016-08-23 +================== + + * Add `optionsSuccessStatus` option + +2.7.2 / 2016-08-23 +================== + + * Fix error when Node.js running in strict mode + +2.7.1 / 2015-05-28 +================== + + * Move module into expressjs organization + +2.7.0 / 2015-05-28 +================== + + * Allow array of matching condition as `origin` option + * Allow regular expression as `origin` option + +2.6.1 / 2015-05-28 +================== + + * Update `license` in package.json + +2.6.0 / 2015-04-27 +================== + + * Add `preflightContinue` option + * Fix "Vary: Origin" header added for "*" diff --git a/GTF/project/backend/node_modules/cors/LICENSE b/GTF/project/backend/node_modules/cors/LICENSE new file mode 100644 index 00000000..fd10c843 --- /dev/null +++ b/GTF/project/backend/node_modules/cors/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2013 Troy Goode + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/GTF/project/backend/node_modules/cors/README.md b/GTF/project/backend/node_modules/cors/README.md new file mode 100644 index 00000000..732b847e --- /dev/null +++ b/GTF/project/backend/node_modules/cors/README.md @@ -0,0 +1,243 @@ +# cors + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +CORS is a node.js package for providing a [Connect](http://www.senchalabs.org/connect/)/[Express](http://expressjs.com/) middleware that can be used to enable [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) with various options. + +**[Follow me (@troygoode) on Twitter!](https://twitter.com/intent/user?screen_name=troygoode)** + +* [Installation](#installation) +* [Usage](#usage) + * [Simple Usage](#simple-usage-enable-all-cors-requests) + * [Enable CORS for a Single Route](#enable-cors-for-a-single-route) + * [Configuring CORS](#configuring-cors) + * [Configuring CORS Asynchronously](#configuring-cors-asynchronously) + * [Enabling CORS Pre-Flight](#enabling-cors-pre-flight) +* [Configuration Options](#configuration-options) +* [Demo](#demo) +* [License](#license) +* [Author](#author) + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install cors +``` + +## Usage + +### Simple Usage (Enable *All* CORS Requests) + +```javascript +var express = require('express') +var cors = require('cors') +var app = express() + +app.use(cors()) + +app.get('/products/:id', function (req, res, next) { + res.json({msg: 'This is CORS-enabled for all origins!'}) +}) + +app.listen(80, function () { + console.log('CORS-enabled web server listening on port 80') +}) +``` + +### Enable CORS for a Single Route + +```javascript +var express = require('express') +var cors = require('cors') +var app = express() + +app.get('/products/:id', cors(), function (req, res, next) { + res.json({msg: 'This is CORS-enabled for a Single Route'}) +}) + +app.listen(80, function () { + console.log('CORS-enabled web server listening on port 80') +}) +``` + +### Configuring CORS + +```javascript +var express = require('express') +var cors = require('cors') +var app = express() + +var corsOptions = { + origin: 'http://example.com', + optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204 +} + +app.get('/products/:id', cors(corsOptions), function (req, res, next) { + res.json({msg: 'This is CORS-enabled for only example.com.'}) +}) + +app.listen(80, function () { + console.log('CORS-enabled web server listening on port 80') +}) +``` + +### Configuring CORS w/ Dynamic Origin + +```javascript +var express = require('express') +var cors = require('cors') +var app = express() + +var whitelist = ['http://example1.com', 'http://example2.com'] +var corsOptions = { + origin: function (origin, callback) { + if (whitelist.indexOf(origin) !== -1) { + callback(null, true) + } else { + callback(new Error('Not allowed by CORS')) + } + } +} + +app.get('/products/:id', cors(corsOptions), function (req, res, next) { + res.json({msg: 'This is CORS-enabled for a whitelisted domain.'}) +}) + +app.listen(80, function () { + console.log('CORS-enabled web server listening on port 80') +}) +``` + +If you do not want to block REST tools or server-to-server requests, +add a `!origin` check in the origin function like so: + +```javascript +var corsOptions = { + origin: function (origin, callback) { + if (whitelist.indexOf(origin) !== -1 || !origin) { + callback(null, true) + } else { + callback(new Error('Not allowed by CORS')) + } + } +} +``` + +### Enabling CORS Pre-Flight + +Certain CORS requests are considered 'complex' and require an initial +`OPTIONS` request (called the "pre-flight request"). An example of a +'complex' CORS request is one that uses an HTTP verb other than +GET/HEAD/POST (such as DELETE) or that uses custom headers. To enable +pre-flighting, you must add a new OPTIONS handler for the route you want +to support: + +```javascript +var express = require('express') +var cors = require('cors') +var app = express() + +app.options('/products/:id', cors()) // enable pre-flight request for DELETE request +app.del('/products/:id', cors(), function (req, res, next) { + res.json({msg: 'This is CORS-enabled for all origins!'}) +}) + +app.listen(80, function () { + console.log('CORS-enabled web server listening on port 80') +}) +``` + +You can also enable pre-flight across-the-board like so: + +```javascript +app.options('*', cors()) // include before other routes +``` + +### Configuring CORS Asynchronously + +```javascript +var express = require('express') +var cors = require('cors') +var app = express() + +var whitelist = ['http://example1.com', 'http://example2.com'] +var corsOptionsDelegate = function (req, callback) { + var corsOptions; + if (whitelist.indexOf(req.header('Origin')) !== -1) { + corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response + } else { + corsOptions = { origin: false } // disable CORS for this request + } + callback(null, corsOptions) // callback expects two parameters: error and options +} + +app.get('/products/:id', cors(corsOptionsDelegate), function (req, res, next) { + res.json({msg: 'This is CORS-enabled for a whitelisted domain.'}) +}) + +app.listen(80, function () { + console.log('CORS-enabled web server listening on port 80') +}) +``` + +## Configuration Options + +* `origin`: Configures the **Access-Control-Allow-Origin** CORS header. Possible values: + - `Boolean` - set `origin` to `true` to reflect the [request origin](http://tools.ietf.org/html/draft-abarth-origin-09), as defined by `req.header('Origin')`, or set it to `false` to disable CORS. + - `String` - set `origin` to a specific origin. For example if you set it to `"http://example.com"` only requests from "http://example.com" will be allowed. + - `RegExp` - set `origin` to a regular expression pattern which will be used to test the request origin. If it's a match, the request origin will be reflected. For example the pattern `/example\.com$/` will reflect any request that is coming from an origin ending with "example.com". + - `Array` - set `origin` to an array of valid origins. Each origin can be a `String` or a `RegExp`. For example `["http://example1.com", /\.example2\.com$/]` will accept any request from "http://example1.com" or from a subdomain of "example2.com". + - `Function` - set `origin` to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (which expects the signature `err [object], allow [bool]`) as the second. +* `methods`: Configures the **Access-Control-Allow-Methods** CORS header. Expects a comma-delimited string (ex: 'GET,PUT,POST') or an array (ex: `['GET', 'PUT', 'POST']`). +* `allowedHeaders`: Configures the **Access-Control-Allow-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Type,Authorization') or an array (ex: `['Content-Type', 'Authorization']`). If not specified, defaults to reflecting the headers specified in the request's **Access-Control-Request-Headers** header. +* `exposedHeaders`: Configures the **Access-Control-Expose-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Range,X-Content-Range') or an array (ex: `['Content-Range', 'X-Content-Range']`). If not specified, no custom headers are exposed. +* `credentials`: Configures the **Access-Control-Allow-Credentials** CORS header. Set to `true` to pass the header, otherwise it is omitted. +* `maxAge`: Configures the **Access-Control-Max-Age** CORS header. Set to an integer to pass the header, otherwise it is omitted. +* `preflightContinue`: Pass the CORS preflight response to the next handler. +* `optionsSuccessStatus`: Provides a status code to use for successful `OPTIONS` requests, since some legacy browsers (IE11, various SmartTVs) choke on `204`. + +The default configuration is the equivalent of: + +```json +{ + "origin": "*", + "methods": "GET,HEAD,PUT,PATCH,POST,DELETE", + "preflightContinue": false, + "optionsSuccessStatus": 204 +} +``` + +For details on the effect of each CORS header, read [this](http://www.html5rocks.com/en/tutorials/cors/) article on HTML5 Rocks. + +## Demo + +A demo that illustrates CORS working (and not working) using jQuery is available here: [http://node-cors-client.herokuapp.com/](http://node-cors-client.herokuapp.com/) + +Code for that demo can be found here: + +* Client: [https://github.com/TroyGoode/node-cors-client](https://github.com/TroyGoode/node-cors-client) +* Server: [https://github.com/TroyGoode/node-cors-server](https://github.com/TroyGoode/node-cors-server) + +## License + +[MIT License](http://www.opensource.org/licenses/mit-license.php) + +## Author + +[Troy Goode](https://github.com/TroyGoode) ([troygoode@gmail.com](mailto:troygoode@gmail.com)) + +[coveralls-image]: https://img.shields.io/coveralls/expressjs/cors/master.svg +[coveralls-url]: https://coveralls.io/r/expressjs/cors?branch=master +[downloads-image]: https://img.shields.io/npm/dm/cors.svg +[downloads-url]: https://npmjs.org/package/cors +[npm-image]: https://img.shields.io/npm/v/cors.svg +[npm-url]: https://npmjs.org/package/cors +[travis-image]: https://img.shields.io/travis/expressjs/cors/master.svg +[travis-url]: https://travis-ci.org/expressjs/cors diff --git a/GTF/project/backend/node_modules/cors/lib/index.js b/GTF/project/backend/node_modules/cors/lib/index.js new file mode 100644 index 00000000..5475aecd --- /dev/null +++ b/GTF/project/backend/node_modules/cors/lib/index.js @@ -0,0 +1,238 @@ +(function () { + + 'use strict'; + + var assign = require('object-assign'); + var vary = require('vary'); + + var defaults = { + origin: '*', + methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', + preflightContinue: false, + optionsSuccessStatus: 204 + }; + + function isString(s) { + return typeof s === 'string' || s instanceof String; + } + + function isOriginAllowed(origin, allowedOrigin) { + if (Array.isArray(allowedOrigin)) { + for (var i = 0; i < allowedOrigin.length; ++i) { + if (isOriginAllowed(origin, allowedOrigin[i])) { + return true; + } + } + return false; + } else if (isString(allowedOrigin)) { + return origin === allowedOrigin; + } else if (allowedOrigin instanceof RegExp) { + return allowedOrigin.test(origin); + } else { + return !!allowedOrigin; + } + } + + function configureOrigin(options, req) { + var requestOrigin = req.headers.origin, + headers = [], + isAllowed; + + if (!options.origin || options.origin === '*') { + // allow any origin + headers.push([{ + key: 'Access-Control-Allow-Origin', + value: '*' + }]); + } else if (isString(options.origin)) { + // fixed origin + headers.push([{ + key: 'Access-Control-Allow-Origin', + value: options.origin + }]); + headers.push([{ + key: 'Vary', + value: 'Origin' + }]); + } else { + isAllowed = isOriginAllowed(requestOrigin, options.origin); + // reflect origin + headers.push([{ + key: 'Access-Control-Allow-Origin', + value: isAllowed ? requestOrigin : false + }]); + headers.push([{ + key: 'Vary', + value: 'Origin' + }]); + } + + return headers; + } + + function configureMethods(options) { + var methods = options.methods; + if (methods.join) { + methods = options.methods.join(','); // .methods is an array, so turn it into a string + } + return { + key: 'Access-Control-Allow-Methods', + value: methods + }; + } + + function configureCredentials(options) { + if (options.credentials === true) { + return { + key: 'Access-Control-Allow-Credentials', + value: 'true' + }; + } + return null; + } + + function configureAllowedHeaders(options, req) { + var allowedHeaders = options.allowedHeaders || options.headers; + var headers = []; + + if (!allowedHeaders) { + allowedHeaders = req.headers['access-control-request-headers']; // .headers wasn't specified, so reflect the request headers + headers.push([{ + key: 'Vary', + value: 'Access-Control-Request-Headers' + }]); + } else if (allowedHeaders.join) { + allowedHeaders = allowedHeaders.join(','); // .headers is an array, so turn it into a string + } + if (allowedHeaders && allowedHeaders.length) { + headers.push([{ + key: 'Access-Control-Allow-Headers', + value: allowedHeaders + }]); + } + + return headers; + } + + function configureExposedHeaders(options) { + var headers = options.exposedHeaders; + if (!headers) { + return null; + } else if (headers.join) { + headers = headers.join(','); // .headers is an array, so turn it into a string + } + if (headers && headers.length) { + return { + key: 'Access-Control-Expose-Headers', + value: headers + }; + } + return null; + } + + function configureMaxAge(options) { + var maxAge = (typeof options.maxAge === 'number' || options.maxAge) && options.maxAge.toString() + if (maxAge && maxAge.length) { + return { + key: 'Access-Control-Max-Age', + value: maxAge + }; + } + return null; + } + + function applyHeaders(headers, res) { + for (var i = 0, n = headers.length; i < n; i++) { + var header = headers[i]; + if (header) { + if (Array.isArray(header)) { + applyHeaders(header, res); + } else if (header.key === 'Vary' && header.value) { + vary(res, header.value); + } else if (header.value) { + res.setHeader(header.key, header.value); + } + } + } + } + + function cors(options, req, res, next) { + var headers = [], + method = req.method && req.method.toUpperCase && req.method.toUpperCase(); + + if (method === 'OPTIONS') { + // preflight + headers.push(configureOrigin(options, req)); + headers.push(configureCredentials(options, req)); + headers.push(configureMethods(options, req)); + headers.push(configureAllowedHeaders(options, req)); + headers.push(configureMaxAge(options, req)); + headers.push(configureExposedHeaders(options, req)); + applyHeaders(headers, res); + + if (options.preflightContinue) { + next(); + } else { + // Safari (and potentially other browsers) need content-length 0, + // for 204 or they just hang waiting for a body + res.statusCode = options.optionsSuccessStatus; + res.setHeader('Content-Length', '0'); + res.end(); + } + } else { + // actual response + headers.push(configureOrigin(options, req)); + headers.push(configureCredentials(options, req)); + headers.push(configureExposedHeaders(options, req)); + applyHeaders(headers, res); + next(); + } + } + + function middlewareWrapper(o) { + // if options are static (either via defaults or custom options passed in), wrap in a function + var optionsCallback = null; + if (typeof o === 'function') { + optionsCallback = o; + } else { + optionsCallback = function (req, cb) { + cb(null, o); + }; + } + + return function corsMiddleware(req, res, next) { + optionsCallback(req, function (err, options) { + if (err) { + next(err); + } else { + var corsOptions = assign({}, defaults, options); + var originCallback = null; + if (corsOptions.origin && typeof corsOptions.origin === 'function') { + originCallback = corsOptions.origin; + } else if (corsOptions.origin) { + originCallback = function (origin, cb) { + cb(null, corsOptions.origin); + }; + } + + if (originCallback) { + originCallback(req.headers.origin, function (err2, origin) { + if (err2 || !origin) { + next(err2); + } else { + corsOptions.origin = origin; + cors(corsOptions, req, res, next); + } + }); + } else { + next(); + } + } + }); + }; + } + + // can pass either an options hash, an options delegate, or nothing + module.exports = middlewareWrapper; + +}()); diff --git a/GTF/project/backend/node_modules/cors/package.json b/GTF/project/backend/node_modules/cors/package.json new file mode 100644 index 00000000..ff37d984 --- /dev/null +++ b/GTF/project/backend/node_modules/cors/package.json @@ -0,0 +1,41 @@ +{ + "name": "cors", + "description": "Node.js CORS middleware", + "version": "2.8.5", + "author": "Troy Goode (https://github.com/troygoode/)", + "license": "MIT", + "keywords": [ + "cors", + "express", + "connect", + "middleware" + ], + "repository": "expressjs/cors", + "main": "./lib/index.js", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "devDependencies": { + "after": "0.8.2", + "eslint": "2.13.1", + "express": "4.16.3", + "mocha": "5.2.0", + "nyc": "13.1.0", + "supertest": "3.3.0" + }, + "files": [ + "lib/index.js", + "CONTRIBUTING.md", + "HISTORY.md", + "LICENSE", + "README.md" + ], + "engines": { + "node": ">= 0.10" + }, + "scripts": { + "test": "npm run lint && nyc --reporter=html --reporter=text mocha --require test/support/env", + "lint": "eslint lib test" + } +} diff --git a/GTF/project/backend/node_modules/object-assign/index.js b/GTF/project/backend/node_modules/object-assign/index.js new file mode 100644 index 00000000..0930cf88 --- /dev/null +++ b/GTF/project/backend/node_modules/object-assign/index.js @@ -0,0 +1,90 @@ +/* +object-assign +(c) Sindre Sorhus +@license MIT +*/ + +'use strict'; +/* eslint-disable no-unused-vars */ +var getOwnPropertySymbols = Object.getOwnPropertySymbols; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var propIsEnumerable = Object.prototype.propertyIsEnumerable; + +function toObject(val) { + if (val === null || val === undefined) { + throw new TypeError('Object.assign cannot be called with null or undefined'); + } + + return Object(val); +} + +function shouldUseNative() { + try { + if (!Object.assign) { + return false; + } + + // Detect buggy property enumeration order in older V8 versions. + + // https://bugs.chromium.org/p/v8/issues/detail?id=4118 + var test1 = new String('abc'); // eslint-disable-line no-new-wrappers + test1[5] = 'de'; + if (Object.getOwnPropertyNames(test1)[0] === '5') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test2 = {}; + for (var i = 0; i < 10; i++) { + test2['_' + String.fromCharCode(i)] = i; + } + var order2 = Object.getOwnPropertyNames(test2).map(function (n) { + return test2[n]; + }); + if (order2.join('') !== '0123456789') { + return false; + } + + // https://bugs.chromium.org/p/v8/issues/detail?id=3056 + var test3 = {}; + 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { + test3[letter] = letter; + }); + if (Object.keys(Object.assign({}, test3)).join('') !== + 'abcdefghijklmnopqrst') { + return false; + } + + return true; + } catch (err) { + // We don't expect any of the above to throw, but better to be safe. + return false; + } +} + +module.exports = shouldUseNative() ? Object.assign : function (target, source) { + var from; + var to = toObject(target); + var symbols; + + for (var s = 1; s < arguments.length; s++) { + from = Object(arguments[s]); + + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } + } + + if (getOwnPropertySymbols) { + symbols = getOwnPropertySymbols(from); + for (var i = 0; i < symbols.length; i++) { + if (propIsEnumerable.call(from, symbols[i])) { + to[symbols[i]] = from[symbols[i]]; + } + } + } + } + + return to; +}; diff --git a/GTF/project/backend/node_modules/object-assign/license b/GTF/project/backend/node_modules/object-assign/license new file mode 100644 index 00000000..654d0bfe --- /dev/null +++ b/GTF/project/backend/node_modules/object-assign/license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/GTF/project/backend/node_modules/object-assign/package.json b/GTF/project/backend/node_modules/object-assign/package.json new file mode 100644 index 00000000..503eb1e6 --- /dev/null +++ b/GTF/project/backend/node_modules/object-assign/package.json @@ -0,0 +1,42 @@ +{ + "name": "object-assign", + "version": "4.1.1", + "description": "ES2015 `Object.assign()` ponyfill", + "license": "MIT", + "repository": "sindresorhus/object-assign", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "xo && ava", + "bench": "matcha bench.js" + }, + "files": [ + "index.js" + ], + "keywords": [ + "object", + "assign", + "extend", + "properties", + "es2015", + "ecmascript", + "harmony", + "ponyfill", + "prollyfill", + "polyfill", + "shim", + "browser" + ], + "devDependencies": { + "ava": "^0.16.0", + "lodash": "^4.16.4", + "matcha": "^0.7.0", + "xo": "^0.16.0" + } +} diff --git a/GTF/project/backend/node_modules/object-assign/readme.md b/GTF/project/backend/node_modules/object-assign/readme.md new file mode 100644 index 00000000..1be09d35 --- /dev/null +++ b/GTF/project/backend/node_modules/object-assign/readme.md @@ -0,0 +1,61 @@ +# object-assign [![Build Status](https://travis-ci.org/sindresorhus/object-assign.svg?branch=master)](https://travis-ci.org/sindresorhus/object-assign) + +> ES2015 [`Object.assign()`](http://www.2ality.com/2014/01/object-assign.html) [ponyfill](https://ponyfill.com) + + +## Use the built-in + +Node.js 4 and up, as well as every evergreen browser (Chrome, Edge, Firefox, Opera, Safari), +support `Object.assign()` :tada:. If you target only those environments, then by all +means, use `Object.assign()` instead of this package. + + +## Install + +``` +$ npm install --save object-assign +``` + + +## Usage + +```js +const objectAssign = require('object-assign'); + +objectAssign({foo: 0}, {bar: 1}); +//=> {foo: 0, bar: 1} + +// multiple sources +objectAssign({foo: 0}, {bar: 1}, {baz: 2}); +//=> {foo: 0, bar: 1, baz: 2} + +// overwrites equal keys +objectAssign({foo: 0}, {foo: 1}, {foo: 2}); +//=> {foo: 2} + +// ignores null and undefined sources +objectAssign({foo: 0}, null, {bar: 1}, undefined); +//=> {foo: 0, bar: 1} +``` + + +## API + +### objectAssign(target, [source, ...]) + +Assigns enumerable own properties of `source` objects to the `target` object and returns the `target` object. Additional `source` objects will overwrite previous ones. + + +## Resources + +- [ES2015 spec - Object.assign](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign) + + +## Related + +- [deep-assign](https://github.com/sindresorhus/deep-assign) - Recursive `Object.assign()` + + +## License + +MIT © [Sindre Sorhus](https://sindresorhus.com) diff --git a/GTF/project/backend/package-lock.json b/GTF/project/backend/package-lock.json index 9a376f3a..261b45a9 100644 --- a/GTF/project/backend/package-lock.json +++ b/GTF/project/backend/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "cors": "^2.8.5", "dotenv": "^17.2.2", "express": "^5.1.0", "mssql": "^11.0.1" @@ -533,6 +534,19 @@ "node": ">=6.6.0" } }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -1206,6 +1220,15 @@ "node": ">= 0.6" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", diff --git a/GTF/project/backend/package.json b/GTF/project/backend/package.json index 2c4a68ee..e5bb4472 100644 --- a/GTF/project/backend/package.json +++ b/GTF/project/backend/package.json @@ -10,6 +10,7 @@ "license": "ISC", "description": "", "dependencies": { + "cors": "^2.8.5", "dotenv": "^17.2.2", "express": "^5.1.0", "mssql": "^11.0.1" diff --git a/GTF/project/backend/save_declaration.php b/GTF/project/backend/save_declaration.php deleted file mode 100644 index 991eec7e..00000000 --- a/GTF/project/backend/save_declaration.php +++ /dev/null @@ -1,26 +0,0 @@ - true, "message" => "Déclaration enregistrée"]); -} else { - echo json_encode(["success" => false, "error" => sqlsrv_errors()]); -} -?> diff --git a/GTF/project/node_modules/.vite/deps/@azure_msal-browser.js b/GTF/project/node_modules/.vite/deps/@azure_msal-browser.js index c9e5c1b0..21c75f91 100644 --- a/GTF/project/node_modules/.vite/deps/@azure_msal-browser.js +++ b/GTF/project/node_modules/.vite/deps/@azure_msal-browser.js @@ -1,6 +1,6 @@ import { BrowserPerformanceMeasurement -} from "./chunk-BXCAR3JX.js"; +} from "./chunk-5VK5IHOT.js"; import { __export } from "./chunk-G3PMV62Z.js"; @@ -16999,7 +16999,7 @@ function getPerfMeasurementModule() { sessionStorage = window[BrowserCacheLocation.SessionStorage]; const perfEnabled = sessionStorage == null ? void 0 : sessionStorage.getItem(BROWSER_PERF_ENABLED_KEY); if (Number(perfEnabled) === 1) { - return import("./BrowserPerformanceMeasurement-5UJNI4WV.js"); + return import("./BrowserPerformanceMeasurement-5VDOVMRB.js"); } } catch (e) { } diff --git a/GTF/project/node_modules/.vite/deps/@azure_msal-browser.js.map b/GTF/project/node_modules/.vite/deps/@azure_msal-browser.js.map index 079dcde6..4d9a574a 100644 --- a/GTF/project/node_modules/.vite/deps/@azure_msal-browser.js.map +++ b/GTF/project/node_modules/.vite/deps/@azure_msal-browser.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../../@azure/msal-common/src/utils/Constants.ts", "../../@azure/msal-common/src/error/AuthErrorCodes.ts", "../../@azure/msal-common/src/error/AuthError.ts", "../../@azure/msal-common/src/error/ClientAuthErrorCodes.ts", "../../@azure/msal-common/src/error/ClientAuthError.ts", "../../@azure/msal-common/src/crypto/ICrypto.ts", "../../@azure/msal-common/src/logger/Logger.ts", "../../@azure/msal-common/src/packageMetadata.ts", "../../@azure/msal-common/src/authority/AuthorityOptions.ts", "../../@azure/msal-common/src/error/ClientConfigurationErrorCodes.ts", "../../@azure/msal-common/src/error/ClientConfigurationError.ts", "../../@azure/msal-common/src/utils/StringUtils.ts", "../../@azure/msal-common/src/request/ScopeSet.ts", "../../@azure/msal-common/src/account/AccountInfo.ts", "../../@azure/msal-common/src/account/AuthToken.ts", "../../@azure/msal-common/src/utils/UrlUtils.ts", "../../@azure/msal-common/src/url/UrlString.ts", "../../@azure/msal-common/src/authority/AuthorityMetadata.ts", "../../@azure/msal-common/src/error/CacheErrorCodes.ts", "../../@azure/msal-common/src/error/CacheError.ts", "../../@azure/msal-common/src/cache/CacheManager.ts", "../../@azure/msal-common/src/authority/ProtocolMode.ts", "../../@azure/msal-common/src/telemetry/performance/PerformanceEvent.ts", "../../@azure/msal-common/src/telemetry/performance/StubPerformanceClient.ts", "../../@azure/msal-common/src/config/ClientConfiguration.ts", "../../@azure/msal-common/src/account/CcsCredential.ts", "../../@azure/msal-common/src/account/ClientInfo.ts", "../../@azure/msal-common/src/constants/AADServerParamKeys.ts", "../../@azure/msal-common/src/request/RequestParameterBuilder.ts", "../../@azure/msal-common/src/authority/AuthorityType.ts", "../../@azure/msal-common/src/authority/OpenIdConfigResponse.ts", "../../@azure/msal-common/src/authority/CloudInstanceDiscoveryResponse.ts", "../../@azure/msal-common/src/authority/CloudInstanceDiscoveryErrorResponse.ts", "../../@azure/msal-common/src/utils/FunctionWrappers.ts", "../../@azure/msal-common/src/authority/RegionDiscovery.ts", "../../@azure/msal-common/src/utils/TimeUtils.ts", "../../@azure/msal-common/src/cache/utils/CacheHelpers.ts", "../../@azure/msal-common/src/authority/Authority.ts", "../../@azure/msal-common/src/authority/AuthorityFactory.ts", "../../@azure/msal-common/src/error/ServerError.ts", "../../@azure/msal-common/src/network/RequestThumbprint.ts", "../../@azure/msal-common/src/network/ThrottlingUtils.ts", "../../@azure/msal-common/src/error/NetworkError.ts", "../../@azure/msal-common/src/client/BaseClient.ts", "../../@azure/msal-common/src/account/TokenClaims.ts", "../../@azure/msal-common/src/cache/entities/AccountEntity.ts", "../../@azure/msal-common/src/error/InteractionRequiredAuthErrorCodes.ts", "../../@azure/msal-common/src/error/InteractionRequiredAuthError.ts", "../../@azure/msal-common/src/utils/ProtocolUtils.ts", "../../@azure/msal-common/src/crypto/PopTokenGenerator.ts", "../../@azure/msal-common/src/cache/persistence/TokenCacheContext.ts", "../../@azure/msal-common/src/response/ResponseHandler.ts", "../../@azure/msal-common/src/utils/ClientAssertionUtils.ts", "../../@azure/msal-common/src/client/AuthorizationCodeClient.ts", "../../@azure/msal-common/src/client/RefreshTokenClient.ts", "../../@azure/msal-common/src/client/SilentFlowClient.ts", "../../@azure/msal-common/src/network/INetworkModule.ts", "../../@azure/msal-common/src/protocol/Authorize.ts", "../../@azure/msal-common/src/request/AuthenticationHeaderParser.ts", "../../@azure/msal-common/src/telemetry/server/ServerTelemetryManager.ts", "../../@azure/msal-common/src/error/JoseHeaderErrorCodes.ts", "../../@azure/msal-common/src/error/JoseHeaderError.ts", "../../@azure/msal-common/src/crypto/JoseHeader.ts", "../../@azure/msal-common/src/telemetry/performance/PerformanceClient.ts", "../../@azure/msal-browser/src/error/BrowserAuthErrorCodes.ts", "../../@azure/msal-browser/src/error/BrowserAuthError.ts", "../../@azure/msal-browser/src/utils/BrowserConstants.ts", "../../@azure/msal-browser/src/encode/Base64Encode.ts", "../../@azure/msal-browser/src/encode/Base64Decode.ts", "../../@azure/msal-browser/src/crypto/BrowserCrypto.ts", "../../@azure/msal-browser/src/error/BrowserConfigurationAuthErrorCodes.ts", "../../@azure/msal-browser/src/error/BrowserConfigurationAuthError.ts", "../../@azure/msal-browser/src/utils/BrowserUtils.ts", "../../@azure/msal-browser/src/navigation/NavigationClient.ts", "../../@azure/msal-browser/src/network/FetchClient.ts", "../../@azure/msal-browser/src/config/Configuration.ts", "../../@azure/msal-browser/src/packageMetadata.ts", "../../@azure/msal-browser/src/cache/CacheKeys.ts", "../../@azure/msal-browser/src/operatingcontext/BaseOperatingContext.ts", "../../@azure/msal-browser/src/naa/BridgeStatusCode.ts", "../../@azure/msal-browser/src/naa/BridgeProxy.ts", "../../@azure/msal-browser/src/operatingcontext/NestedAppOperatingContext.ts", "../../@azure/msal-browser/src/operatingcontext/StandardOperatingContext.ts", "../../@azure/msal-browser/src/cache/DatabaseStorage.ts", "../../@azure/msal-browser/src/cache/MemoryStorage.ts", "../../@azure/msal-browser/src/cache/AsyncMemoryStorage.ts", "../../@azure/msal-browser/src/crypto/CryptoOps.ts", "../../@azure/msal-browser/src/cache/CookieStorage.ts", "../../@azure/msal-browser/src/cache/CacheHelpers.ts", "../../@azure/msal-browser/src/cache/EncryptedData.ts", "../../@azure/msal-browser/src/cache/LocalStorage.ts", "../../@azure/msal-browser/src/cache/SessionStorage.ts", "../../@azure/msal-browser/src/event/EventType.ts", "../../@azure/msal-browser/src/utils/Helpers.ts", "../../@azure/msal-browser/src/cache/BrowserCacheManager.ts", "../../@azure/msal-browser/src/cache/AccountManager.ts", "../../@azure/msal-browser/src/event/EventHandler.ts", "../../@azure/msal-browser/src/interaction_client/BaseInteractionClient.ts", "../../@azure/msal-browser/src/request/RequestHelpers.ts", "../../@azure/msal-browser/src/interaction_client/StandardInteractionClient.ts", "../../@azure/msal-browser/src/utils/BrowserProtocolUtils.ts", "../../@azure/msal-browser/src/response/ResponseHandler.ts", "../../@azure/msal-browser/src/interaction_handler/InteractionHandler.ts", "../../@azure/msal-browser/src/error/NativeAuthErrorCodes.ts", "../../@azure/msal-browser/src/broker/nativeBroker/NativeStatusCodes.ts", "../../@azure/msal-browser/src/error/NativeAuthError.ts", "../../@azure/msal-browser/src/interaction_client/SilentCacheClient.ts", "../../@azure/msal-browser/src/interaction_client/PlatformAuthInteractionClient.ts", "../../@azure/msal-browser/src/protocol/Authorize.ts", "../../@azure/msal-browser/src/crypto/PkceGenerator.ts", "../../@azure/msal-browser/src/broker/nativeBroker/PlatformAuthExtensionHandler.ts", "../../@azure/msal-browser/src/broker/nativeBroker/PlatformAuthDOMHandler.ts", "../../@azure/msal-browser/src/broker/nativeBroker/PlatformAuthProvider.ts", "../../@azure/msal-browser/src/interaction_client/PopupClient.ts", "../../@azure/msal-browser/src/interaction_client/RedirectClient.ts", "../../@azure/msal-browser/src/interaction_handler/SilentHandler.ts", "../../@azure/msal-browser/src/interaction_client/SilentIframeClient.ts", "../../@azure/msal-browser/src/interaction_client/SilentRefreshClient.ts", "../../@azure/msal-browser/src/cache/TokenCache.ts", "../../@azure/msal-browser/src/interaction_client/HybridSpaAuthorizationCodeClient.ts", "../../@azure/msal-browser/src/interaction_client/SilentAuthCodeClient.ts", "../../@azure/msal-browser/src/utils/MsalFrameStatsUtils.ts", "../../@azure/msal-browser/src/controllers/StandardController.ts", "../../@azure/msal-browser/src/naa/BridgeError.ts", "../../@azure/msal-browser/src/naa/mapping/NestedAppAuthAdapter.ts", "../../@azure/msal-browser/src/error/NestedAppAuthError.ts", "../../@azure/msal-browser/src/controllers/NestedAppAuthController.ts", "../../@azure/msal-browser/src/controllers/ControllerFactory.ts", "../../@azure/msal-browser/src/app/PublicClientApplication.ts", "../../@azure/msal-browser/src/controllers/UnknownOperatingContextController.ts", "../../@azure/msal-browser/src/operatingcontext/UnknownOperatingContext.ts", "../../@azure/msal-browser/src/app/PublicClientNext.ts", "../../@azure/msal-browser/src/app/IPublicClientApplication.ts", "../../@azure/msal-browser/src/event/EventMessage.ts", "../../@azure/msal-browser/src/crypto/SignedHttpRequest.ts", "../../@azure/msal-browser/src/telemetry/BrowserPerformanceClient.ts"], - "sourcesContent": ["/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const Constants = {\n LIBRARY_NAME: \"MSAL.JS\",\n SKU: \"msal.js.common\",\n // default authority\n DEFAULT_AUTHORITY: \"https://login.microsoftonline.com/common/\",\n DEFAULT_AUTHORITY_HOST: \"login.microsoftonline.com\",\n DEFAULT_COMMON_TENANT: \"common\",\n // ADFS String\n ADFS: \"adfs\",\n DSTS: \"dstsv2\",\n // Default AAD Instance Discovery Endpoint\n AAD_INSTANCE_DISCOVERY_ENDPT:\n \"https://login.microsoftonline.com/common/discovery/instance?api-version=1.1&authorization_endpoint=\",\n // CIAM URL\n CIAM_AUTH_URL: \".ciamlogin.com\",\n AAD_TENANT_DOMAIN_SUFFIX: \".onmicrosoft.com\",\n // Resource delimiter - used for certain cache entries\n RESOURCE_DELIM: \"|\",\n // Placeholder for non-existent account ids/objects\n NO_ACCOUNT: \"NO_ACCOUNT\",\n // Claims\n CLAIMS: \"claims\",\n // Consumer UTID\n CONSUMER_UTID: \"9188040d-6c67-4c5b-b112-36a304b66dad\",\n // Default scopes\n OPENID_SCOPE: \"openid\",\n PROFILE_SCOPE: \"profile\",\n OFFLINE_ACCESS_SCOPE: \"offline_access\",\n EMAIL_SCOPE: \"email\",\n CODE_GRANT_TYPE: \"authorization_code\",\n RT_GRANT_TYPE: \"refresh_token\",\n S256_CODE_CHALLENGE_METHOD: \"S256\",\n URL_FORM_CONTENT_TYPE: \"application/x-www-form-urlencoded;charset=utf-8\",\n AUTHORIZATION_PENDING: \"authorization_pending\",\n NOT_DEFINED: \"not_defined\",\n EMPTY_STRING: \"\",\n NOT_APPLICABLE: \"N/A\",\n NOT_AVAILABLE: \"Not Available\",\n FORWARD_SLASH: \"/\",\n IMDS_ENDPOINT: \"http://169.254.169.254/metadata/instance/compute/location\",\n IMDS_VERSION: \"2020-06-01\",\n IMDS_TIMEOUT: 2000,\n AZURE_REGION_AUTO_DISCOVER_FLAG: \"TryAutoDetect\",\n REGIONAL_AUTH_PUBLIC_CLOUD_SUFFIX: \"login.microsoft.com\",\n KNOWN_PUBLIC_CLOUDS: [\n \"login.microsoftonline.com\",\n \"login.windows.net\",\n \"login.microsoft.com\",\n \"sts.windows.net\",\n ],\n SHR_NONCE_VALIDITY: 240,\n INVALID_INSTANCE: \"invalid_instance\",\n};\n\nexport const HttpStatus = {\n SUCCESS: 200,\n SUCCESS_RANGE_START: 200,\n SUCCESS_RANGE_END: 299,\n REDIRECT: 302,\n CLIENT_ERROR: 400,\n CLIENT_ERROR_RANGE_START: 400,\n BAD_REQUEST: 400,\n UNAUTHORIZED: 401,\n NOT_FOUND: 404,\n REQUEST_TIMEOUT: 408,\n GONE: 410,\n TOO_MANY_REQUESTS: 429,\n CLIENT_ERROR_RANGE_END: 499,\n SERVER_ERROR: 500,\n SERVER_ERROR_RANGE_START: 500,\n SERVICE_UNAVAILABLE: 503,\n GATEWAY_TIMEOUT: 504,\n SERVER_ERROR_RANGE_END: 599,\n MULTI_SIDED_ERROR: 600,\n} as const;\nexport type HttpStatus = (typeof HttpStatus)[keyof typeof HttpStatus];\n\nexport const HttpMethod = {\n GET: \"GET\",\n POST: \"POST\",\n} as const;\nexport type HttpMethod = (typeof HttpMethod)[keyof typeof HttpMethod];\n\nexport const OIDC_DEFAULT_SCOPES = [\n Constants.OPENID_SCOPE,\n Constants.PROFILE_SCOPE,\n Constants.OFFLINE_ACCESS_SCOPE,\n];\n\nexport const OIDC_SCOPES = [...OIDC_DEFAULT_SCOPES, Constants.EMAIL_SCOPE];\n\n/**\n * Request header names\n */\nexport const HeaderNames = {\n CONTENT_TYPE: \"Content-Type\",\n CONTENT_LENGTH: \"Content-Length\",\n RETRY_AFTER: \"Retry-After\",\n CCS_HEADER: \"X-AnchorMailbox\",\n WWWAuthenticate: \"WWW-Authenticate\",\n AuthenticationInfo: \"Authentication-Info\",\n X_MS_REQUEST_ID: \"x-ms-request-id\",\n X_MS_HTTP_VERSION: \"x-ms-httpver\",\n} as const;\nexport type HeaderNames = (typeof HeaderNames)[keyof typeof HeaderNames];\n\n/**\n * Persistent cache keys MSAL which stay while user is logged in.\n */\nexport const PersistentCacheKeys = {\n ACTIVE_ACCOUNT_FILTERS: \"active-account-filters\", // new cache entry for active_account for a more robust version for browser\n} as const;\nexport type PersistentCacheKeys =\n (typeof PersistentCacheKeys)[keyof typeof PersistentCacheKeys];\n\n/**\n * String constants related to AAD Authority\n */\nexport const AADAuthorityConstants = {\n COMMON: \"common\",\n ORGANIZATIONS: \"organizations\",\n CONSUMERS: \"consumers\",\n} as const;\nexport type AADAuthorityConstants =\n (typeof AADAuthorityConstants)[keyof typeof AADAuthorityConstants];\n\n/**\n * Claims request keys\n */\nexport const ClaimsRequestKeys = {\n ACCESS_TOKEN: \"access_token\",\n XMS_CC: \"xms_cc\",\n} as const;\nexport type ClaimsRequestKeys =\n (typeof ClaimsRequestKeys)[keyof typeof ClaimsRequestKeys];\n\n/**\n * we considered making this \"enum\" in the request instead of string, however it looks like the allowed list of\n * prompt values kept changing over past couple of years. There are some undocumented prompt values for some\n * internal partners too, hence the choice of generic \"string\" type instead of the \"enum\"\n */\nexport const PromptValue = {\n LOGIN: \"login\",\n SELECT_ACCOUNT: \"select_account\",\n CONSENT: \"consent\",\n NONE: \"none\",\n CREATE: \"create\",\n NO_SESSION: \"no_session\",\n};\n\n/**\n * allowed values for codeVerifier\n */\nexport const CodeChallengeMethodValues = {\n PLAIN: \"plain\",\n S256: \"S256\",\n};\n\n/**\n * Allowed values for response_type\n */\nexport const OAuthResponseType = {\n CODE: \"code\",\n IDTOKEN_TOKEN: \"id_token token\",\n IDTOKEN_TOKEN_REFRESHTOKEN: \"id_token token refresh_token\",\n} as const;\nexport type OAuthResponseType =\n (typeof OAuthResponseType)[keyof typeof OAuthResponseType];\n\n/**\n * allowed values for server response type\n * @deprecated Use ResponseMode instead\n */\nexport const ServerResponseType = {\n QUERY: \"query\",\n FRAGMENT: \"fragment\",\n} as const;\nexport type ServerResponseType =\n (typeof ServerResponseType)[keyof typeof ServerResponseType];\n\n/**\n * allowed values for response_mode\n */\nexport const ResponseMode = {\n QUERY: \"query\",\n FRAGMENT: \"fragment\",\n FORM_POST: \"form_post\",\n} as const;\nexport type ResponseMode = (typeof ResponseMode)[keyof typeof ResponseMode];\n\n/**\n * allowed grant_type\n */\nexport const GrantType = {\n IMPLICIT_GRANT: \"implicit\",\n AUTHORIZATION_CODE_GRANT: \"authorization_code\",\n CLIENT_CREDENTIALS_GRANT: \"client_credentials\",\n RESOURCE_OWNER_PASSWORD_GRANT: \"password\",\n REFRESH_TOKEN_GRANT: \"refresh_token\",\n DEVICE_CODE_GRANT: \"device_code\",\n JWT_BEARER: \"urn:ietf:params:oauth:grant-type:jwt-bearer\",\n} as const;\nexport type GrantType = (typeof GrantType)[keyof typeof GrantType];\n\n/**\n * Account types in Cache\n */\nexport const CacheAccountType = {\n MSSTS_ACCOUNT_TYPE: \"MSSTS\",\n ADFS_ACCOUNT_TYPE: \"ADFS\",\n MSAV1_ACCOUNT_TYPE: \"MSA\",\n GENERIC_ACCOUNT_TYPE: \"Generic\", // NTLM, Kerberos, FBA, Basic etc\n} as const;\nexport type CacheAccountType =\n (typeof CacheAccountType)[keyof typeof CacheAccountType];\n\n/**\n * Separators used in cache\n */\nexport const Separators = {\n CACHE_KEY_SEPARATOR: \"-\",\n CLIENT_INFO_SEPARATOR: \".\",\n} as const;\nexport type Separators = (typeof Separators)[keyof typeof Separators];\n\n/**\n * Credential Type stored in the cache\n */\nexport const CredentialType = {\n ID_TOKEN: \"IdToken\",\n ACCESS_TOKEN: \"AccessToken\",\n ACCESS_TOKEN_WITH_AUTH_SCHEME: \"AccessToken_With_AuthScheme\",\n REFRESH_TOKEN: \"RefreshToken\",\n} as const;\nexport type CredentialType =\n (typeof CredentialType)[keyof typeof CredentialType];\n\n/**\n * Combine all cache types\n */\nexport const CacheType = {\n ADFS: 1001,\n MSA: 1002,\n MSSTS: 1003,\n GENERIC: 1004,\n ACCESS_TOKEN: 2001,\n REFRESH_TOKEN: 2002,\n ID_TOKEN: 2003,\n APP_METADATA: 3001,\n UNDEFINED: 9999,\n} as const;\nexport type CacheType = (typeof CacheType)[keyof typeof CacheType];\n\n/**\n * More Cache related constants\n */\nexport const APP_METADATA = \"appmetadata\";\nexport const CLIENT_INFO = \"client_info\";\nexport const THE_FAMILY_ID = \"1\";\n\nexport const AUTHORITY_METADATA_CONSTANTS = {\n CACHE_KEY: \"authority-metadata\",\n REFRESH_TIME_SECONDS: 3600 * 24, // 24 Hours\n};\n\nexport const AuthorityMetadataSource = {\n CONFIG: \"config\",\n CACHE: \"cache\",\n NETWORK: \"network\",\n HARDCODED_VALUES: \"hardcoded_values\",\n} as const;\nexport type AuthorityMetadataSource =\n (typeof AuthorityMetadataSource)[keyof typeof AuthorityMetadataSource];\n\nexport const SERVER_TELEM_CONSTANTS = {\n SCHEMA_VERSION: 5,\n MAX_CUR_HEADER_BYTES: 80, // ESTS limit is 100B, set to 80 to provide a 20B buffer\n MAX_LAST_HEADER_BYTES: 330, // ESTS limit is 350B, set to 330 to provide a 20B buffer,\n MAX_CACHED_ERRORS: 50, // Limit the number of errors that can be stored to prevent uncontrolled size gains\n CACHE_KEY: \"server-telemetry\",\n CATEGORY_SEPARATOR: \"|\",\n VALUE_SEPARATOR: \",\",\n OVERFLOW_TRUE: \"1\",\n OVERFLOW_FALSE: \"0\",\n UNKNOWN_ERROR: \"unknown_error\",\n};\n\n/**\n * Type of the authentication request\n */\nexport const AuthenticationScheme = {\n BEARER: \"Bearer\",\n POP: \"pop\",\n SSH: \"ssh-cert\",\n} as const;\nexport type AuthenticationScheme =\n (typeof AuthenticationScheme)[keyof typeof AuthenticationScheme];\n\n/**\n * Constants related to throttling\n */\nexport const ThrottlingConstants = {\n // Default time to throttle RequestThumbprint in seconds\n DEFAULT_THROTTLE_TIME_SECONDS: 60,\n // Default maximum time to throttle in seconds, overrides what the server sends back\n DEFAULT_MAX_THROTTLE_TIME_SECONDS: 3600,\n // Prefix for storing throttling entries\n THROTTLING_PREFIX: \"throttling\",\n // Value assigned to the x-ms-lib-capability header to indicate to the server the library supports throttling\n X_MS_LIB_CAPABILITY_VALUE: \"retry-after, h429\",\n};\n\nexport const Errors = {\n INVALID_GRANT_ERROR: \"invalid_grant\",\n CLIENT_MISMATCH_ERROR: \"client_mismatch\",\n};\n\n/**\n * Password grant parameters\n */\nexport const PasswordGrantConstants = {\n username: \"username\",\n password: \"password\",\n} as const;\nexport type PasswordGrantConstants =\n (typeof PasswordGrantConstants)[keyof typeof PasswordGrantConstants];\n\n/**\n * Region Discovery Sources\n */\nexport const RegionDiscoverySources = {\n FAILED_AUTO_DETECTION: \"1\",\n INTERNAL_CACHE: \"2\",\n ENVIRONMENT_VARIABLE: \"3\",\n IMDS: \"4\",\n} as const;\nexport type RegionDiscoverySources =\n (typeof RegionDiscoverySources)[keyof typeof RegionDiscoverySources];\n\n/**\n * Region Discovery Outcomes\n */\nexport const RegionDiscoveryOutcomes = {\n CONFIGURED_MATCHES_DETECTED: \"1\",\n CONFIGURED_NO_AUTO_DETECTION: \"2\",\n CONFIGURED_NOT_DETECTED: \"3\",\n AUTO_DETECTION_REQUESTED_SUCCESSFUL: \"4\",\n AUTO_DETECTION_REQUESTED_FAILED: \"5\",\n} as const;\nexport type RegionDiscoveryOutcomes =\n (typeof RegionDiscoveryOutcomes)[keyof typeof RegionDiscoveryOutcomes];\n\n/**\n * Specifies the reason for fetching the access token from the identity provider\n */\nexport const CacheOutcome = {\n // When a token is found in the cache or the cache is not supposed to be hit when making the request\n NOT_APPLICABLE: \"0\",\n // When the token request goes to the identity provider because force_refresh was set to true. Also occurs if claims were requested\n FORCE_REFRESH_OR_CLAIMS: \"1\",\n // When the token request goes to the identity provider because no cached access token exists\n NO_CACHED_ACCESS_TOKEN: \"2\",\n // When the token request goes to the identity provider because cached access token expired\n CACHED_ACCESS_TOKEN_EXPIRED: \"3\",\n // When the token request goes to the identity provider because refresh_in was used and the existing token needs to be refreshed\n PROACTIVELY_REFRESHED: \"4\",\n} as const;\nexport type CacheOutcome = (typeof CacheOutcome)[keyof typeof CacheOutcome];\n\nexport const JsonWebTokenTypes = {\n Jwt: \"JWT\",\n Jwk: \"JWK\",\n Pop: \"pop\",\n} as const;\nexport type JsonWebTokenTypes =\n (typeof JsonWebTokenTypes)[keyof typeof JsonWebTokenTypes];\n\nexport const ONE_DAY_IN_MS = 86400000;\n\n// Token renewal offset default in seconds\nexport const DEFAULT_TOKEN_RENEWAL_OFFSET_SEC = 300;\n\nexport const EncodingTypes = {\n BASE64: \"base64\",\n HEX: \"hex\",\n UTF8: \"utf-8\",\n} as const;\nexport type EncodingTypes = (typeof EncodingTypes)[keyof typeof EncodingTypes];\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * AuthErrorMessage class containing string constants used by error codes and messages.\n */\nexport const unexpectedError = \"unexpected_error\";\nexport const postRequestFailed = \"post_request_failed\";\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Constants } from \"../utils/Constants.js\";\nimport * as AuthErrorCodes from \"./AuthErrorCodes.js\";\nexport { AuthErrorCodes };\n\nexport const AuthErrorMessages = {\n [AuthErrorCodes.unexpectedError]: \"Unexpected error in authentication.\",\n [AuthErrorCodes.postRequestFailed]:\n \"Post request failed from the network, could be a 4xx/5xx or a network unavailability. Please check the exact error code for details.\",\n};\n\n/**\n * AuthErrorMessage class containing string constants used by error codes and messages.\n * @deprecated Use AuthErrorCodes instead\n */\nexport const AuthErrorMessage = {\n unexpectedError: {\n code: AuthErrorCodes.unexpectedError,\n desc: AuthErrorMessages[AuthErrorCodes.unexpectedError],\n },\n postRequestFailed: {\n code: AuthErrorCodes.postRequestFailed,\n desc: AuthErrorMessages[AuthErrorCodes.postRequestFailed],\n },\n};\n\n/**\n * General error class thrown by the MSAL.js library.\n */\nexport class AuthError extends Error {\n /**\n * Short string denoting error\n */\n errorCode: string;\n\n /**\n * Detailed description of error\n */\n errorMessage: string;\n\n /**\n * Describes the subclass of an error\n */\n subError: string;\n\n /**\n * CorrelationId associated with the error\n */\n correlationId: string;\n\n constructor(errorCode?: string, errorMessage?: string, suberror?: string) {\n const errorString = errorMessage\n ? `${errorCode}: ${errorMessage}`\n : errorCode;\n super(errorString);\n Object.setPrototypeOf(this, AuthError.prototype);\n\n this.errorCode = errorCode || Constants.EMPTY_STRING;\n this.errorMessage = errorMessage || Constants.EMPTY_STRING;\n this.subError = suberror || Constants.EMPTY_STRING;\n this.name = \"AuthError\";\n }\n\n setCorrelationId(correlationId: string): void {\n this.correlationId = correlationId;\n }\n}\n\nexport function createAuthError(\n code: string,\n additionalMessage?: string\n): AuthError {\n return new AuthError(\n code,\n additionalMessage\n ? `${AuthErrorMessages[code]} ${additionalMessage}`\n : AuthErrorMessages[code]\n );\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const clientInfoDecodingError = \"client_info_decoding_error\";\nexport const clientInfoEmptyError = \"client_info_empty_error\";\nexport const tokenParsingError = \"token_parsing_error\";\nexport const nullOrEmptyToken = \"null_or_empty_token\";\nexport const endpointResolutionError = \"endpoints_resolution_error\";\nexport const networkError = \"network_error\";\nexport const openIdConfigError = \"openid_config_error\";\nexport const hashNotDeserialized = \"hash_not_deserialized\";\nexport const invalidState = \"invalid_state\";\nexport const stateMismatch = \"state_mismatch\";\nexport const stateNotFound = \"state_not_found\";\nexport const nonceMismatch = \"nonce_mismatch\";\nexport const authTimeNotFound = \"auth_time_not_found\";\nexport const maxAgeTranspired = \"max_age_transpired\";\nexport const multipleMatchingTokens = \"multiple_matching_tokens\";\nexport const multipleMatchingAccounts = \"multiple_matching_accounts\";\nexport const multipleMatchingAppMetadata = \"multiple_matching_appMetadata\";\nexport const requestCannotBeMade = \"request_cannot_be_made\";\nexport const cannotRemoveEmptyScope = \"cannot_remove_empty_scope\";\nexport const cannotAppendScopeSet = \"cannot_append_scopeset\";\nexport const emptyInputScopeSet = \"empty_input_scopeset\";\nexport const deviceCodePollingCancelled = \"device_code_polling_cancelled\";\nexport const deviceCodeExpired = \"device_code_expired\";\nexport const deviceCodeUnknownError = \"device_code_unknown_error\";\nexport const noAccountInSilentRequest = \"no_account_in_silent_request\";\nexport const invalidCacheRecord = \"invalid_cache_record\";\nexport const invalidCacheEnvironment = \"invalid_cache_environment\";\nexport const noAccountFound = \"no_account_found\";\nexport const noCryptoObject = \"no_crypto_object\";\nexport const unexpectedCredentialType = \"unexpected_credential_type\";\nexport const invalidAssertion = \"invalid_assertion\";\nexport const invalidClientCredential = \"invalid_client_credential\";\nexport const tokenRefreshRequired = \"token_refresh_required\";\nexport const userTimeoutReached = \"user_timeout_reached\";\nexport const tokenClaimsCnfRequiredForSignedJwt =\n \"token_claims_cnf_required_for_signedjwt\";\nexport const authorizationCodeMissingFromServerResponse =\n \"authorization_code_missing_from_server_response\";\nexport const bindingKeyNotRemoved = \"binding_key_not_removed\";\nexport const endSessionEndpointNotSupported =\n \"end_session_endpoint_not_supported\";\nexport const keyIdMissing = \"key_id_missing\";\nexport const noNetworkConnectivity = \"no_network_connectivity\";\nexport const userCanceled = \"user_canceled\";\nexport const missingTenantIdError = \"missing_tenant_id_error\";\nexport const methodNotImplemented = \"method_not_implemented\";\nexport const nestedAppAuthBridgeDisabled = \"nested_app_auth_bridge_disabled\";\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthError } from \"./AuthError.js\";\nimport * as ClientAuthErrorCodes from \"./ClientAuthErrorCodes.js\";\nexport { ClientAuthErrorCodes }; // Allow importing as \"ClientAuthErrorCodes\";\n\n/**\n * ClientAuthErrorMessage class containing string constants used by error codes and messages.\n */\n\nexport const ClientAuthErrorMessages = {\n [ClientAuthErrorCodes.clientInfoDecodingError]:\n \"The client info could not be parsed/decoded correctly\",\n [ClientAuthErrorCodes.clientInfoEmptyError]: \"The client info was empty\",\n [ClientAuthErrorCodes.tokenParsingError]: \"Token cannot be parsed\",\n [ClientAuthErrorCodes.nullOrEmptyToken]: \"The token is null or empty\",\n [ClientAuthErrorCodes.endpointResolutionError]:\n \"Endpoints cannot be resolved\",\n [ClientAuthErrorCodes.networkError]: \"Network request failed\",\n [ClientAuthErrorCodes.openIdConfigError]:\n \"Could not retrieve endpoints. Check your authority and verify the .well-known/openid-configuration endpoint returns the required endpoints.\",\n [ClientAuthErrorCodes.hashNotDeserialized]:\n \"The hash parameters could not be deserialized\",\n [ClientAuthErrorCodes.invalidState]: \"State was not the expected format\",\n [ClientAuthErrorCodes.stateMismatch]: \"State mismatch error\",\n [ClientAuthErrorCodes.stateNotFound]: \"State not found\",\n [ClientAuthErrorCodes.nonceMismatch]: \"Nonce mismatch error\",\n [ClientAuthErrorCodes.authTimeNotFound]:\n \"Max Age was requested and the ID token is missing the auth_time variable.\" +\n \" auth_time is an optional claim and is not enabled by default - it must be enabled.\" +\n \" See https://aka.ms/msaljs/optional-claims for more information.\",\n [ClientAuthErrorCodes.maxAgeTranspired]:\n \"Max Age is set to 0, or too much time has elapsed since the last end-user authentication.\",\n [ClientAuthErrorCodes.multipleMatchingTokens]:\n \"The cache contains multiple tokens satisfying the requirements. \" +\n \"Call AcquireToken again providing more requirements such as authority or account.\",\n [ClientAuthErrorCodes.multipleMatchingAccounts]:\n \"The cache contains multiple accounts satisfying the given parameters. Please pass more info to obtain the correct account\",\n [ClientAuthErrorCodes.multipleMatchingAppMetadata]:\n \"The cache contains multiple appMetadata satisfying the given parameters. Please pass more info to obtain the correct appMetadata\",\n [ClientAuthErrorCodes.requestCannotBeMade]:\n \"Token request cannot be made without authorization code or refresh token.\",\n [ClientAuthErrorCodes.cannotRemoveEmptyScope]:\n \"Cannot remove null or empty scope from ScopeSet\",\n [ClientAuthErrorCodes.cannotAppendScopeSet]: \"Cannot append ScopeSet\",\n [ClientAuthErrorCodes.emptyInputScopeSet]:\n \"Empty input ScopeSet cannot be processed\",\n [ClientAuthErrorCodes.deviceCodePollingCancelled]:\n \"Caller has cancelled token endpoint polling during device code flow by setting DeviceCodeRequest.cancel = true.\",\n [ClientAuthErrorCodes.deviceCodeExpired]: \"Device code is expired.\",\n [ClientAuthErrorCodes.deviceCodeUnknownError]:\n \"Device code stopped polling for unknown reasons.\",\n [ClientAuthErrorCodes.noAccountInSilentRequest]:\n \"Please pass an account object, silent flow is not supported without account information\",\n [ClientAuthErrorCodes.invalidCacheRecord]:\n \"Cache record object was null or undefined.\",\n [ClientAuthErrorCodes.invalidCacheEnvironment]:\n \"Invalid environment when attempting to create cache entry\",\n [ClientAuthErrorCodes.noAccountFound]:\n \"No account found in cache for given key.\",\n [ClientAuthErrorCodes.noCryptoObject]: \"No crypto object detected.\",\n [ClientAuthErrorCodes.unexpectedCredentialType]:\n \"Unexpected credential type.\",\n [ClientAuthErrorCodes.invalidAssertion]:\n \"Client assertion must meet requirements described in https://tools.ietf.org/html/rfc7515\",\n [ClientAuthErrorCodes.invalidClientCredential]:\n \"Client credential (secret, certificate, or assertion) must not be empty when creating a confidential client. An application should at most have one credential\",\n [ClientAuthErrorCodes.tokenRefreshRequired]:\n \"Cannot return token from cache because it must be refreshed. This may be due to one of the following reasons: forceRefresh parameter is set to true, claims have been requested, there is no cached access token or it is expired.\",\n [ClientAuthErrorCodes.userTimeoutReached]:\n \"User defined timeout for device code polling reached\",\n [ClientAuthErrorCodes.tokenClaimsCnfRequiredForSignedJwt]:\n \"Cannot generate a POP jwt if the token_claims are not populated\",\n [ClientAuthErrorCodes.authorizationCodeMissingFromServerResponse]:\n \"Server response does not contain an authorization code to proceed\",\n [ClientAuthErrorCodes.bindingKeyNotRemoved]:\n \"Could not remove the credential's binding key from storage.\",\n [ClientAuthErrorCodes.endSessionEndpointNotSupported]:\n \"The provided authority does not support logout\",\n [ClientAuthErrorCodes.keyIdMissing]:\n \"A keyId value is missing from the requested bound token's cache record and is required to match the token to it's stored binding key.\",\n [ClientAuthErrorCodes.noNetworkConnectivity]:\n \"No network connectivity. Check your internet connection.\",\n [ClientAuthErrorCodes.userCanceled]: \"User cancelled the flow.\",\n [ClientAuthErrorCodes.missingTenantIdError]:\n \"A tenant id - not common, organizations, or consumers - must be specified when using the client_credentials flow.\",\n [ClientAuthErrorCodes.methodNotImplemented]:\n \"This method has not been implemented\",\n [ClientAuthErrorCodes.nestedAppAuthBridgeDisabled]:\n \"The nested app auth bridge is disabled\",\n};\n\n/**\n * String constants used by error codes and messages.\n * @deprecated Use ClientAuthErrorCodes instead\n */\nexport const ClientAuthErrorMessage = {\n clientInfoDecodingError: {\n code: ClientAuthErrorCodes.clientInfoDecodingError,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.clientInfoDecodingError\n ],\n },\n clientInfoEmptyError: {\n code: ClientAuthErrorCodes.clientInfoEmptyError,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.clientInfoEmptyError\n ],\n },\n tokenParsingError: {\n code: ClientAuthErrorCodes.tokenParsingError,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.tokenParsingError],\n },\n nullOrEmptyToken: {\n code: ClientAuthErrorCodes.nullOrEmptyToken,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.nullOrEmptyToken],\n },\n endpointResolutionError: {\n code: ClientAuthErrorCodes.endpointResolutionError,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.endpointResolutionError\n ],\n },\n networkError: {\n code: ClientAuthErrorCodes.networkError,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.networkError],\n },\n unableToGetOpenidConfigError: {\n code: ClientAuthErrorCodes.openIdConfigError,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.openIdConfigError],\n },\n hashNotDeserialized: {\n code: ClientAuthErrorCodes.hashNotDeserialized,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.hashNotDeserialized],\n },\n invalidStateError: {\n code: ClientAuthErrorCodes.invalidState,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.invalidState],\n },\n stateMismatchError: {\n code: ClientAuthErrorCodes.stateMismatch,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.stateMismatch],\n },\n stateNotFoundError: {\n code: ClientAuthErrorCodes.stateNotFound,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.stateNotFound],\n },\n nonceMismatchError: {\n code: ClientAuthErrorCodes.nonceMismatch,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.nonceMismatch],\n },\n authTimeNotFoundError: {\n code: ClientAuthErrorCodes.authTimeNotFound,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.authTimeNotFound],\n },\n maxAgeTranspired: {\n code: ClientAuthErrorCodes.maxAgeTranspired,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.maxAgeTranspired],\n },\n multipleMatchingTokens: {\n code: ClientAuthErrorCodes.multipleMatchingTokens,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.multipleMatchingTokens\n ],\n },\n multipleMatchingAccounts: {\n code: ClientAuthErrorCodes.multipleMatchingAccounts,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.multipleMatchingAccounts\n ],\n },\n multipleMatchingAppMetadata: {\n code: ClientAuthErrorCodes.multipleMatchingAppMetadata,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.multipleMatchingAppMetadata\n ],\n },\n tokenRequestCannotBeMade: {\n code: ClientAuthErrorCodes.requestCannotBeMade,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.requestCannotBeMade],\n },\n removeEmptyScopeError: {\n code: ClientAuthErrorCodes.cannotRemoveEmptyScope,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.cannotRemoveEmptyScope\n ],\n },\n appendScopeSetError: {\n code: ClientAuthErrorCodes.cannotAppendScopeSet,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.cannotAppendScopeSet\n ],\n },\n emptyInputScopeSetError: {\n code: ClientAuthErrorCodes.emptyInputScopeSet,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.emptyInputScopeSet],\n },\n DeviceCodePollingCancelled: {\n code: ClientAuthErrorCodes.deviceCodePollingCancelled,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.deviceCodePollingCancelled\n ],\n },\n DeviceCodeExpired: {\n code: ClientAuthErrorCodes.deviceCodeExpired,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.deviceCodeExpired],\n },\n DeviceCodeUnknownError: {\n code: ClientAuthErrorCodes.deviceCodeUnknownError,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.deviceCodeUnknownError\n ],\n },\n NoAccountInSilentRequest: {\n code: ClientAuthErrorCodes.noAccountInSilentRequest,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.noAccountInSilentRequest\n ],\n },\n invalidCacheRecord: {\n code: ClientAuthErrorCodes.invalidCacheRecord,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.invalidCacheRecord],\n },\n invalidCacheEnvironment: {\n code: ClientAuthErrorCodes.invalidCacheEnvironment,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.invalidCacheEnvironment\n ],\n },\n noAccountFound: {\n code: ClientAuthErrorCodes.noAccountFound,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.noAccountFound],\n },\n noCryptoObj: {\n code: ClientAuthErrorCodes.noCryptoObject,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.noCryptoObject],\n },\n unexpectedCredentialType: {\n code: ClientAuthErrorCodes.unexpectedCredentialType,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.unexpectedCredentialType\n ],\n },\n invalidAssertion: {\n code: ClientAuthErrorCodes.invalidAssertion,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.invalidAssertion],\n },\n invalidClientCredential: {\n code: ClientAuthErrorCodes.invalidClientCredential,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.invalidClientCredential\n ],\n },\n tokenRefreshRequired: {\n code: ClientAuthErrorCodes.tokenRefreshRequired,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.tokenRefreshRequired\n ],\n },\n userTimeoutReached: {\n code: ClientAuthErrorCodes.userTimeoutReached,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.userTimeoutReached],\n },\n tokenClaimsRequired: {\n code: ClientAuthErrorCodes.tokenClaimsCnfRequiredForSignedJwt,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.tokenClaimsCnfRequiredForSignedJwt\n ],\n },\n noAuthorizationCodeFromServer: {\n code: ClientAuthErrorCodes.authorizationCodeMissingFromServerResponse,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.authorizationCodeMissingFromServerResponse\n ],\n },\n bindingKeyNotRemovedError: {\n code: ClientAuthErrorCodes.bindingKeyNotRemoved,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.bindingKeyNotRemoved\n ],\n },\n logoutNotSupported: {\n code: ClientAuthErrorCodes.endSessionEndpointNotSupported,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.endSessionEndpointNotSupported\n ],\n },\n keyIdMissing: {\n code: ClientAuthErrorCodes.keyIdMissing,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.keyIdMissing],\n },\n noNetworkConnectivity: {\n code: ClientAuthErrorCodes.noNetworkConnectivity,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.noNetworkConnectivity\n ],\n },\n userCanceledError: {\n code: ClientAuthErrorCodes.userCanceled,\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.userCanceled],\n },\n missingTenantIdError: {\n code: ClientAuthErrorCodes.missingTenantIdError,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.missingTenantIdError\n ],\n },\n nestedAppAuthBridgeDisabled: {\n code: ClientAuthErrorCodes.nestedAppAuthBridgeDisabled,\n desc: ClientAuthErrorMessages[\n ClientAuthErrorCodes.nestedAppAuthBridgeDisabled\n ],\n },\n};\n\n/**\n * Error thrown when there is an error in the client code running on the browser.\n */\nexport class ClientAuthError extends AuthError {\n constructor(errorCode: string, additionalMessage?: string) {\n super(\n errorCode,\n additionalMessage\n ? `${ClientAuthErrorMessages[errorCode]}: ${additionalMessage}`\n : ClientAuthErrorMessages[errorCode]\n );\n this.name = \"ClientAuthError\";\n\n Object.setPrototypeOf(this, ClientAuthError.prototype);\n }\n}\n\nexport function createClientAuthError(\n errorCode: string,\n additionalMessage?: string\n): ClientAuthError {\n return new ClientAuthError(errorCode, additionalMessage);\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n} from \"../error/ClientAuthError.js\";\nimport type { BaseAuthRequest } from \"../request/BaseAuthRequest.js\";\nimport type { ShrOptions, SignedHttpRequest } from \"./SignedHttpRequest.js\";\n\n/**\n * The PkceCodes type describes the structure\n * of objects that contain PKCE code\n * challenge and verifier pairs\n */\nexport type PkceCodes = {\n verifier: string;\n challenge: string;\n};\n\nexport type SignedHttpRequestParameters = Pick<\n BaseAuthRequest,\n | \"resourceRequestMethod\"\n | \"resourceRequestUri\"\n | \"shrClaims\"\n | \"shrNonce\"\n | \"shrOptions\"\n> & {\n correlationId?: string;\n};\n\n/**\n * Interface for crypto functions used by library\n */\nexport interface ICrypto {\n /**\n * Creates a guid randomly.\n */\n createNewGuid(): string;\n /**\n * base64 Encode string\n * @param input\n */\n base64Encode(input: string): string;\n /**\n * base64 decode string\n * @param input\n */\n base64Decode(input: string): string;\n /**\n * base64 URL safe encoded string\n */\n base64UrlEncode(input: string): string;\n /**\n * Stringifies and base64Url encodes input public key\n * @param inputKid\n * @returns Base64Url encoded public key\n */\n encodeKid(inputKid: string): string;\n /**\n * Generates an JWK RSA S256 Thumbprint\n * @param request\n */\n getPublicKeyThumbprint(\n request: SignedHttpRequestParameters\n ): Promise;\n /**\n * Removes cryptographic keypair from key store matching the keyId passed in\n * @param kid\n */\n removeTokenBindingKey(kid: string): Promise;\n /**\n * Removes all cryptographic keys from IndexedDB storage\n */\n clearKeystore(): Promise;\n /**\n * Returns a signed proof-of-possession token with a given acces token that contains a cnf claim with the required kid.\n * @param accessToken\n */\n signJwt(\n payload: SignedHttpRequest,\n kid: string,\n shrOptions?: ShrOptions,\n correlationId?: string\n ): Promise;\n /**\n * Returns the SHA-256 hash of an input string\n * @param plainText\n */\n hashString(plainText: string): Promise;\n}\n\nexport const DEFAULT_CRYPTO_IMPLEMENTATION: ICrypto = {\n createNewGuid: (): string => {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n },\n base64Decode: (): string => {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n },\n base64Encode: (): string => {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n },\n base64UrlEncode: (): string => {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n },\n encodeKid: (): string => {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n },\n async getPublicKeyThumbprint(): Promise {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n },\n async removeTokenBindingKey(): Promise {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n },\n async clearKeystore(): Promise {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n },\n async signJwt(): Promise {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n },\n async hashString(): Promise {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n },\n};\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { LoggerOptions } from \"../config/ClientConfiguration.js\";\nimport { Constants } from \"../utils/Constants.js\";\n\n/**\n * Options for logger messages.\n */\nexport type LoggerMessageOptions = {\n logLevel: LogLevel;\n containsPii?: boolean;\n context?: string;\n correlationId?: string;\n};\n\n/**\n * Log message level.\n */\nexport enum LogLevel {\n Error,\n Warning,\n Info,\n Verbose,\n Trace,\n}\n\n/**\n * Callback to send the messages to.\n */\nexport interface ILoggerCallback {\n (level: LogLevel, message: string, containsPii: boolean): void;\n}\n\n/**\n * Class which facilitates logging of messages to a specific place.\n */\nexport class Logger {\n // Correlation ID for request, usually set by user.\n private correlationId: string;\n\n // Current log level, defaults to info.\n private level: LogLevel = LogLevel.Info;\n\n // Boolean describing whether PII logging is allowed.\n private piiLoggingEnabled: boolean;\n\n // Callback to send messages to.\n private localCallback: ILoggerCallback;\n\n // Package name implementing this logger\n private packageName: string;\n\n // Package version implementing this logger\n private packageVersion: string;\n\n constructor(\n loggerOptions: LoggerOptions,\n packageName?: string,\n packageVersion?: string\n ) {\n const defaultLoggerCallback = () => {\n return;\n };\n const setLoggerOptions =\n loggerOptions || Logger.createDefaultLoggerOptions();\n this.localCallback =\n setLoggerOptions.loggerCallback || defaultLoggerCallback;\n this.piiLoggingEnabled = setLoggerOptions.piiLoggingEnabled || false;\n this.level =\n typeof setLoggerOptions.logLevel === \"number\"\n ? setLoggerOptions.logLevel\n : LogLevel.Info;\n this.correlationId =\n setLoggerOptions.correlationId || Constants.EMPTY_STRING;\n this.packageName = packageName || Constants.EMPTY_STRING;\n this.packageVersion = packageVersion || Constants.EMPTY_STRING;\n }\n\n private static createDefaultLoggerOptions(): LoggerOptions {\n return {\n loggerCallback: () => {\n // allow users to not set loggerCallback\n },\n piiLoggingEnabled: false,\n logLevel: LogLevel.Info,\n };\n }\n\n /**\n * Create new Logger with existing configurations.\n */\n public clone(\n packageName: string,\n packageVersion: string,\n correlationId?: string\n ): Logger {\n return new Logger(\n {\n loggerCallback: this.localCallback,\n piiLoggingEnabled: this.piiLoggingEnabled,\n logLevel: this.level,\n correlationId: correlationId || this.correlationId,\n },\n packageName,\n packageVersion\n );\n }\n\n /**\n * Log message with required options.\n */\n private logMessage(\n logMessage: string,\n options: LoggerMessageOptions\n ): void {\n if (\n options.logLevel > this.level ||\n (!this.piiLoggingEnabled && options.containsPii)\n ) {\n return;\n }\n const timestamp = new Date().toUTCString();\n\n // Add correlationId to logs if set, correlationId provided on log messages take precedence\n const logHeader = `[${timestamp}] : [${\n options.correlationId || this.correlationId || \"\"\n }]`;\n\n const log = `${logHeader} : ${this.packageName}@${\n this.packageVersion\n } : ${LogLevel[options.logLevel]} - ${logMessage}`;\n // debug(`msal:${LogLevel[options.logLevel]}${options.containsPii ? \"-Pii\": Constants.EMPTY_STRING}${options.context ? `:${options.context}` : Constants.EMPTY_STRING}`)(logMessage);\n this.executeCallback(\n options.logLevel,\n log,\n options.containsPii || false\n );\n }\n\n /**\n * Execute callback with message.\n */\n executeCallback(\n level: LogLevel,\n message: string,\n containsPii: boolean\n ): void {\n if (this.localCallback) {\n this.localCallback(level, message, containsPii);\n }\n }\n\n /**\n * Logs error messages.\n */\n error(message: string, correlationId?: string): void {\n this.logMessage(message, {\n logLevel: LogLevel.Error,\n containsPii: false,\n correlationId: correlationId || Constants.EMPTY_STRING,\n });\n }\n\n /**\n * Logs error messages with PII.\n */\n errorPii(message: string, correlationId?: string): void {\n this.logMessage(message, {\n logLevel: LogLevel.Error,\n containsPii: true,\n correlationId: correlationId || Constants.EMPTY_STRING,\n });\n }\n\n /**\n * Logs warning messages.\n */\n warning(message: string, correlationId?: string): void {\n this.logMessage(message, {\n logLevel: LogLevel.Warning,\n containsPii: false,\n correlationId: correlationId || Constants.EMPTY_STRING,\n });\n }\n\n /**\n * Logs warning messages with PII.\n */\n warningPii(message: string, correlationId?: string): void {\n this.logMessage(message, {\n logLevel: LogLevel.Warning,\n containsPii: true,\n correlationId: correlationId || Constants.EMPTY_STRING,\n });\n }\n\n /**\n * Logs info messages.\n */\n info(message: string, correlationId?: string): void {\n this.logMessage(message, {\n logLevel: LogLevel.Info,\n containsPii: false,\n correlationId: correlationId || Constants.EMPTY_STRING,\n });\n }\n\n /**\n * Logs info messages with PII.\n */\n infoPii(message: string, correlationId?: string): void {\n this.logMessage(message, {\n logLevel: LogLevel.Info,\n containsPii: true,\n correlationId: correlationId || Constants.EMPTY_STRING,\n });\n }\n\n /**\n * Logs verbose messages.\n */\n verbose(message: string, correlationId?: string): void {\n this.logMessage(message, {\n logLevel: LogLevel.Verbose,\n containsPii: false,\n correlationId: correlationId || Constants.EMPTY_STRING,\n });\n }\n\n /**\n * Logs verbose messages with PII.\n */\n verbosePii(message: string, correlationId?: string): void {\n this.logMessage(message, {\n logLevel: LogLevel.Verbose,\n containsPii: true,\n correlationId: correlationId || Constants.EMPTY_STRING,\n });\n }\n\n /**\n * Logs trace messages.\n */\n trace(message: string, correlationId?: string): void {\n this.logMessage(message, {\n logLevel: LogLevel.Trace,\n containsPii: false,\n correlationId: correlationId || Constants.EMPTY_STRING,\n });\n }\n\n /**\n * Logs trace messages with PII.\n */\n tracePii(message: string, correlationId?: string): void {\n this.logMessage(message, {\n logLevel: LogLevel.Trace,\n containsPii: true,\n correlationId: correlationId || Constants.EMPTY_STRING,\n });\n }\n\n /**\n * Returns whether PII Logging is enabled or not.\n */\n isPiiLoggingEnabled(): boolean {\n return this.piiLoggingEnabled || false;\n }\n}\n", "/* eslint-disable header/header */\nexport const name = \"@azure/msal-common\";\nexport const version = \"15.12.0\";\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ProtocolMode } from \"./ProtocolMode.js\";\nimport { OIDCOptions } from \"./OIDCOptions.js\";\nimport { AzureRegionConfiguration } from \"./AzureRegionConfiguration.js\";\nimport { CloudInstanceDiscoveryResponse } from \"./CloudInstanceDiscoveryResponse.js\";\n\nexport type AuthorityOptions = {\n protocolMode: ProtocolMode;\n OIDCOptions?: OIDCOptions | null;\n knownAuthorities: Array;\n cloudDiscoveryMetadata: string;\n authorityMetadata: string;\n skipAuthorityMetadataCache?: boolean;\n azureRegionConfiguration?: AzureRegionConfiguration;\n authority?: string;\n};\n\nexport type StaticAuthorityOptions = Partial<\n Pick\n> & {\n canonicalAuthority?: string;\n cloudDiscoveryMetadata?: CloudInstanceDiscoveryResponse;\n};\n\nexport const AzureCloudInstance = {\n // AzureCloudInstance is not specified.\n None: \"none\",\n\n // Microsoft Azure public cloud\n AzurePublic: \"https://login.microsoftonline.com\",\n\n // Microsoft PPE\n AzurePpe: \"https://login.windows-ppe.net\",\n\n // Microsoft Chinese national/regional cloud\n AzureChina: \"https://login.chinacloudapi.cn\",\n\n // Microsoft German national/regional cloud (\"Black Forest\")\n AzureGermany: \"https://login.microsoftonline.de\",\n\n // US Government cloud\n AzureUsGovernment: \"https://login.microsoftonline.us\",\n} as const;\nexport type AzureCloudInstance =\n (typeof AzureCloudInstance)[keyof typeof AzureCloudInstance];\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const redirectUriEmpty = \"redirect_uri_empty\";\nexport const claimsRequestParsingError = \"claims_request_parsing_error\";\nexport const authorityUriInsecure = \"authority_uri_insecure\";\nexport const urlParseError = \"url_parse_error\";\nexport const urlEmptyError = \"empty_url_error\";\nexport const emptyInputScopesError = \"empty_input_scopes_error\";\nexport const invalidClaims = \"invalid_claims\";\nexport const tokenRequestEmpty = \"token_request_empty\";\nexport const logoutRequestEmpty = \"logout_request_empty\";\nexport const invalidCodeChallengeMethod = \"invalid_code_challenge_method\";\nexport const pkceParamsMissing = \"pkce_params_missing\";\nexport const invalidCloudDiscoveryMetadata = \"invalid_cloud_discovery_metadata\";\nexport const invalidAuthorityMetadata = \"invalid_authority_metadata\";\nexport const untrustedAuthority = \"untrusted_authority\";\nexport const missingSshJwk = \"missing_ssh_jwk\";\nexport const missingSshKid = \"missing_ssh_kid\";\nexport const missingNonceAuthenticationHeader =\n \"missing_nonce_authentication_header\";\nexport const invalidAuthenticationHeader = \"invalid_authentication_header\";\nexport const cannotSetOIDCOptions = \"cannot_set_OIDCOptions\";\nexport const cannotAllowPlatformBroker = \"cannot_allow_platform_broker\";\nexport const authorityMismatch = \"authority_mismatch\";\nexport const invalidRequestMethodForEAR = \"invalid_request_method_for_EAR\";\nexport const invalidAuthorizePostBodyParameters =\n \"invalid_authorize_post_body_parameters\";\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthError } from \"./AuthError.js\";\nimport * as ClientConfigurationErrorCodes from \"./ClientConfigurationErrorCodes.js\";\nexport { ClientConfigurationErrorCodes };\n\nexport const ClientConfigurationErrorMessages = {\n [ClientConfigurationErrorCodes.redirectUriEmpty]:\n \"A redirect URI is required for all calls, and none has been set.\",\n [ClientConfigurationErrorCodes.claimsRequestParsingError]:\n \"Could not parse the given claims request object.\",\n [ClientConfigurationErrorCodes.authorityUriInsecure]:\n \"Authority URIs must use https. Please see here for valid authority configuration options: https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-js-initializing-client-applications#configuration-options\",\n [ClientConfigurationErrorCodes.urlParseError]:\n \"URL could not be parsed into appropriate segments.\",\n [ClientConfigurationErrorCodes.urlEmptyError]: \"URL was empty or null.\",\n [ClientConfigurationErrorCodes.emptyInputScopesError]:\n \"Scopes cannot be passed as null, undefined or empty array because they are required to obtain an access token.\",\n [ClientConfigurationErrorCodes.invalidClaims]:\n \"Given claims parameter must be a stringified JSON object.\",\n [ClientConfigurationErrorCodes.tokenRequestEmpty]:\n \"Token request was empty and not found in cache.\",\n [ClientConfigurationErrorCodes.logoutRequestEmpty]:\n \"The logout request was null or undefined.\",\n [ClientConfigurationErrorCodes.invalidCodeChallengeMethod]:\n 'code_challenge_method passed is invalid. Valid values are \"plain\" and \"S256\".',\n [ClientConfigurationErrorCodes.pkceParamsMissing]:\n \"Both params: code_challenge and code_challenge_method are to be passed if to be sent in the request\",\n [ClientConfigurationErrorCodes.invalidCloudDiscoveryMetadata]:\n \"Invalid cloudDiscoveryMetadata provided. Must be a stringified JSON object containing tenant_discovery_endpoint and metadata fields\",\n [ClientConfigurationErrorCodes.invalidAuthorityMetadata]:\n \"Invalid authorityMetadata provided. Must by a stringified JSON object containing authorization_endpoint, token_endpoint, issuer fields.\",\n [ClientConfigurationErrorCodes.untrustedAuthority]:\n \"The provided authority is not a trusted authority. Please include this authority in the knownAuthorities config parameter.\",\n [ClientConfigurationErrorCodes.missingSshJwk]:\n \"Missing sshJwk in SSH certificate request. A stringified JSON Web Key is required when using the SSH authentication scheme.\",\n [ClientConfigurationErrorCodes.missingSshKid]:\n \"Missing sshKid in SSH certificate request. A string that uniquely identifies the public SSH key is required when using the SSH authentication scheme.\",\n [ClientConfigurationErrorCodes.missingNonceAuthenticationHeader]:\n \"Unable to find an authentication header containing server nonce. Either the Authentication-Info or WWW-Authenticate headers must be present in order to obtain a server nonce.\",\n [ClientConfigurationErrorCodes.invalidAuthenticationHeader]:\n \"Invalid authentication header provided\",\n [ClientConfigurationErrorCodes.cannotSetOIDCOptions]:\n \"Cannot set OIDCOptions parameter. Please change the protocol mode to OIDC or use a non-Microsoft authority.\",\n [ClientConfigurationErrorCodes.cannotAllowPlatformBroker]:\n \"Cannot set allowPlatformBroker parameter to true when not in AAD protocol mode.\",\n [ClientConfigurationErrorCodes.authorityMismatch]:\n \"Authority mismatch error. Authority provided in login request or PublicClientApplication config does not match the environment of the provided account. Please use a matching account or make an interactive request to login to this authority.\",\n [ClientConfigurationErrorCodes.invalidAuthorizePostBodyParameters]:\n \"Invalid authorize post body parameters provided. If you are using authorizePostBodyParameters, the request method must be POST. Please check the request method and parameters.\",\n [ClientConfigurationErrorCodes.invalidRequestMethodForEAR]:\n \"Invalid request method for EAR protocol mode. The request method cannot be GET when using EAR protocol mode. Please change the request method to POST.\",\n};\n\n/**\n * ClientConfigurationErrorMessage class containing string constants used by error codes and messages.\n * @deprecated Use ClientConfigurationErrorCodes instead\n */\nexport const ClientConfigurationErrorMessage = {\n redirectUriNotSet: {\n code: ClientConfigurationErrorCodes.redirectUriEmpty,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.redirectUriEmpty\n ],\n },\n claimsRequestParsingError: {\n code: ClientConfigurationErrorCodes.claimsRequestParsingError,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.claimsRequestParsingError\n ],\n },\n authorityUriInsecure: {\n code: ClientConfigurationErrorCodes.authorityUriInsecure,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.authorityUriInsecure\n ],\n },\n urlParseError: {\n code: ClientConfigurationErrorCodes.urlParseError,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.urlParseError\n ],\n },\n urlEmptyError: {\n code: ClientConfigurationErrorCodes.urlEmptyError,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.urlEmptyError\n ],\n },\n emptyScopesError: {\n code: ClientConfigurationErrorCodes.emptyInputScopesError,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.emptyInputScopesError\n ],\n },\n invalidClaimsRequest: {\n code: ClientConfigurationErrorCodes.invalidClaims,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.invalidClaims\n ],\n },\n tokenRequestEmptyError: {\n code: ClientConfigurationErrorCodes.tokenRequestEmpty,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.tokenRequestEmpty\n ],\n },\n logoutRequestEmptyError: {\n code: ClientConfigurationErrorCodes.logoutRequestEmpty,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.logoutRequestEmpty\n ],\n },\n invalidCodeChallengeMethod: {\n code: ClientConfigurationErrorCodes.invalidCodeChallengeMethod,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.invalidCodeChallengeMethod\n ],\n },\n invalidCodeChallengeParams: {\n code: ClientConfigurationErrorCodes.pkceParamsMissing,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.pkceParamsMissing\n ],\n },\n invalidCloudDiscoveryMetadata: {\n code: ClientConfigurationErrorCodes.invalidCloudDiscoveryMetadata,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.invalidCloudDiscoveryMetadata\n ],\n },\n invalidAuthorityMetadata: {\n code: ClientConfigurationErrorCodes.invalidAuthorityMetadata,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.invalidAuthorityMetadata\n ],\n },\n untrustedAuthority: {\n code: ClientConfigurationErrorCodes.untrustedAuthority,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.untrustedAuthority\n ],\n },\n missingSshJwk: {\n code: ClientConfigurationErrorCodes.missingSshJwk,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.missingSshJwk\n ],\n },\n missingSshKid: {\n code: ClientConfigurationErrorCodes.missingSshKid,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.missingSshKid\n ],\n },\n missingNonceAuthenticationHeader: {\n code: ClientConfigurationErrorCodes.missingNonceAuthenticationHeader,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.missingNonceAuthenticationHeader\n ],\n },\n invalidAuthenticationHeader: {\n code: ClientConfigurationErrorCodes.invalidAuthenticationHeader,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.invalidAuthenticationHeader\n ],\n },\n cannotSetOIDCOptions: {\n code: ClientConfigurationErrorCodes.cannotSetOIDCOptions,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.cannotSetOIDCOptions\n ],\n },\n cannotAllowPlatformBroker: {\n code: ClientConfigurationErrorCodes.cannotAllowPlatformBroker,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.cannotAllowPlatformBroker\n ],\n },\n authorityMismatch: {\n code: ClientConfigurationErrorCodes.authorityMismatch,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.authorityMismatch\n ],\n },\n invalidAuthorizePostBodyParameters: {\n code: ClientConfigurationErrorCodes.invalidAuthorizePostBodyParameters,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.invalidAuthorizePostBodyParameters\n ],\n },\n invalidRequestMethodForEAR: {\n code: ClientConfigurationErrorCodes.invalidRequestMethodForEAR,\n desc: ClientConfigurationErrorMessages[\n ClientConfigurationErrorCodes.invalidRequestMethodForEAR\n ],\n },\n};\n\n/**\n * Error thrown when there is an error in configuration of the MSAL.js library.\n */\nexport class ClientConfigurationError extends AuthError {\n constructor(errorCode: string) {\n super(errorCode, ClientConfigurationErrorMessages[errorCode]);\n this.name = \"ClientConfigurationError\";\n Object.setPrototypeOf(this, ClientConfigurationError.prototype);\n }\n}\n\nexport function createClientConfigurationError(\n errorCode: string\n): ClientConfigurationError {\n return new ClientConfigurationError(errorCode);\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * @hidden\n */\nexport class StringUtils {\n /**\n * Check if stringified object is empty\n * @param strObj\n */\n static isEmptyObj(strObj?: string): boolean {\n if (strObj) {\n try {\n const obj = JSON.parse(strObj);\n return Object.keys(obj).length === 0;\n } catch (e) {}\n }\n return true;\n }\n\n static startsWith(str: string, search: string): boolean {\n return str.indexOf(search) === 0;\n }\n\n static endsWith(str: string, search: string): boolean {\n return (\n str.length >= search.length &&\n str.lastIndexOf(search) === str.length - search.length\n );\n }\n\n /**\n * Parses string into an object.\n *\n * @param query\n */\n static queryStringToObject(query: string): T {\n const obj: {} = {};\n const params = query.split(\"&\");\n const decode = (s: string) => decodeURIComponent(s.replace(/\\+/g, \" \"));\n params.forEach((pair) => {\n if (pair.trim()) {\n const [key, value] = pair.split(/=(.+)/g, 2); // Split on the first occurence of the '=' character\n if (key && value) {\n obj[decode(key)] = decode(value);\n }\n }\n });\n return obj as T;\n }\n\n /**\n * Trims entries in an array.\n *\n * @param arr\n */\n static trimArrayEntries(arr: Array): Array {\n return arr.map((entry) => entry.trim());\n }\n\n /**\n * Removes empty strings from array\n * @param arr\n */\n static removeEmptyStringsFromArray(arr: Array): Array {\n return arr.filter((entry) => {\n return !!entry;\n });\n }\n\n /**\n * Attempts to parse a string into JSON\n * @param str\n */\n static jsonParseHelper(str: string): T | null {\n try {\n return JSON.parse(str) as T;\n } catch (e) {\n return null;\n }\n }\n\n /**\n * Tests if a given string matches a given pattern, with support for wildcards and queries.\n * @param pattern Wildcard pattern to string match. Supports \"*\" for wildcards and \"?\" for queries\n * @param input String to match against\n */\n static matchPattern(pattern: string, input: string): boolean {\n /**\n * Wildcard support: https://stackoverflow.com/a/3117248/4888559\n * Queries: replaces \"?\" in string with escaped \"\\?\" for regex test\n */\n // eslint-disable-next-line security/detect-non-literal-regexp\n const regex: RegExp = new RegExp(\n pattern\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\\*/g, \"[^ ]*\")\n .replace(/\\?/g, \"\\\\?\")\n );\n\n return regex.test(input);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n createClientConfigurationError,\n ClientConfigurationErrorCodes,\n} from \"../error/ClientConfigurationError.js\";\nimport { StringUtils } from \"../utils/StringUtils.js\";\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n} from \"../error/ClientAuthError.js\";\nimport {\n Constants,\n OIDC_SCOPES,\n OIDC_DEFAULT_SCOPES,\n} from \"../utils/Constants.js\";\n\n/**\n * The ScopeSet class creates a set of scopes. Scopes are case-insensitive, unique values, so the Set object in JS makes\n * the most sense to implement for this class. All scopes are trimmed and converted to lower case strings in intersection and union functions\n * to ensure uniqueness of strings.\n */\nexport class ScopeSet {\n // Scopes as a Set of strings\n private scopes: Set;\n\n constructor(inputScopes: Array) {\n // Filter empty string and null/undefined array items\n const scopeArr = inputScopes\n ? StringUtils.trimArrayEntries([...inputScopes])\n : [];\n const filteredInput = scopeArr\n ? StringUtils.removeEmptyStringsFromArray(scopeArr)\n : [];\n\n // Check if scopes array has at least one member\n if (!filteredInput || !filteredInput.length) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.emptyInputScopesError\n );\n }\n\n this.scopes = new Set(); // Iterator in constructor not supported by IE11\n filteredInput.forEach((scope) => this.scopes.add(scope));\n }\n\n /**\n * Factory method to create ScopeSet from space-delimited string\n * @param inputScopeString\n * @param appClientId\n * @param scopesRequired\n */\n static fromString(inputScopeString: string): ScopeSet {\n const scopeString = inputScopeString || Constants.EMPTY_STRING;\n const inputScopes: Array = scopeString.split(\" \");\n return new ScopeSet(inputScopes);\n }\n\n /**\n * Creates the set of scopes to search for in cache lookups\n * @param inputScopeString\n * @returns\n */\n static createSearchScopes(inputScopeString: Array): ScopeSet {\n // Handle empty scopes by using default OIDC scopes for cache lookup\n const scopesToUse =\n inputScopeString && inputScopeString.length > 0\n ? inputScopeString\n : [...OIDC_DEFAULT_SCOPES];\n\n const scopeSet = new ScopeSet(scopesToUse);\n if (!scopeSet.containsOnlyOIDCScopes()) {\n scopeSet.removeOIDCScopes();\n } else {\n scopeSet.removeScope(Constants.OFFLINE_ACCESS_SCOPE);\n }\n\n return scopeSet;\n }\n\n /**\n * Check if a given scope is present in this set of scopes.\n * @param scope\n */\n containsScope(scope: string): boolean {\n const lowerCaseScopes = this.printScopesLowerCase().split(\" \");\n const lowerCaseScopesSet = new ScopeSet(lowerCaseScopes);\n // compare lowercase scopes\n return scope\n ? lowerCaseScopesSet.scopes.has(scope.toLowerCase())\n : false;\n }\n\n /**\n * Check if a set of scopes is present in this set of scopes.\n * @param scopeSet\n */\n containsScopeSet(scopeSet: ScopeSet): boolean {\n if (!scopeSet || scopeSet.scopes.size <= 0) {\n return false;\n }\n\n return (\n this.scopes.size >= scopeSet.scopes.size &&\n scopeSet.asArray().every((scope) => this.containsScope(scope))\n );\n }\n\n /**\n * Check if set of scopes contains only the defaults\n */\n containsOnlyOIDCScopes(): boolean {\n let defaultScopeCount = 0;\n OIDC_SCOPES.forEach((defaultScope: string) => {\n if (this.containsScope(defaultScope)) {\n defaultScopeCount += 1;\n }\n });\n\n return this.scopes.size === defaultScopeCount;\n }\n\n /**\n * Appends single scope if passed\n * @param newScope\n */\n appendScope(newScope: string): void {\n if (newScope) {\n this.scopes.add(newScope.trim());\n }\n }\n\n /**\n * Appends multiple scopes if passed\n * @param newScopes\n */\n appendScopes(newScopes: Array): void {\n try {\n newScopes.forEach((newScope) => this.appendScope(newScope));\n } catch (e) {\n throw createClientAuthError(\n ClientAuthErrorCodes.cannotAppendScopeSet\n );\n }\n }\n\n /**\n * Removes element from set of scopes.\n * @param scope\n */\n removeScope(scope: string): void {\n if (!scope) {\n throw createClientAuthError(\n ClientAuthErrorCodes.cannotRemoveEmptyScope\n );\n }\n this.scopes.delete(scope.trim());\n }\n\n /**\n * Removes default scopes from set of scopes\n * Primarily used to prevent cache misses if the default scopes are not returned from the server\n */\n removeOIDCScopes(): void {\n OIDC_SCOPES.forEach((defaultScope: string) => {\n this.scopes.delete(defaultScope);\n });\n }\n\n /**\n * Combines an array of scopes with the current set of scopes.\n * @param otherScopes\n */\n unionScopeSets(otherScopes: ScopeSet): Set {\n if (!otherScopes) {\n throw createClientAuthError(\n ClientAuthErrorCodes.emptyInputScopeSet\n );\n }\n const unionScopes = new Set(); // Iterator in constructor not supported in IE11\n otherScopes.scopes.forEach((scope) =>\n unionScopes.add(scope.toLowerCase())\n );\n this.scopes.forEach((scope) => unionScopes.add(scope.toLowerCase()));\n return unionScopes;\n }\n\n /**\n * Check if scopes intersect between this set and another.\n * @param otherScopes\n */\n intersectingScopeSets(otherScopes: ScopeSet): boolean {\n if (!otherScopes) {\n throw createClientAuthError(\n ClientAuthErrorCodes.emptyInputScopeSet\n );\n }\n\n // Do not allow OIDC scopes to be the only intersecting scopes\n if (!otherScopes.containsOnlyOIDCScopes()) {\n otherScopes.removeOIDCScopes();\n }\n const unionScopes = this.unionScopeSets(otherScopes);\n const sizeOtherScopes = otherScopes.getScopeCount();\n const sizeThisScopes = this.getScopeCount();\n const sizeUnionScopes = unionScopes.size;\n return sizeUnionScopes < sizeThisScopes + sizeOtherScopes;\n }\n\n /**\n * Returns size of set of scopes.\n */\n getScopeCount(): number {\n return this.scopes.size;\n }\n\n /**\n * Returns the scopes as an array of string values\n */\n asArray(): Array {\n const array: Array = [];\n this.scopes.forEach((val) => array.push(val));\n return array;\n }\n\n /**\n * Prints scopes into a space-delimited string\n */\n printScopes(): string {\n if (this.scopes) {\n const scopeArr = this.asArray();\n return scopeArr.join(\" \");\n }\n return Constants.EMPTY_STRING;\n }\n\n /**\n * Prints scopes into a space-delimited lower-case string (used for caching)\n */\n printScopesLowerCase(): string {\n return this.printScopes().toLowerCase();\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TokenClaims } from \"./TokenClaims.js\";\n/**\n * Account object with the following signature:\n * - homeAccountId - Home account identifier for this account object\n * - environment - Entity which issued the token represented by the domain of the issuer (e.g. login.microsoftonline.com)\n * - tenantId - Full tenant or organizational id that this account belongs to\n * - username - preferred_username claim of the id_token that represents this account\n * - localAccountId - Local, tenant-specific account identifer for this account object, usually used in legacy cases\n * - name - Full name for the account, including given name and family name\n * - idToken - raw ID token\n * - idTokenClaims - Object contains claims from ID token\n * - nativeAccountId - The user's native account ID\n * - tenantProfiles - Map of tenant profile objects for each tenant that the account has authenticated with in the browser\n */\nexport type AccountInfo = {\n homeAccountId: string;\n environment: string;\n tenantId: string;\n username: string;\n localAccountId: string;\n loginHint?: string;\n name?: string;\n idToken?: string;\n idTokenClaims?: TokenClaims & {\n [key: string]:\n | string\n | number\n | string[]\n | object\n | undefined\n | unknown;\n };\n nativeAccountId?: string;\n authorityType?: string;\n tenantProfiles?: Map;\n};\n\n/**\n * Account details that vary across tenants for the same user\n */\nexport type TenantProfile = Pick<\n AccountInfo,\n \"tenantId\" | \"localAccountId\" | \"name\" | \"username\" | \"loginHint\"\n> & {\n /**\n * - isHomeTenant - True if this is the home tenant profile of the account, false if it's a guest tenant profile\n */\n isHomeTenant?: boolean;\n};\n\nexport type ActiveAccountFilters = {\n homeAccountId: string;\n localAccountId: string;\n tenantId?: string;\n lastUpdatedAt?: string;\n};\n\n/**\n * Returns true if tenantId matches the utid portion of homeAccountId\n * @param tenantId\n * @param homeAccountId\n * @returns\n */\nexport function tenantIdMatchesHomeTenant(\n tenantId?: string,\n homeAccountId?: string\n): boolean {\n return (\n !!tenantId &&\n !!homeAccountId &&\n tenantId === homeAccountId.split(\".\")[1]\n );\n}\n\n/**\n * Build tenant profile\n * @param homeAccountId - Home account identifier for this account object\n * @param localAccountId - Local account identifer for this account object\n * @param tenantId - Full tenant or organizational id that this account belongs to\n * @param idTokenClaims - Claims from the ID token\n * @returns\n */\nexport function buildTenantProfile(\n homeAccountId: string,\n localAccountId: string,\n tenantId: string,\n idTokenClaims?: TokenClaims\n): TenantProfile {\n if (idTokenClaims) {\n const {\n oid,\n sub,\n tid,\n name,\n tfp,\n acr,\n preferred_username,\n upn,\n login_hint,\n } = idTokenClaims;\n\n /**\n * Since there is no way to determine if the authority is AAD or B2C, we exhaust all the possible claims that can serve as tenant ID with the following precedence:\n * tid - TenantID claim that identifies the tenant that issued the token in AAD. Expected in all AAD ID tokens, not present in B2C ID Tokens.\n * tfp - Trust Framework Policy claim that identifies the policy that was used to authenticate the user. Functions as tenant for B2C scenarios.\n * acr - Authentication Context Class Reference claim used only with older B2C policies. Fallback in case tfp is not present, but likely won't be present anyway.\n */\n const tenantId = tid || tfp || acr || \"\";\n\n return {\n tenantId: tenantId,\n localAccountId: oid || sub || \"\",\n name: name,\n username: preferred_username || upn || \"\",\n loginHint: login_hint,\n isHomeTenant: tenantIdMatchesHomeTenant(tenantId, homeAccountId),\n };\n } else {\n return {\n tenantId,\n localAccountId,\n username: \"\",\n isHomeTenant: tenantIdMatchesHomeTenant(tenantId, homeAccountId),\n };\n }\n}\n\n/**\n * Replaces account info that varies by tenant profile sourced from the ID token claims passed in with the tenant-specific account info\n * @param baseAccountInfo\n * @param idTokenClaims\n * @returns\n */\nexport function updateAccountTenantProfileData(\n baseAccountInfo: AccountInfo,\n tenantProfile?: TenantProfile,\n idTokenClaims?: TokenClaims,\n idTokenSecret?: string\n): AccountInfo {\n let updatedAccountInfo = baseAccountInfo;\n // Tenant Profile overrides passed in account info\n if (tenantProfile) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { isHomeTenant, ...tenantProfileOverride } = tenantProfile;\n updatedAccountInfo = { ...baseAccountInfo, ...tenantProfileOverride };\n }\n\n // ID token claims override passed in account info and tenant profile\n if (idTokenClaims) {\n // Ignore isHomeTenant, loginHint, and sid which are part of tenant profile but not base account info\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { isHomeTenant, ...claimsSourcedTenantProfile } =\n buildTenantProfile(\n baseAccountInfo.homeAccountId,\n baseAccountInfo.localAccountId,\n baseAccountInfo.tenantId,\n idTokenClaims\n );\n\n updatedAccountInfo = {\n ...updatedAccountInfo,\n ...claimsSourcedTenantProfile,\n idTokenClaims: idTokenClaims,\n idToken: idTokenSecret,\n };\n\n return updatedAccountInfo;\n }\n\n return updatedAccountInfo;\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TokenClaims } from \"./TokenClaims.js\";\nimport {\n createClientAuthError,\n ClientAuthErrorCodes,\n} from \"../error/ClientAuthError.js\";\n\n/**\n * Extract token by decoding the rawToken\n *\n * @param encodedToken\n */\nexport function extractTokenClaims(\n encodedToken: string,\n base64Decode: (input: string) => string\n): TokenClaims {\n const jswPayload = getJWSPayload(encodedToken);\n\n // token will be decoded to get the username\n try {\n // base64Decode() should throw an error if there is an issue\n const base64Decoded = base64Decode(jswPayload);\n return JSON.parse(base64Decoded) as TokenClaims;\n } catch (err) {\n throw createClientAuthError(ClientAuthErrorCodes.tokenParsingError);\n }\n}\n\n/**\n * decode a JWT\n *\n * @param authToken\n */\nexport function getJWSPayload(authToken: string): string {\n if (!authToken) {\n throw createClientAuthError(ClientAuthErrorCodes.nullOrEmptyToken);\n }\n const tokenPartsRegex = /^([^\\.\\s]*)\\.([^\\.\\s]+)\\.([^\\.\\s]*)$/;\n const matches = tokenPartsRegex.exec(authToken);\n if (!matches || matches.length < 4) {\n throw createClientAuthError(ClientAuthErrorCodes.tokenParsingError);\n }\n /**\n * const crackedToken = {\n * header: matches[1],\n * JWSPayload: matches[2],\n * JWSSig: matches[3],\n * };\n */\n\n return matches[2];\n}\n\n/**\n * Determine if the token's max_age has transpired\n */\nexport function checkMaxAge(authTime: number, maxAge: number): void {\n /*\n * per https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest\n * To force an immediate re-authentication: If an app requires that a user re-authenticate prior to access,\n * provide a value of 0 for the max_age parameter and the AS will force a fresh login.\n */\n const fiveMinuteSkew = 300000; // five minutes in milliseconds\n if (maxAge === 0 || Date.now() - fiveMinuteSkew > authTime + maxAge) {\n throw createClientAuthError(ClientAuthErrorCodes.maxAgeTranspired);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthorizeResponse } from \"../response/AuthorizeResponse.js\";\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n} from \"../error/ClientAuthError.js\";\nimport { StringDict } from \"./MsalTypes.js\";\nimport { StringUtils } from \"./StringUtils.js\";\n\n/**\n * Canonicalizes a URL by making it lowercase and ensuring it ends with /\n * Inlined version of UrlString.canonicalizeUri to avoid circular dependency\n * @param url - URL to canonicalize\n * @returns Canonicalized URL\n */\nfunction canonicalizeUrl(url: string): string {\n if (!url) {\n return url;\n }\n\n let lowerCaseUrl = url.toLowerCase();\n\n if (StringUtils.endsWith(lowerCaseUrl, \"?\")) {\n lowerCaseUrl = lowerCaseUrl.slice(0, -1);\n } else if (StringUtils.endsWith(lowerCaseUrl, \"?/\")) {\n lowerCaseUrl = lowerCaseUrl.slice(0, -2);\n }\n\n if (!StringUtils.endsWith(lowerCaseUrl, \"/\")) {\n lowerCaseUrl += \"/\";\n }\n\n return lowerCaseUrl;\n}\n\n/**\n * Parses hash string from given string. Returns empty string if no hash symbol is found.\n * @param hashString\n */\nexport function stripLeadingHashOrQuery(responseString: string): string {\n if (responseString.startsWith(\"#/\")) {\n return responseString.substring(2);\n } else if (\n responseString.startsWith(\"#\") ||\n responseString.startsWith(\"?\")\n ) {\n return responseString.substring(1);\n }\n\n return responseString;\n}\n\n/**\n * Returns URL hash as server auth code response object.\n */\nexport function getDeserializedResponse(\n responseString: string\n): AuthorizeResponse | null {\n // Check if given hash is empty\n if (!responseString || responseString.indexOf(\"=\") < 0) {\n return null;\n }\n try {\n // Strip the # or ? symbol if present\n const normalizedResponse = stripLeadingHashOrQuery(responseString);\n // If # symbol was not present, above will return empty string, so give original hash value\n const deserializedHash: AuthorizeResponse = Object.fromEntries(\n new URLSearchParams(normalizedResponse)\n );\n\n // Check for known response properties\n if (\n deserializedHash.code ||\n deserializedHash.ear_jwe ||\n deserializedHash.error ||\n deserializedHash.error_description ||\n deserializedHash.state\n ) {\n return deserializedHash;\n }\n } catch (e) {\n throw createClientAuthError(ClientAuthErrorCodes.hashNotDeserialized);\n }\n\n return null;\n}\n\n/**\n * Utility to create a URL from the params map\n */\nexport function mapToQueryString(\n parameters: Map,\n encodeExtraParams: boolean = true,\n extraQueryParameters?: StringDict\n): string {\n const queryParameterArray: Array = new Array();\n\n parameters.forEach((value, key) => {\n if (\n !encodeExtraParams &&\n extraQueryParameters &&\n key in extraQueryParameters\n ) {\n queryParameterArray.push(`${key}=${value}`);\n } else {\n queryParameterArray.push(`${key}=${encodeURIComponent(value)}`);\n }\n });\n\n return queryParameterArray.join(\"&\");\n}\n\n/**\n * Normalizes URLs for comparison by removing hash, canonicalizing,\n * and ensuring consistent URL encoding in query parameters.\n * This fixes redirect loops when URLs contain encoded characters like apostrophes (%27).\n * @param url - URL to normalize\n * @returns Normalized URL string for comparison\n */\nexport function normalizeUrlForComparison(url: string): string {\n if (!url) {\n return url;\n }\n\n // Remove hash first\n const urlWithoutHash = url.split(\"#\")[0];\n\n try {\n // Parse the URL to handle encoding consistently\n const urlObj = new URL(urlWithoutHash);\n\n /*\n * Reconstruct the URL with properly decoded query parameters\n * This ensures that %27 and ' are treated as equivalent\n */\n const normalizedUrl = urlObj.origin + urlObj.pathname + urlObj.search;\n\n // Apply canonicalization logic inline to avoid circular dependency\n return canonicalizeUrl(normalizedUrl);\n } catch (e) {\n // Fallback to original logic if URL parsing fails\n return canonicalizeUrl(urlWithoutHash);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n createClientConfigurationError,\n ClientConfigurationErrorCodes,\n} from \"../error/ClientConfigurationError.js\";\nimport { StringUtils } from \"../utils/StringUtils.js\";\nimport { IUri } from \"./IUri.js\";\nimport { AADAuthorityConstants, Constants } from \"../utils/Constants.js\";\nimport * as UrlUtils from \"../utils/UrlUtils.js\";\n\n/**\n * Url object class which can perform various transformations on url strings.\n */\nexport class UrlString {\n // internal url string field\n private _urlString: string;\n public get urlString(): string {\n return this._urlString;\n }\n\n constructor(url: string) {\n this._urlString = url;\n if (!this._urlString) {\n // Throws error if url is empty\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.urlEmptyError\n );\n }\n\n if (!url.includes(\"#\")) {\n this._urlString = UrlString.canonicalizeUri(url);\n }\n }\n\n /**\n * Ensure urls are lower case and end with a / character.\n * @param url\n */\n static canonicalizeUri(url: string): string {\n if (url) {\n let lowerCaseUrl = url.toLowerCase();\n\n if (StringUtils.endsWith(lowerCaseUrl, \"?\")) {\n lowerCaseUrl = lowerCaseUrl.slice(0, -1);\n } else if (StringUtils.endsWith(lowerCaseUrl, \"?/\")) {\n lowerCaseUrl = lowerCaseUrl.slice(0, -2);\n }\n\n if (!StringUtils.endsWith(lowerCaseUrl, \"/\")) {\n lowerCaseUrl += \"/\";\n }\n\n return lowerCaseUrl;\n }\n\n return url;\n }\n\n /**\n * Throws if urlString passed is not a valid authority URI string.\n */\n validateAsUri(): void {\n // Attempts to parse url for uri components\n let components;\n try {\n components = this.getUrlComponents();\n } catch (e) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.urlParseError\n );\n }\n\n // Throw error if URI or path segments are not parseable.\n if (!components.HostNameAndPort || !components.PathSegments) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.urlParseError\n );\n }\n\n // Throw error if uri is insecure.\n if (\n !components.Protocol ||\n components.Protocol.toLowerCase() !== \"https:\"\n ) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.authorityUriInsecure\n );\n }\n }\n\n /**\n * Given a url and a query string return the url with provided query string appended\n * @param url\n * @param queryString\n */\n static appendQueryString(url: string, queryString: string): string {\n if (!queryString) {\n return url;\n }\n\n return url.indexOf(\"?\") < 0\n ? `${url}?${queryString}`\n : `${url}&${queryString}`;\n }\n\n /**\n * Returns a url with the hash removed\n * @param url\n */\n static removeHashFromUrl(url: string): string {\n return UrlString.canonicalizeUri(url.split(\"#\")[0]);\n }\n\n /**\n * Given a url like https://a:b/common/d?e=f#g, and a tenantId, returns https://a:b/tenantId/d\n * @param href The url\n * @param tenantId The tenant id to replace\n */\n replaceTenantPath(tenantId: string): UrlString {\n const urlObject = this.getUrlComponents();\n const pathArray = urlObject.PathSegments;\n if (\n tenantId &&\n pathArray.length !== 0 &&\n (pathArray[0] === AADAuthorityConstants.COMMON ||\n pathArray[0] === AADAuthorityConstants.ORGANIZATIONS)\n ) {\n pathArray[0] = tenantId;\n }\n return UrlString.constructAuthorityUriFromObject(urlObject);\n }\n\n /**\n * Parses out the components from a url string.\n * @returns An object with the various components. Please cache this value insted of calling this multiple times on the same url.\n */\n getUrlComponents(): IUri {\n // https://gist.github.com/curtisz/11139b2cfcaef4a261e0\n const regEx = RegExp(\n \"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\\\?([^#]*))?(#(.*))?\"\n );\n\n // If url string does not match regEx, we throw an error\n const match = this.urlString.match(regEx);\n if (!match) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.urlParseError\n );\n }\n\n // Url component object\n const urlComponents = {\n Protocol: match[1],\n HostNameAndPort: match[4],\n AbsolutePath: match[5],\n QueryString: match[7],\n } as IUri;\n\n let pathSegments = urlComponents.AbsolutePath.split(\"/\");\n pathSegments = pathSegments.filter((val) => val && val.length > 0); // remove empty elements\n urlComponents.PathSegments = pathSegments;\n\n if (\n urlComponents.QueryString &&\n urlComponents.QueryString.endsWith(\"/\")\n ) {\n urlComponents.QueryString = urlComponents.QueryString.substring(\n 0,\n urlComponents.QueryString.length - 1\n );\n }\n return urlComponents;\n }\n\n static getDomainFromUrl(url: string): string {\n const regEx = RegExp(\"^([^:/?#]+://)?([^/?#]*)\");\n\n const match = url.match(regEx);\n\n if (!match) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.urlParseError\n );\n }\n\n return match[2];\n }\n\n static getAbsoluteUrl(relativeUrl: string, baseUrl: string): string {\n if (relativeUrl[0] === Constants.FORWARD_SLASH) {\n const url = new UrlString(baseUrl);\n const baseComponents = url.getUrlComponents();\n\n return (\n baseComponents.Protocol +\n \"//\" +\n baseComponents.HostNameAndPort +\n relativeUrl\n );\n }\n\n return relativeUrl;\n }\n\n static constructAuthorityUriFromObject(urlObject: IUri): UrlString {\n return new UrlString(\n urlObject.Protocol +\n \"//\" +\n urlObject.HostNameAndPort +\n \"/\" +\n urlObject.PathSegments.join(\"/\")\n );\n }\n\n /**\n * Check if the hash of the URL string contains known properties\n * @deprecated This API will be removed in a future version\n */\n static hashContainsKnownProperties(response: string): boolean {\n return !!UrlUtils.getDeserializedResponse(response);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Logger } from \"../logger/Logger.js\";\nimport { UrlString } from \"../url/UrlString.js\";\nimport { AuthorityMetadataSource } from \"../utils/Constants.js\";\nimport { StaticAuthorityOptions } from \"./AuthorityOptions.js\";\nimport { CloudDiscoveryMetadata } from \"./CloudDiscoveryMetadata.js\";\nimport { CloudInstanceDiscoveryResponse } from \"./CloudInstanceDiscoveryResponse.js\";\nimport { OpenIdConfigResponse } from \"./OpenIdConfigResponse.js\";\n\ntype RawMetadata = {\n endpointMetadata: { [key: string]: OpenIdConfigResponse };\n instanceDiscoveryMetadata: CloudInstanceDiscoveryResponse;\n};\n\nexport const rawMetdataJSON: RawMetadata = {\n endpointMetadata: {\n \"login.microsoftonline.com\": {\n token_endpoint:\n \"https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/token\",\n jwks_uri:\n \"https://login.microsoftonline.com/{tenantid}/discovery/v2.0/keys\",\n issuer: \"https://login.microsoftonline.com/{tenantid}/v2.0\",\n authorization_endpoint:\n \"https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/authorize\",\n end_session_endpoint:\n \"https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/logout\",\n },\n \"login.chinacloudapi.cn\": {\n token_endpoint:\n \"https://login.chinacloudapi.cn/{tenantid}/oauth2/v2.0/token\",\n jwks_uri:\n \"https://login.chinacloudapi.cn/{tenantid}/discovery/v2.0/keys\",\n issuer: \"https://login.partner.microsoftonline.cn/{tenantid}/v2.0\",\n authorization_endpoint:\n \"https://login.chinacloudapi.cn/{tenantid}/oauth2/v2.0/authorize\",\n end_session_endpoint:\n \"https://login.chinacloudapi.cn/{tenantid}/oauth2/v2.0/logout\",\n },\n \"login.microsoftonline.us\": {\n token_endpoint:\n \"https://login.microsoftonline.us/{tenantid}/oauth2/v2.0/token\",\n jwks_uri:\n \"https://login.microsoftonline.us/{tenantid}/discovery/v2.0/keys\",\n issuer: \"https://login.microsoftonline.us/{tenantid}/v2.0\",\n authorization_endpoint:\n \"https://login.microsoftonline.us/{tenantid}/oauth2/v2.0/authorize\",\n end_session_endpoint:\n \"https://login.microsoftonline.us/{tenantid}/oauth2/v2.0/logout\",\n },\n },\n instanceDiscoveryMetadata: {\n tenant_discovery_endpoint:\n \"https://{canonicalAuthority}/v2.0/.well-known/openid-configuration\",\n metadata: [\n {\n preferred_network: \"login.microsoftonline.com\",\n preferred_cache: \"login.windows.net\",\n aliases: [\n \"login.microsoftonline.com\",\n \"login.windows.net\",\n \"login.microsoft.com\",\n \"sts.windows.net\",\n ],\n },\n {\n preferred_network: \"login.partner.microsoftonline.cn\",\n preferred_cache: \"login.partner.microsoftonline.cn\",\n aliases: [\n \"login.partner.microsoftonline.cn\",\n \"login.chinacloudapi.cn\",\n ],\n },\n {\n preferred_network: \"login.microsoftonline.de\",\n preferred_cache: \"login.microsoftonline.de\",\n aliases: [\"login.microsoftonline.de\"],\n },\n {\n preferred_network: \"login.microsoftonline.us\",\n preferred_cache: \"login.microsoftonline.us\",\n aliases: [\n \"login.microsoftonline.us\",\n \"login.usgovcloudapi.net\",\n ],\n },\n {\n preferred_network: \"login-us.microsoftonline.com\",\n preferred_cache: \"login-us.microsoftonline.com\",\n aliases: [\"login-us.microsoftonline.com\"],\n },\n ],\n },\n};\n\nexport const EndpointMetadata = rawMetdataJSON.endpointMetadata;\nexport const InstanceDiscoveryMetadata =\n rawMetdataJSON.instanceDiscoveryMetadata;\n\nexport const InstanceDiscoveryMetadataAliases: Set = new Set();\nInstanceDiscoveryMetadata.metadata.forEach(\n (metadataEntry: CloudDiscoveryMetadata) => {\n metadataEntry.aliases.forEach((alias: string) => {\n InstanceDiscoveryMetadataAliases.add(alias);\n });\n }\n);\n\n/**\n * Attempts to get an aliases array from the static authority metadata sources based on the canonical authority host\n * @param staticAuthorityOptions\n * @param logger\n * @returns\n */\nexport function getAliasesFromStaticSources(\n staticAuthorityOptions: StaticAuthorityOptions,\n logger?: Logger\n): string[] {\n let staticAliases: string[] | undefined;\n const canonicalAuthority = staticAuthorityOptions.canonicalAuthority;\n if (canonicalAuthority) {\n const authorityHost = new UrlString(\n canonicalAuthority\n ).getUrlComponents().HostNameAndPort;\n staticAliases =\n getAliasesFromMetadata(\n authorityHost,\n staticAuthorityOptions.cloudDiscoveryMetadata?.metadata,\n AuthorityMetadataSource.CONFIG,\n logger\n ) ||\n getAliasesFromMetadata(\n authorityHost,\n InstanceDiscoveryMetadata.metadata,\n AuthorityMetadataSource.HARDCODED_VALUES,\n logger\n ) ||\n staticAuthorityOptions.knownAuthorities;\n }\n\n return staticAliases || [];\n}\n\n/**\n * Returns aliases for from the raw cloud discovery metadata passed in\n * @param authorityHost\n * @param rawCloudDiscoveryMetadata\n * @returns\n */\nexport function getAliasesFromMetadata(\n authorityHost?: string,\n cloudDiscoveryMetadata?: CloudDiscoveryMetadata[],\n source?: AuthorityMetadataSource,\n logger?: Logger\n): string[] | null {\n logger?.trace(`getAliasesFromMetadata called with source: ${source}`);\n if (authorityHost && cloudDiscoveryMetadata) {\n const metadata = getCloudDiscoveryMetadataFromNetworkResponse(\n cloudDiscoveryMetadata,\n authorityHost\n );\n\n if (metadata) {\n logger?.trace(\n `getAliasesFromMetadata: found cloud discovery metadata in ${source}, returning aliases`\n );\n return metadata.aliases;\n } else {\n logger?.trace(\n `getAliasesFromMetadata: did not find cloud discovery metadata in ${source}`\n );\n }\n }\n\n return null;\n}\n\n/**\n * Get cloud discovery metadata for common authorities\n */\nexport function getCloudDiscoveryMetadataFromHardcodedValues(\n authorityHost: string\n): CloudDiscoveryMetadata | null {\n const metadata = getCloudDiscoveryMetadataFromNetworkResponse(\n InstanceDiscoveryMetadata.metadata,\n authorityHost\n );\n return metadata;\n}\n\n/**\n * Searches instance discovery network response for the entry that contains the host in the aliases list\n * @param response\n * @param authority\n */\nexport function getCloudDiscoveryMetadataFromNetworkResponse(\n response: CloudDiscoveryMetadata[],\n authorityHost: string\n): CloudDiscoveryMetadata | null {\n for (let i = 0; i < response.length; i++) {\n const metadata = response[i];\n if (metadata.aliases.includes(authorityHost)) {\n return metadata;\n }\n }\n\n return null;\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const cacheQuotaExceeded = \"cache_quota_exceeded\";\nexport const cacheErrorUnknown = \"cache_error_unknown\";\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthError } from \"./AuthError.js\";\nimport * as CacheErrorCodes from \"./CacheErrorCodes.js\";\nexport { CacheErrorCodes };\n\nexport const CacheErrorMessages = {\n [CacheErrorCodes.cacheQuotaExceeded]: \"Exceeded cache storage capacity.\",\n [CacheErrorCodes.cacheErrorUnknown]:\n \"Unexpected error occurred when using cache storage.\",\n};\n\n/**\n * Error thrown when there is an error with the cache\n */\nexport class CacheError extends AuthError {\n /**\n * Short string denoting error\n */\n errorCode: string;\n\n /**\n * Detailed description of error\n */\n errorMessage: string;\n\n constructor(errorCode: string, errorMessage?: string) {\n const message =\n errorMessage ||\n (CacheErrorMessages[errorCode]\n ? CacheErrorMessages[errorCode]\n : CacheErrorMessages[CacheErrorCodes.cacheErrorUnknown]);\n\n super(`${errorCode}: ${message}`);\n Object.setPrototypeOf(this, CacheError.prototype);\n\n this.name = \"CacheError\";\n this.errorCode = errorCode;\n this.errorMessage = message;\n }\n}\n\n/**\n * Helper function to wrap browser errors in a CacheError object\n * @param e\n * @returns\n */\nexport function createCacheError(e: unknown): CacheError {\n if (!(e instanceof Error)) {\n return new CacheError(CacheErrorCodes.cacheErrorUnknown);\n }\n\n if (\n e.name === \"QuotaExceededError\" ||\n e.name === \"NS_ERROR_DOM_QUOTA_REACHED\" ||\n e.message.includes(\"exceeded the quota\")\n ) {\n return new CacheError(CacheErrorCodes.cacheQuotaExceeded);\n } else {\n return new CacheError(e.name, e.message);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n AccountFilter,\n CredentialFilter,\n ValidCredentialType,\n AppMetadataFilter,\n AppMetadataCache,\n TokenKeys,\n TenantProfileFilter,\n} from \"./utils/CacheTypes.js\";\nimport { CacheRecord } from \"./entities/CacheRecord.js\";\nimport {\n CredentialType,\n APP_METADATA,\n THE_FAMILY_ID,\n AUTHORITY_METADATA_CONSTANTS,\n AuthenticationScheme,\n} from \"../utils/Constants.js\";\nimport { CredentialEntity } from \"./entities/CredentialEntity.js\";\nimport { ScopeSet } from \"../request/ScopeSet.js\";\nimport { AccountEntity } from \"./entities/AccountEntity.js\";\nimport { AccessTokenEntity } from \"./entities/AccessTokenEntity.js\";\nimport { IdTokenEntity } from \"./entities/IdTokenEntity.js\";\nimport { RefreshTokenEntity } from \"./entities/RefreshTokenEntity.js\";\nimport { ICacheManager } from \"./interface/ICacheManager.js\";\nimport {\n createClientAuthError,\n ClientAuthErrorCodes,\n} from \"../error/ClientAuthError.js\";\nimport {\n AccountInfo,\n TenantProfile,\n updateAccountTenantProfileData,\n} from \"../account/AccountInfo.js\";\nimport { AppMetadataEntity } from \"./entities/AppMetadataEntity.js\";\nimport { ServerTelemetryEntity } from \"./entities/ServerTelemetryEntity.js\";\nimport { ThrottlingEntity } from \"./entities/ThrottlingEntity.js\";\nimport { extractTokenClaims } from \"../account/AuthToken.js\";\nimport { ICrypto } from \"../crypto/ICrypto.js\";\nimport { AuthorityMetadataEntity } from \"./entities/AuthorityMetadataEntity.js\";\nimport { BaseAuthRequest } from \"../request/BaseAuthRequest.js\";\nimport { Logger } from \"../logger/Logger.js\";\nimport { name, version } from \"../packageMetadata.js\";\nimport { StoreInCache } from \"../request/StoreInCache.js\";\nimport { getAliasesFromStaticSources } from \"../authority/AuthorityMetadata.js\";\nimport { StaticAuthorityOptions } from \"../authority/AuthorityOptions.js\";\nimport { TokenClaims } from \"../account/TokenClaims.js\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\nimport { createCacheError } from \"../error/CacheError.js\";\nimport { AuthError } from \"../error/AuthError.js\";\n\n/**\n * Interface class which implement cache storage functions used by MSAL to perform validity checks, and store tokens.\n * @internal\n */\nexport abstract class CacheManager implements ICacheManager {\n protected clientId: string;\n protected cryptoImpl: ICrypto;\n // Instance of logger for functions defined in the msal-common layer\n private commonLogger: Logger;\n private staticAuthorityOptions?: StaticAuthorityOptions;\n protected performanceClient: IPerformanceClient;\n\n constructor(\n clientId: string,\n cryptoImpl: ICrypto,\n logger: Logger,\n performanceClient: IPerformanceClient,\n staticAuthorityOptions?: StaticAuthorityOptions\n ) {\n this.clientId = clientId;\n this.cryptoImpl = cryptoImpl;\n this.commonLogger = logger.clone(name, version);\n this.staticAuthorityOptions = staticAuthorityOptions;\n this.performanceClient = performanceClient;\n }\n\n /**\n * fetch the account entity from the platform cache\n * @param accountKey\n */\n abstract getAccount(\n accountKey: string,\n correlationId: string\n ): AccountEntity | null;\n\n /**\n * set account entity in the platform cache\n * @param account\n * @param correlationId\n */\n abstract setAccount(\n account: AccountEntity,\n correlationId: string\n ): Promise;\n\n /**\n * fetch the idToken entity from the platform cache\n * @param idTokenKey\n */\n abstract getIdTokenCredential(\n idTokenKey: string,\n correlationId: string\n ): IdTokenEntity | null;\n\n /**\n * set idToken entity to the platform cache\n * @param idToken\n * @param correlationId\n */\n abstract setIdTokenCredential(\n idToken: IdTokenEntity,\n correlationId: string\n ): Promise;\n\n /**\n * fetch the idToken entity from the platform cache\n * @param accessTokenKey\n */\n abstract getAccessTokenCredential(\n accessTokenKey: string,\n correlationId: string\n ): AccessTokenEntity | null;\n\n /**\n * set accessToken entity to the platform cache\n * @param accessToken\n * @param correlationId\n */\n abstract setAccessTokenCredential(\n accessToken: AccessTokenEntity,\n correlationId: string\n ): Promise;\n\n /**\n * fetch the idToken entity from the platform cache\n * @param refreshTokenKey\n */\n abstract getRefreshTokenCredential(\n refreshTokenKey: string,\n correlationId: string\n ): RefreshTokenEntity | null;\n\n /**\n * set refreshToken entity to the platform cache\n * @param refreshToken\n * @param correlationId\n */\n abstract setRefreshTokenCredential(\n refreshToken: RefreshTokenEntity,\n correlationId: string\n ): Promise;\n\n /**\n * fetch appMetadata entity from the platform cache\n * @param appMetadataKey\n */\n abstract getAppMetadata(appMetadataKey: string): AppMetadataEntity | null;\n\n /**\n * set appMetadata entity to the platform cache\n * @param appMetadata\n */\n abstract setAppMetadata(\n appMetadata: AppMetadataEntity,\n correlationId: string\n ): void;\n\n /**\n * fetch server telemetry entity from the platform cache\n * @param serverTelemetryKey\n */\n abstract getServerTelemetry(\n serverTelemetryKey: string\n ): ServerTelemetryEntity | null;\n\n /**\n * set server telemetry entity to the platform cache\n * @param serverTelemetryKey\n * @param serverTelemetry\n */\n abstract setServerTelemetry(\n serverTelemetryKey: string,\n serverTelemetry: ServerTelemetryEntity,\n correlationId: string\n ): void;\n\n /**\n * fetch cloud discovery metadata entity from the platform cache\n * @param key\n */\n abstract getAuthorityMetadata(key: string): AuthorityMetadataEntity | null;\n\n /**\n *\n */\n abstract getAuthorityMetadataKeys(): Array;\n\n /**\n * set cloud discovery metadata entity to the platform cache\n * @param key\n * @param value\n */\n abstract setAuthorityMetadata(\n key: string,\n value: AuthorityMetadataEntity\n ): void;\n\n /**\n * fetch throttling entity from the platform cache\n * @param throttlingCacheKey\n */\n abstract getThrottlingCache(\n throttlingCacheKey: string\n ): ThrottlingEntity | null;\n\n /**\n * set throttling entity to the platform cache\n * @param throttlingCacheKey\n * @param throttlingCache\n */\n abstract setThrottlingCache(\n throttlingCacheKey: string,\n throttlingCache: ThrottlingEntity,\n correlationId: string\n ): void;\n\n /**\n * Function to remove an item from cache given its key.\n * @param key\n */\n abstract removeItem(key: string, correlationId: string): void;\n\n /**\n * Function which retrieves all current keys from the cache.\n */\n abstract getKeys(): string[];\n\n /**\n * Function which retrieves all account keys from the cache\n */\n abstract getAccountKeys(): string[];\n\n /**\n * Function which retrieves all token keys from the cache\n */\n abstract getTokenKeys(): TokenKeys;\n\n /**\n * Returns credential cache key from the entity\n * @param credential\n */\n abstract generateCredentialKey(credential: CredentialEntity): string;\n\n /**\n * Returns the account cache key from the account info\n * @param account\n */\n abstract generateAccountKey(account: AccountInfo): string;\n\n /**\n * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.\n * @param accountFilter - (Optional) filter to narrow down the accounts returned\n * @returns Array of AccountInfo objects in cache\n */\n getAllAccounts(\n accountFilter: AccountFilter,\n correlationId: string\n ): AccountInfo[] {\n return this.buildTenantProfiles(\n this.getAccountsFilteredBy(accountFilter, correlationId),\n correlationId,\n accountFilter\n );\n }\n\n /**\n * Gets first tenanted AccountInfo object found based on provided filters\n */\n getAccountInfoFilteredBy(\n accountFilter: AccountFilter,\n correlationId: string\n ): AccountInfo | null {\n if (\n Object.keys(accountFilter).length === 0 ||\n Object.values(accountFilter).every((value) => !value)\n ) {\n this.commonLogger.warning(\n \"getAccountInfoFilteredBy: Account filter is empty or invalid, returning null\"\n );\n return null;\n }\n const allAccounts = this.getAllAccounts(accountFilter, correlationId);\n if (allAccounts.length > 1) {\n // If one or more accounts are found, prioritize accounts that have an ID token\n const sortedAccounts = allAccounts.sort((account) => {\n return account.idTokenClaims ? -1 : 1;\n });\n return sortedAccounts[0];\n } else if (allAccounts.length === 1) {\n // If only one account is found, return it regardless of whether a matching ID token was found\n return allAccounts[0];\n } else {\n return null;\n }\n }\n\n /**\n * Returns a single matching\n * @param accountFilter\n * @returns\n */\n getBaseAccountInfo(\n accountFilter: AccountFilter,\n correlationId: string\n ): AccountInfo | null {\n const accountEntities = this.getAccountsFilteredBy(\n accountFilter,\n correlationId\n );\n if (accountEntities.length > 0) {\n return accountEntities[0].getAccountInfo();\n } else {\n return null;\n }\n }\n\n /**\n * Matches filtered account entities with cached ID tokens that match the tenant profile-specific account filters\n * and builds the account info objects from the matching ID token's claims\n * @param cachedAccounts\n * @param accountFilter\n * @returns Array of AccountInfo objects that match account and tenant profile filters\n */\n private buildTenantProfiles(\n cachedAccounts: AccountEntity[],\n correlationId: string,\n accountFilter?: AccountFilter\n ): AccountInfo[] {\n return cachedAccounts.flatMap((accountEntity) => {\n return this.getTenantProfilesFromAccountEntity(\n accountEntity,\n correlationId,\n accountFilter?.tenantId,\n accountFilter\n );\n });\n }\n\n private getTenantedAccountInfoByFilter(\n accountInfo: AccountInfo,\n tokenKeys: TokenKeys,\n tenantProfile: TenantProfile,\n correlationId: string,\n tenantProfileFilter?: TenantProfileFilter\n ): AccountInfo | null {\n let tenantedAccountInfo: AccountInfo | null = null;\n let idTokenClaims: TokenClaims | undefined;\n\n if (tenantProfileFilter) {\n if (\n !this.tenantProfileMatchesFilter(\n tenantProfile,\n tenantProfileFilter\n )\n ) {\n return null;\n }\n }\n\n const idToken = this.getIdToken(\n accountInfo,\n correlationId,\n tokenKeys,\n tenantProfile.tenantId\n );\n\n if (idToken) {\n idTokenClaims = extractTokenClaims(\n idToken.secret,\n this.cryptoImpl.base64Decode\n );\n\n if (\n !this.idTokenClaimsMatchTenantProfileFilter(\n idTokenClaims,\n tenantProfileFilter\n )\n ) {\n // ID token sourced claims don't match so this tenant profile is not a match\n return null;\n }\n }\n\n // Expand tenant profile into account info based on matching tenant profile and if available matching ID token claims\n tenantedAccountInfo = updateAccountTenantProfileData(\n accountInfo,\n tenantProfile,\n idTokenClaims,\n idToken?.secret\n );\n\n return tenantedAccountInfo;\n }\n\n private getTenantProfilesFromAccountEntity(\n accountEntity: AccountEntity,\n correlationId: string,\n targetTenantId?: string,\n tenantProfileFilter?: TenantProfileFilter\n ): AccountInfo[] {\n const accountInfo = accountEntity.getAccountInfo();\n let searchTenantProfiles: Map =\n accountInfo.tenantProfiles || new Map();\n const tokenKeys = this.getTokenKeys();\n\n // If a tenant ID was provided, only return the tenant profile for that tenant ID if it exists\n if (targetTenantId) {\n const tenantProfile = searchTenantProfiles.get(targetTenantId);\n if (tenantProfile) {\n // Reduce search field to just this tenant profile\n searchTenantProfiles = new Map([\n [targetTenantId, tenantProfile],\n ]);\n } else {\n // No tenant profile for search tenant ID, return empty array\n return [];\n }\n }\n\n const matchingTenantProfiles: AccountInfo[] = [];\n searchTenantProfiles.forEach((tenantProfile: TenantProfile) => {\n const tenantedAccountInfo = this.getTenantedAccountInfoByFilter(\n accountInfo,\n tokenKeys,\n tenantProfile,\n correlationId,\n tenantProfileFilter\n );\n if (tenantedAccountInfo) {\n matchingTenantProfiles.push(tenantedAccountInfo);\n }\n });\n\n return matchingTenantProfiles;\n }\n\n private tenantProfileMatchesFilter(\n tenantProfile: TenantProfile,\n tenantProfileFilter: TenantProfileFilter\n ): boolean {\n if (\n !!tenantProfileFilter.localAccountId &&\n !this.matchLocalAccountIdFromTenantProfile(\n tenantProfile,\n tenantProfileFilter.localAccountId\n )\n ) {\n return false;\n }\n\n if (\n !!tenantProfileFilter.name &&\n !(tenantProfile.name === tenantProfileFilter.name)\n ) {\n return false;\n }\n\n if (\n tenantProfileFilter.isHomeTenant !== undefined &&\n !(tenantProfile.isHomeTenant === tenantProfileFilter.isHomeTenant)\n ) {\n return false;\n }\n\n return true;\n }\n\n private idTokenClaimsMatchTenantProfileFilter(\n idTokenClaims: TokenClaims,\n tenantProfileFilter?: TenantProfileFilter\n ): boolean {\n // Tenant Profile filtering\n if (tenantProfileFilter) {\n if (\n !!tenantProfileFilter.localAccountId &&\n !this.matchLocalAccountIdFromTokenClaims(\n idTokenClaims,\n tenantProfileFilter.localAccountId\n )\n ) {\n return false;\n }\n\n if (\n !!tenantProfileFilter.loginHint &&\n !this.matchLoginHintFromTokenClaims(\n idTokenClaims,\n tenantProfileFilter.loginHint\n )\n ) {\n return false;\n }\n\n if (\n !!tenantProfileFilter.username &&\n !this.matchUsername(\n idTokenClaims.preferred_username,\n tenantProfileFilter.username\n )\n ) {\n return false;\n }\n\n if (\n !!tenantProfileFilter.name &&\n !this.matchName(idTokenClaims, tenantProfileFilter.name)\n ) {\n return false;\n }\n\n if (\n !!tenantProfileFilter.sid &&\n !this.matchSid(idTokenClaims, tenantProfileFilter.sid)\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * saves a cache record\n * @param cacheRecord {CacheRecord}\n * @param storeInCache {?StoreInCache}\n * @param correlationId {?string} correlation id\n */\n async saveCacheRecord(\n cacheRecord: CacheRecord,\n correlationId: string,\n storeInCache?: StoreInCache\n ): Promise {\n if (!cacheRecord) {\n throw createClientAuthError(\n ClientAuthErrorCodes.invalidCacheRecord\n );\n }\n\n try {\n if (!!cacheRecord.account) {\n await this.setAccount(cacheRecord.account, correlationId);\n }\n\n if (!!cacheRecord.idToken && storeInCache?.idToken !== false) {\n await this.setIdTokenCredential(\n cacheRecord.idToken,\n correlationId\n );\n }\n\n if (\n !!cacheRecord.accessToken &&\n storeInCache?.accessToken !== false\n ) {\n await this.saveAccessToken(\n cacheRecord.accessToken,\n correlationId\n );\n }\n\n if (\n !!cacheRecord.refreshToken &&\n storeInCache?.refreshToken !== false\n ) {\n await this.setRefreshTokenCredential(\n cacheRecord.refreshToken,\n correlationId\n );\n }\n\n if (!!cacheRecord.appMetadata) {\n this.setAppMetadata(cacheRecord.appMetadata, correlationId);\n }\n } catch (e: unknown) {\n this.commonLogger?.error(`CacheManager.saveCacheRecord: failed`);\n if (e instanceof AuthError) {\n throw e;\n } else {\n throw createCacheError(e);\n }\n }\n }\n\n /**\n * saves access token credential\n * @param credential\n */\n private async saveAccessToken(\n credential: AccessTokenEntity,\n correlationId: string\n ): Promise {\n const accessTokenFilter: CredentialFilter = {\n clientId: credential.clientId,\n credentialType: credential.credentialType,\n environment: credential.environment,\n homeAccountId: credential.homeAccountId,\n realm: credential.realm,\n tokenType: credential.tokenType,\n requestedClaimsHash: credential.requestedClaimsHash,\n };\n\n const tokenKeys = this.getTokenKeys();\n const currentScopes = ScopeSet.fromString(credential.target);\n\n tokenKeys.accessToken.forEach((key) => {\n if (\n !this.accessTokenKeyMatchesFilter(key, accessTokenFilter, false)\n ) {\n return;\n }\n\n const tokenEntity = this.getAccessTokenCredential(\n key,\n correlationId\n );\n\n if (\n tokenEntity &&\n this.credentialMatchesFilter(tokenEntity, accessTokenFilter)\n ) {\n const tokenScopeSet = ScopeSet.fromString(tokenEntity.target);\n if (tokenScopeSet.intersectingScopeSets(currentScopes)) {\n this.removeAccessToken(key, correlationId);\n }\n }\n });\n await this.setAccessTokenCredential(credential, correlationId);\n }\n\n /**\n * Retrieve account entities matching all provided tenant-agnostic filters; if no filter is set, get all account entities in the cache\n * Not checking for casing as keys are all generated in lower case, remember to convert to lower case if object properties are compared\n * @param accountFilter - An object containing Account properties to filter by\n */\n getAccountsFilteredBy(\n accountFilter: AccountFilter,\n correlationId: string\n ): AccountEntity[] {\n const allAccountKeys = this.getAccountKeys();\n const matchingAccounts: AccountEntity[] = [];\n allAccountKeys.forEach((cacheKey) => {\n const entity: AccountEntity | null = this.getAccount(\n cacheKey,\n correlationId\n );\n\n // Match base account fields\n\n if (!entity) {\n return;\n }\n\n if (\n !!accountFilter.homeAccountId &&\n !this.matchHomeAccountId(entity, accountFilter.homeAccountId)\n ) {\n return;\n }\n\n if (\n !!accountFilter.username &&\n !this.matchUsername(entity.username, accountFilter.username)\n ) {\n return;\n }\n\n if (\n !!accountFilter.environment &&\n !this.matchEnvironment(entity, accountFilter.environment)\n ) {\n return;\n }\n\n if (\n !!accountFilter.realm &&\n !this.matchRealm(entity, accountFilter.realm)\n ) {\n return;\n }\n\n if (\n !!accountFilter.nativeAccountId &&\n !this.matchNativeAccountId(\n entity,\n accountFilter.nativeAccountId\n )\n ) {\n return;\n }\n\n if (\n !!accountFilter.authorityType &&\n !this.matchAuthorityType(entity, accountFilter.authorityType)\n ) {\n return;\n }\n\n // If at least one tenant profile matches the tenant profile filter, add the account to the list of matching accounts\n const tenantProfileFilter: TenantProfileFilter = {\n localAccountId: accountFilter?.localAccountId,\n name: accountFilter?.name,\n };\n\n const matchingTenantProfiles = entity.tenantProfiles?.filter(\n (tenantProfile: TenantProfile) => {\n return this.tenantProfileMatchesFilter(\n tenantProfile,\n tenantProfileFilter\n );\n }\n );\n\n if (matchingTenantProfiles && matchingTenantProfiles.length === 0) {\n // No tenant profile for this account matches filter, don't add to list of matching accounts\n return;\n }\n\n matchingAccounts.push(entity);\n });\n\n return matchingAccounts;\n }\n\n /**\n * Returns whether or not the given credential entity matches the filter\n * @param entity\n * @param filter\n * @returns\n */\n credentialMatchesFilter(\n entity: ValidCredentialType,\n filter: CredentialFilter\n ): boolean {\n if (!!filter.clientId && !this.matchClientId(entity, filter.clientId)) {\n return false;\n }\n\n if (\n !!filter.userAssertionHash &&\n !this.matchUserAssertionHash(entity, filter.userAssertionHash)\n ) {\n return false;\n }\n\n /*\n * homeAccountId can be undefined, and we want to filter out cached items that have a homeAccountId of \"\"\n * because we don't want a client_credential request to return a cached token that has a homeAccountId\n */\n if (\n typeof filter.homeAccountId === \"string\" &&\n !this.matchHomeAccountId(entity, filter.homeAccountId)\n ) {\n return false;\n }\n\n if (\n !!filter.environment &&\n !this.matchEnvironment(entity, filter.environment)\n ) {\n return false;\n }\n\n if (!!filter.realm && !this.matchRealm(entity, filter.realm)) {\n return false;\n }\n\n if (\n !!filter.credentialType &&\n !this.matchCredentialType(entity, filter.credentialType)\n ) {\n return false;\n }\n\n if (!!filter.familyId && !this.matchFamilyId(entity, filter.familyId)) {\n return false;\n }\n\n /*\n * idTokens do not have \"target\", target specific refreshTokens do exist for some types of authentication\n * Resource specific refresh tokens case will be added when the support is deemed necessary\n */\n if (!!filter.target && !this.matchTarget(entity, filter.target)) {\n return false;\n }\n\n // If request OR cached entity has requested Claims Hash, check if they match\n if (filter.requestedClaimsHash || entity.requestedClaimsHash) {\n // Don't match if either is undefined or they are different\n if (entity.requestedClaimsHash !== filter.requestedClaimsHash) {\n return false;\n }\n }\n\n // Access Token with Auth Scheme specific matching\n if (\n entity.credentialType ===\n CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME\n ) {\n if (\n !!filter.tokenType &&\n !this.matchTokenType(entity, filter.tokenType)\n ) {\n return false;\n }\n\n // KeyId (sshKid) in request must match cached SSH certificate keyId because SSH cert is bound to a specific key\n if (filter.tokenType === AuthenticationScheme.SSH) {\n if (filter.keyId && !this.matchKeyId(entity, filter.keyId)) {\n return false;\n }\n }\n }\n\n return true;\n }\n\n /**\n * retrieve appMetadata matching all provided filters; if no filter is set, get all appMetadata\n * @param filter\n */\n getAppMetadataFilteredBy(filter: AppMetadataFilter): AppMetadataCache {\n const allCacheKeys = this.getKeys();\n const matchingAppMetadata: AppMetadataCache = {};\n\n allCacheKeys.forEach((cacheKey) => {\n // don't parse any non-appMetadata type cache entities\n if (!this.isAppMetadata(cacheKey)) {\n return;\n }\n\n // Attempt retrieval\n const entity = this.getAppMetadata(cacheKey);\n\n if (!entity) {\n return;\n }\n\n if (\n !!filter.environment &&\n !this.matchEnvironment(entity, filter.environment)\n ) {\n return;\n }\n\n if (\n !!filter.clientId &&\n !this.matchClientId(entity, filter.clientId)\n ) {\n return;\n }\n\n matchingAppMetadata[cacheKey] = entity;\n });\n\n return matchingAppMetadata;\n }\n\n /**\n * retrieve authorityMetadata that contains a matching alias\n * @param filter\n */\n getAuthorityMetadataByAlias(host: string): AuthorityMetadataEntity | null {\n const allCacheKeys = this.getAuthorityMetadataKeys();\n let matchedEntity = null;\n\n allCacheKeys.forEach((cacheKey) => {\n // don't parse any non-authorityMetadata type cache entities\n if (\n !this.isAuthorityMetadata(cacheKey) ||\n cacheKey.indexOf(this.clientId) === -1\n ) {\n return;\n }\n\n // Attempt retrieval\n const entity = this.getAuthorityMetadata(cacheKey);\n\n if (!entity) {\n return;\n }\n\n if (entity.aliases.indexOf(host) === -1) {\n return;\n }\n\n matchedEntity = entity;\n });\n\n return matchedEntity;\n }\n\n /**\n * Removes all accounts and related tokens from cache.\n */\n removeAllAccounts(correlationId: string): void {\n const accounts = this.getAllAccounts({}, correlationId);\n accounts.forEach((account) => {\n this.removeAccount(account, correlationId);\n });\n }\n\n /**\n * Removes the account and related tokens for a given account key\n * @param account\n */\n removeAccount(account: AccountInfo, correlationId: string): void {\n this.removeAccountContext(account, correlationId);\n const accountKeys = this.getAccountKeys();\n const keyFilter = (key: string): boolean => {\n return (\n key.includes(account.homeAccountId) &&\n key.includes(account.environment)\n );\n };\n accountKeys.filter(keyFilter).forEach((key) => {\n this.removeItem(key, correlationId);\n this.performanceClient.incrementFields(\n { accountsRemoved: 1 },\n correlationId\n );\n });\n }\n\n /**\n * Removes credentials associated with the provided account\n * @param account\n */\n removeAccountContext(account: AccountInfo, correlationId: string): void {\n const allTokenKeys = this.getTokenKeys();\n const keyFilter = (key: string): boolean => {\n return (\n key.includes(account.homeAccountId) &&\n key.includes(account.environment)\n );\n };\n\n allTokenKeys.idToken.filter(keyFilter).forEach((key) => {\n this.removeIdToken(key, correlationId);\n });\n\n allTokenKeys.accessToken.filter(keyFilter).forEach((key) => {\n this.removeAccessToken(key, correlationId);\n });\n\n allTokenKeys.refreshToken.filter(keyFilter).forEach((key) => {\n this.removeRefreshToken(key, correlationId);\n });\n }\n\n /**\n * Removes accessToken from the cache\n * @param key\n * @param correlationId\n */\n removeAccessToken(key: string, correlationId: string): void {\n const credential = this.getAccessTokenCredential(key, correlationId);\n this.removeItem(key, correlationId);\n this.performanceClient.incrementFields(\n { accessTokensRemoved: 1 },\n correlationId\n );\n\n if (\n !credential ||\n credential.credentialType.toLowerCase() !==\n CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME.toLowerCase() ||\n credential.tokenType !== AuthenticationScheme.POP\n ) {\n // If the credential is not a PoP token, we can return\n return;\n }\n\n // Remove Token Binding Key from key store for PoP Tokens Credentials\n const kid = credential.keyId;\n\n if (kid) {\n void this.cryptoImpl.removeTokenBindingKey(kid).catch(() => {\n this.commonLogger.error(\n `Failed to remove token binding key ${kid}`,\n correlationId\n );\n this.performanceClient?.incrementFields(\n { removeTokenBindingKeyFailure: 1 },\n correlationId\n );\n });\n }\n }\n\n /**\n * Removes all app metadata objects from cache.\n */\n removeAppMetadata(correlationId: string): boolean {\n const allCacheKeys = this.getKeys();\n allCacheKeys.forEach((cacheKey) => {\n if (this.isAppMetadata(cacheKey)) {\n this.removeItem(cacheKey, correlationId);\n }\n });\n\n return true;\n }\n\n /**\n * Retrieve IdTokenEntity from cache\n * @param account {AccountInfo}\n * @param tokenKeys {?TokenKeys}\n * @param targetRealm {?string}\n * @param performanceClient {?IPerformanceClient}\n * @param correlationId {?string}\n */\n getIdToken(\n account: AccountInfo,\n correlationId: string,\n tokenKeys?: TokenKeys,\n targetRealm?: string,\n performanceClient?: IPerformanceClient\n ): IdTokenEntity | null {\n this.commonLogger.trace(\"CacheManager - getIdToken called\");\n const idTokenFilter: CredentialFilter = {\n homeAccountId: account.homeAccountId,\n environment: account.environment,\n credentialType: CredentialType.ID_TOKEN,\n clientId: this.clientId,\n realm: targetRealm,\n };\n\n const idTokenMap: Map = this.getIdTokensByFilter(\n idTokenFilter,\n correlationId,\n tokenKeys\n );\n\n const numIdTokens = idTokenMap.size;\n\n if (numIdTokens < 1) {\n this.commonLogger.info(\"CacheManager:getIdToken - No token found\");\n return null;\n } else if (numIdTokens > 1) {\n let tokensToBeRemoved: Map = idTokenMap;\n // Multiple tenant profiles and no tenant specified, pick home account\n if (!targetRealm) {\n const homeIdTokenMap: Map = new Map<\n string,\n IdTokenEntity\n >();\n idTokenMap.forEach((idToken, key) => {\n if (idToken.realm === account.tenantId) {\n homeIdTokenMap.set(key, idToken);\n }\n });\n const numHomeIdTokens = homeIdTokenMap.size;\n if (numHomeIdTokens < 1) {\n this.commonLogger.info(\n \"CacheManager:getIdToken - Multiple ID tokens found for account but none match account entity tenant id, returning first result\"\n );\n return idTokenMap.values().next().value;\n } else if (numHomeIdTokens === 1) {\n this.commonLogger.info(\n \"CacheManager:getIdToken - Multiple ID tokens found for account, defaulting to home tenant profile\"\n );\n return homeIdTokenMap.values().next().value;\n } else {\n // Multiple ID tokens for home tenant profile, remove all and return null\n tokensToBeRemoved = homeIdTokenMap;\n }\n }\n // Multiple tokens for a single tenant profile, remove all and return null\n this.commonLogger.info(\n \"CacheManager:getIdToken - Multiple matching ID tokens found, clearing them\"\n );\n tokensToBeRemoved.forEach((idToken, key) => {\n this.removeIdToken(key, correlationId);\n });\n if (performanceClient && correlationId) {\n performanceClient.addFields(\n { multiMatchedID: idTokenMap.size },\n correlationId\n );\n }\n return null;\n }\n\n this.commonLogger.info(\"CacheManager:getIdToken - Returning ID token\");\n return idTokenMap.values().next().value;\n }\n\n /**\n * Gets all idTokens matching the given filter\n * @param filter\n * @returns\n */\n getIdTokensByFilter(\n filter: CredentialFilter,\n correlationId: string,\n tokenKeys?: TokenKeys\n ): Map {\n const idTokenKeys =\n (tokenKeys && tokenKeys.idToken) || this.getTokenKeys().idToken;\n\n const idTokens: Map = new Map<\n string,\n IdTokenEntity\n >();\n idTokenKeys.forEach((key) => {\n if (\n !this.idTokenKeyMatchesFilter(key, {\n clientId: this.clientId,\n ...filter,\n })\n ) {\n return;\n }\n const idToken = this.getIdTokenCredential(key, correlationId);\n if (idToken && this.credentialMatchesFilter(idToken, filter)) {\n idTokens.set(key, idToken);\n }\n });\n\n return idTokens;\n }\n\n /**\n * Validate the cache key against filter before retrieving and parsing cache value\n * @param key\n * @param filter\n * @returns\n */\n idTokenKeyMatchesFilter(\n inputKey: string,\n filter: CredentialFilter\n ): boolean {\n const key = inputKey.toLowerCase();\n if (\n filter.clientId &&\n key.indexOf(filter.clientId.toLowerCase()) === -1\n ) {\n return false;\n }\n\n if (\n filter.homeAccountId &&\n key.indexOf(filter.homeAccountId.toLowerCase()) === -1\n ) {\n return false;\n }\n\n return true;\n }\n\n /**\n * Removes idToken from the cache\n * @param key\n */\n removeIdToken(key: string, correlationId: string): void {\n this.removeItem(key, correlationId);\n }\n\n /**\n * Removes refresh token from the cache\n * @param key\n */\n removeRefreshToken(key: string, correlationId: string): void {\n this.removeItem(key, correlationId);\n }\n\n /**\n * Retrieve AccessTokenEntity from cache\n * @param account {AccountInfo}\n * @param request {BaseAuthRequest}\n * @param correlationId {?string}\n * @param tokenKeys {?TokenKeys}\n * @param performanceClient {?IPerformanceClient}\n */\n getAccessToken(\n account: AccountInfo,\n request: BaseAuthRequest,\n tokenKeys?: TokenKeys,\n targetRealm?: string\n ): AccessTokenEntity | null {\n const correlationId = request.correlationId;\n this.commonLogger.trace(\n \"CacheManager - getAccessToken called\",\n correlationId\n );\n const scopes = ScopeSet.createSearchScopes(request.scopes);\n const authScheme =\n request.authenticationScheme || AuthenticationScheme.BEARER;\n /*\n * Distinguish between Bearer and PoP/SSH token cache types\n * Cast to lowercase to handle \"bearer\" from ADFS\n */\n const credentialType =\n authScheme &&\n authScheme.toLowerCase() !==\n AuthenticationScheme.BEARER.toLowerCase()\n ? CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME\n : CredentialType.ACCESS_TOKEN;\n\n const accessTokenFilter: CredentialFilter = {\n homeAccountId: account.homeAccountId,\n environment: account.environment,\n credentialType: credentialType,\n clientId: this.clientId,\n realm: targetRealm || account.tenantId,\n target: scopes,\n tokenType: authScheme,\n keyId: request.sshKid,\n requestedClaimsHash: request.requestedClaimsHash,\n };\n\n const accessTokenKeys =\n (tokenKeys && tokenKeys.accessToken) ||\n this.getTokenKeys().accessToken;\n const accessTokens: AccessTokenEntity[] = [];\n\n accessTokenKeys.forEach((key) => {\n // Validate key\n if (\n this.accessTokenKeyMatchesFilter(key, accessTokenFilter, true)\n ) {\n const accessToken = this.getAccessTokenCredential(\n key,\n correlationId\n );\n\n // Validate value\n if (\n accessToken &&\n this.credentialMatchesFilter(accessToken, accessTokenFilter)\n ) {\n accessTokens.push(accessToken);\n }\n }\n });\n\n const numAccessTokens = accessTokens.length;\n if (numAccessTokens < 1) {\n this.commonLogger.info(\n \"CacheManager:getAccessToken - No token found\",\n correlationId\n );\n return null;\n } else if (numAccessTokens > 1) {\n this.commonLogger.info(\n \"CacheManager:getAccessToken - Multiple access tokens found, clearing them\",\n correlationId\n );\n accessTokens.forEach((accessToken) => {\n this.removeAccessToken(\n this.generateCredentialKey(accessToken),\n correlationId\n );\n });\n this.performanceClient.addFields(\n { multiMatchedAT: accessTokens.length },\n correlationId\n );\n return null;\n }\n\n this.commonLogger.info(\n \"CacheManager:getAccessToken - Returning access token\",\n correlationId\n );\n return accessTokens[0];\n }\n\n /**\n * Validate the cache key against filter before retrieving and parsing cache value\n * @param key\n * @param filter\n * @param keyMustContainAllScopes\n * @returns\n */\n accessTokenKeyMatchesFilter(\n inputKey: string,\n filter: CredentialFilter,\n keyMustContainAllScopes: boolean\n ): boolean {\n const key = inputKey.toLowerCase();\n if (\n filter.clientId &&\n key.indexOf(filter.clientId.toLowerCase()) === -1\n ) {\n return false;\n }\n\n if (\n filter.homeAccountId &&\n key.indexOf(filter.homeAccountId.toLowerCase()) === -1\n ) {\n return false;\n }\n\n if (filter.realm && key.indexOf(filter.realm.toLowerCase()) === -1) {\n return false;\n }\n\n if (\n filter.requestedClaimsHash &&\n key.indexOf(filter.requestedClaimsHash.toLowerCase()) === -1\n ) {\n return false;\n }\n\n if (filter.target) {\n const scopes = filter.target.asArray();\n for (let i = 0; i < scopes.length; i++) {\n if (\n keyMustContainAllScopes &&\n !key.includes(scopes[i].toLowerCase())\n ) {\n // When performing a cache lookup a missing scope would be a cache miss\n return false;\n } else if (\n !keyMustContainAllScopes &&\n key.includes(scopes[i].toLowerCase())\n ) {\n // When performing a cache write, any token with a subset of requested scopes should be replaced\n return true;\n }\n }\n }\n\n return true;\n }\n\n /**\n * Gets all access tokens matching the filter\n * @param filter\n * @returns\n */\n getAccessTokensByFilter(\n filter: CredentialFilter,\n correlationId: string\n ): AccessTokenEntity[] {\n const tokenKeys = this.getTokenKeys();\n\n const accessTokens: AccessTokenEntity[] = [];\n tokenKeys.accessToken.forEach((key) => {\n if (!this.accessTokenKeyMatchesFilter(key, filter, true)) {\n return;\n }\n\n const accessToken = this.getAccessTokenCredential(\n key,\n correlationId\n );\n if (\n accessToken &&\n this.credentialMatchesFilter(accessToken, filter)\n ) {\n accessTokens.push(accessToken);\n }\n });\n\n return accessTokens;\n }\n\n /**\n * Helper to retrieve the appropriate refresh token from cache\n * @param account {AccountInfo}\n * @param familyRT {boolean}\n * @param correlationId {?string}\n * @param tokenKeys {?TokenKeys}\n * @param performanceClient {?IPerformanceClient}\n */\n getRefreshToken(\n account: AccountInfo,\n familyRT: boolean,\n correlationId: string,\n tokenKeys?: TokenKeys,\n performanceClient?: IPerformanceClient\n ): RefreshTokenEntity | null {\n this.commonLogger.trace(\"CacheManager - getRefreshToken called\");\n const id = familyRT ? THE_FAMILY_ID : undefined;\n const refreshTokenFilter: CredentialFilter = {\n homeAccountId: account.homeAccountId,\n environment: account.environment,\n credentialType: CredentialType.REFRESH_TOKEN,\n clientId: this.clientId,\n familyId: id,\n };\n\n const refreshTokenKeys =\n (tokenKeys && tokenKeys.refreshToken) ||\n this.getTokenKeys().refreshToken;\n const refreshTokens: RefreshTokenEntity[] = [];\n\n refreshTokenKeys.forEach((key) => {\n // Validate key\n if (this.refreshTokenKeyMatchesFilter(key, refreshTokenFilter)) {\n const refreshToken = this.getRefreshTokenCredential(\n key,\n correlationId\n );\n // Validate value\n if (\n refreshToken &&\n this.credentialMatchesFilter(\n refreshToken,\n refreshTokenFilter\n )\n ) {\n refreshTokens.push(refreshToken);\n }\n }\n });\n\n const numRefreshTokens = refreshTokens.length;\n if (numRefreshTokens < 1) {\n this.commonLogger.info(\n \"CacheManager:getRefreshToken - No refresh token found.\"\n );\n return null;\n }\n // address the else case after remove functions address environment aliases\n\n if (numRefreshTokens > 1 && performanceClient && correlationId) {\n performanceClient.addFields(\n { multiMatchedRT: numRefreshTokens },\n correlationId\n );\n }\n\n this.commonLogger.info(\n \"CacheManager:getRefreshToken - returning refresh token\"\n );\n return refreshTokens[0] as RefreshTokenEntity;\n }\n\n /**\n * Validate the cache key against filter before retrieving and parsing cache value\n * @param key\n * @param filter\n */\n refreshTokenKeyMatchesFilter(\n inputKey: string,\n filter: CredentialFilter\n ): boolean {\n const key = inputKey.toLowerCase();\n if (\n filter.familyId &&\n key.indexOf(filter.familyId.toLowerCase()) === -1\n ) {\n return false;\n }\n\n // If familyId is used, clientId is not in the key\n if (\n !filter.familyId &&\n filter.clientId &&\n key.indexOf(filter.clientId.toLowerCase()) === -1\n ) {\n return false;\n }\n\n if (\n filter.homeAccountId &&\n key.indexOf(filter.homeAccountId.toLowerCase()) === -1\n ) {\n return false;\n }\n\n return true;\n }\n\n /**\n * Retrieve AppMetadataEntity from cache\n */\n readAppMetadataFromCache(environment: string): AppMetadataEntity | null {\n const appMetadataFilter: AppMetadataFilter = {\n environment,\n clientId: this.clientId,\n };\n\n const appMetadata: AppMetadataCache =\n this.getAppMetadataFilteredBy(appMetadataFilter);\n const appMetadataEntries: AppMetadataEntity[] = Object.keys(\n appMetadata\n ).map((key) => appMetadata[key]);\n\n const numAppMetadata = appMetadataEntries.length;\n if (numAppMetadata < 1) {\n return null;\n } else if (numAppMetadata > 1) {\n throw createClientAuthError(\n ClientAuthErrorCodes.multipleMatchingAppMetadata\n );\n }\n\n return appMetadataEntries[0] as AppMetadataEntity;\n }\n\n /**\n * Return the family_id value associated with FOCI\n * @param environment\n * @param clientId\n */\n isAppMetadataFOCI(environment: string): boolean {\n const appMetadata = this.readAppMetadataFromCache(environment);\n return !!(appMetadata && appMetadata.familyId === THE_FAMILY_ID);\n }\n\n /**\n * helper to match account ids\n * @param value\n * @param homeAccountId\n */\n private matchHomeAccountId(\n entity: AccountEntity | CredentialEntity,\n homeAccountId: string\n ): boolean {\n return !!(\n typeof entity.homeAccountId === \"string\" &&\n homeAccountId === entity.homeAccountId\n );\n }\n\n /**\n * helper to match account ids\n * @param entity\n * @param localAccountId\n * @returns\n */\n private matchLocalAccountIdFromTokenClaims(\n tokenClaims: TokenClaims,\n localAccountId: string\n ): boolean {\n const idTokenLocalAccountId = tokenClaims.oid || tokenClaims.sub;\n return localAccountId === idTokenLocalAccountId;\n }\n\n private matchLocalAccountIdFromTenantProfile(\n tenantProfile: TenantProfile,\n localAccountId: string\n ): boolean {\n return tenantProfile.localAccountId === localAccountId;\n }\n\n /**\n * helper to match names\n * @param entity\n * @param name\n * @returns true if the downcased name properties are present and match in the filter and the entity\n */\n private matchName(claims: TokenClaims, name: string): boolean {\n return !!(name.toLowerCase() === claims.name?.toLowerCase());\n }\n\n /**\n * helper to match usernames\n * @param entity\n * @param username\n * @returns\n */\n private matchUsername(\n cachedUsername?: string,\n filterUsername?: string\n ): boolean {\n return !!(\n cachedUsername &&\n typeof cachedUsername === \"string\" &&\n filterUsername?.toLowerCase() === cachedUsername.toLowerCase()\n );\n }\n\n /**\n * helper to match assertion\n * @param value\n * @param oboAssertion\n */\n private matchUserAssertionHash(\n entity: CredentialEntity,\n userAssertionHash: string\n ): boolean {\n return !!(\n entity.userAssertionHash &&\n userAssertionHash === entity.userAssertionHash\n );\n }\n\n /**\n * helper to match environment\n * @param value\n * @param environment\n */\n private matchEnvironment(\n entity: AccountEntity | CredentialEntity | AppMetadataEntity,\n environment: string\n ): boolean {\n // Check static authority options first for cases where authority metadata has not been resolved and cached yet\n if (this.staticAuthorityOptions) {\n const staticAliases = getAliasesFromStaticSources(\n this.staticAuthorityOptions,\n this.commonLogger\n );\n if (\n staticAliases.includes(environment) &&\n staticAliases.includes(entity.environment)\n ) {\n return true;\n }\n }\n\n // Query metadata cache if no static authority configuration has aliases that match enviroment\n const cloudMetadata = this.getAuthorityMetadataByAlias(environment);\n if (\n cloudMetadata &&\n cloudMetadata.aliases.indexOf(entity.environment) > -1\n ) {\n return true;\n }\n return false;\n }\n\n /**\n * helper to match credential type\n * @param entity\n * @param credentialType\n */\n private matchCredentialType(\n entity: CredentialEntity,\n credentialType: string\n ): boolean {\n return (\n entity.credentialType &&\n credentialType.toLowerCase() === entity.credentialType.toLowerCase()\n );\n }\n\n /**\n * helper to match client ids\n * @param entity\n * @param clientId\n */\n private matchClientId(\n entity: CredentialEntity | AppMetadataEntity,\n clientId: string\n ): boolean {\n return !!(entity.clientId && clientId === entity.clientId);\n }\n\n /**\n * helper to match family ids\n * @param entity\n * @param familyId\n */\n private matchFamilyId(\n entity: CredentialEntity | AppMetadataEntity,\n familyId: string\n ): boolean {\n return !!(entity.familyId && familyId === entity.familyId);\n }\n\n /**\n * helper to match realm\n * @param entity\n * @param realm\n */\n private matchRealm(\n entity: AccountEntity | CredentialEntity,\n realm: string\n ): boolean {\n return !!(entity.realm?.toLowerCase() === realm.toLowerCase());\n }\n\n /**\n * helper to match nativeAccountId\n * @param entity\n * @param nativeAccountId\n * @returns boolean indicating the match result\n */\n private matchNativeAccountId(\n entity: AccountEntity,\n nativeAccountId: string\n ): boolean {\n return !!(\n entity.nativeAccountId && nativeAccountId === entity.nativeAccountId\n );\n }\n\n /**\n * helper to match loginHint which can be either:\n * 1. login_hint ID token claim\n * 2. username in cached account object\n * 3. upn in ID token claims\n * @param entity\n * @param loginHint\n * @returns\n */\n private matchLoginHintFromTokenClaims(\n tokenClaims: TokenClaims,\n loginHint: string\n ): boolean {\n if (tokenClaims.login_hint === loginHint) {\n return true;\n }\n\n if (tokenClaims.preferred_username === loginHint) {\n return true;\n }\n\n if (tokenClaims.upn === loginHint) {\n return true;\n }\n\n return false;\n }\n\n /**\n * Helper to match sid\n * @param entity\n * @param sid\n * @returns true if the sid claim is present and matches the filter\n */\n private matchSid(idTokenClaims: TokenClaims, sid: string): boolean {\n return idTokenClaims.sid === sid;\n }\n\n private matchAuthorityType(\n entity: AccountEntity,\n authorityType: string\n ): boolean {\n return !!(\n entity.authorityType &&\n authorityType.toLowerCase() === entity.authorityType.toLowerCase()\n );\n }\n\n /**\n * Returns true if the target scopes are a subset of the current entity's scopes, false otherwise.\n * @param entity\n * @param target\n */\n private matchTarget(entity: CredentialEntity, target: ScopeSet): boolean {\n const isNotAccessTokenCredential =\n entity.credentialType !== CredentialType.ACCESS_TOKEN &&\n entity.credentialType !==\n CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME;\n\n if (isNotAccessTokenCredential || !entity.target) {\n return false;\n }\n\n const entityScopeSet: ScopeSet = ScopeSet.fromString(entity.target);\n\n return entityScopeSet.containsScopeSet(target);\n }\n\n /**\n * Returns true if the credential's tokenType or Authentication Scheme matches the one in the request, false otherwise\n * @param entity\n * @param tokenType\n */\n private matchTokenType(\n entity: CredentialEntity,\n tokenType: AuthenticationScheme\n ): boolean {\n return !!(entity.tokenType && entity.tokenType === tokenType);\n }\n\n /**\n * Returns true if the credential's keyId matches the one in the request, false otherwise\n * @param entity\n * @param keyId\n */\n private matchKeyId(entity: CredentialEntity, keyId: string): boolean {\n return !!(entity.keyId && entity.keyId === keyId);\n }\n\n /**\n * returns if a given cache entity is of the type appmetadata\n * @param key\n */\n private isAppMetadata(key: string): boolean {\n return key.indexOf(APP_METADATA) !== -1;\n }\n\n /**\n * returns if a given cache entity is of the type authoritymetadata\n * @param key\n */\n protected isAuthorityMetadata(key: string): boolean {\n return key.indexOf(AUTHORITY_METADATA_CONSTANTS.CACHE_KEY) !== -1;\n }\n\n /**\n * returns cache key used for cloud instance metadata\n */\n generateAuthorityMetadataCacheKey(authority: string): string {\n return `${AUTHORITY_METADATA_CONSTANTS.CACHE_KEY}-${this.clientId}-${authority}`;\n }\n\n /**\n * Helper to convert serialized data to object\n * @param obj\n * @param json\n */\n static toObject(obj: T, json: object): T {\n for (const propertyName in json) {\n obj[propertyName] = json[propertyName];\n }\n return obj;\n }\n}\n\n/** @internal */\nexport class DefaultStorageClass extends CacheManager {\n async setAccount(): Promise {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n getAccount(): AccountEntity {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n async setIdTokenCredential(): Promise {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n getIdTokenCredential(): IdTokenEntity {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n async setAccessTokenCredential(): Promise {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n getAccessTokenCredential(): AccessTokenEntity {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n async setRefreshTokenCredential(): Promise {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n getRefreshTokenCredential(): RefreshTokenEntity {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n setAppMetadata(): void {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n getAppMetadata(): AppMetadataEntity {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n setServerTelemetry(): void {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n getServerTelemetry(): ServerTelemetryEntity {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n setAuthorityMetadata(): void {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n getAuthorityMetadata(): AuthorityMetadataEntity | null {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n getAuthorityMetadataKeys(): Array {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n setThrottlingCache(): void {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n getThrottlingCache(): ThrottlingEntity {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n removeItem(): boolean {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n getKeys(): string[] {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n getAccountKeys(): string[] {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n getTokenKeys(): TokenKeys {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n generateCredentialKey(): string {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n generateAccountKey(): string {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Protocol modes supported by MSAL.\n */\nexport const ProtocolMode = {\n /**\n * Auth Code + PKCE with Entra ID (formerly AAD) specific optimizations and features\n */\n AAD: \"AAD\",\n /**\n * Auth Code + PKCE without Entra ID specific optimizations and features. For use only with non-Microsoft owned authorities.\n * Support is limited for this mode.\n */\n OIDC: \"OIDC\",\n /**\n * Encrypted Authorize Response (EAR) with Entra ID specific optimizations and features\n */\n EAR: \"EAR\",\n} as const;\nexport type ProtocolMode = (typeof ProtocolMode)[keyof typeof ProtocolMode];\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Enumeration of operations that are instrumented by have their performance measured by the PerformanceClient.\n *\n * @export\n * @enum {number}\n */\nexport const PerformanceEvents = {\n /**\n * acquireTokenByCode API (msal-browser and msal-node).\n * Used to acquire tokens by trading an authorization code against the token endpoint.\n */\n AcquireTokenByCode: \"acquireTokenByCode\",\n\n /**\n * acquireTokenByRefreshToken API (msal-browser and msal-node).\n * Used to renew an access token using a refresh token against the token endpoint.\n */\n AcquireTokenByRefreshToken: \"acquireTokenByRefreshToken\",\n\n /**\n * acquireTokenSilent API (msal-browser and msal-node).\n * Used to silently acquire a new access token (from the cache or the network).\n */\n AcquireTokenSilent: \"acquireTokenSilent\",\n\n /**\n * acquireTokenSilentAsync (msal-browser).\n * Internal API for acquireTokenSilent.\n */\n AcquireTokenSilentAsync: \"acquireTokenSilentAsync\",\n\n /**\n * acquireTokenPopup (msal-browser).\n * Used to acquire a new access token interactively through pop ups\n */\n AcquireTokenPopup: \"acquireTokenPopup\",\n\n /**\n * acquireTokenPreRedirect (msal-browser).\n * First part of the redirect flow.\n * Used to acquire a new access token interactively through redirects.\n */\n AcquireTokenPreRedirect: \"acquireTokenPreRedirect\",\n\n /**\n * acquireTokenRedirect (msal-browser).\n * Second part of the redirect flow.\n * Used to acquire a new access token interactively through redirects.\n */\n AcquireTokenRedirect: \"acquireTokenRedirect\",\n\n /**\n * getPublicKeyThumbprint API in CryptoOpts class (msal-browser).\n * Used to generate a public/private keypair and generate a public key thumbprint for pop requests.\n */\n CryptoOptsGetPublicKeyThumbprint: \"cryptoOptsGetPublicKeyThumbprint\",\n\n /**\n * signJwt API in CryptoOpts class (msal-browser).\n * Used to signed a pop token.\n */\n CryptoOptsSignJwt: \"cryptoOptsSignJwt\",\n\n /**\n * acquireToken API in the SilentCacheClient class (msal-browser).\n * Used to read access tokens from the cache.\n */\n SilentCacheClientAcquireToken: \"silentCacheClientAcquireToken\",\n\n /**\n * acquireToken API in the SilentIframeClient class (msal-browser).\n * Used to acquire a new set of tokens from the authorize endpoint in a hidden iframe.\n */\n SilentIframeClientAcquireToken: \"silentIframeClientAcquireToken\",\n AwaitConcurrentIframe: \"awaitConcurrentIframe\", // Time spent waiting for a concurrent iframe to complete\n\n /**\n * acquireToken API in SilentRereshClient (msal-browser).\n * Used to acquire a new set of tokens from the token endpoint using a refresh token.\n */\n SilentRefreshClientAcquireToken: \"silentRefreshClientAcquireToken\",\n\n /**\n * ssoSilent API (msal-browser).\n * Used to silently acquire an authorization code and set of tokens using a hidden iframe.\n */\n SsoSilent: \"ssoSilent\",\n\n /**\n * getDiscoveredAuthority API in StandardInteractionClient class (msal-browser).\n * Used to load authority metadata for a request.\n */\n StandardInteractionClientGetDiscoveredAuthority:\n \"standardInteractionClientGetDiscoveredAuthority\",\n\n /**\n * acquireToken APIs in msal-browser.\n * Used to make an /authorize endpoint call with native brokering enabled.\n */\n FetchAccountIdWithNativeBroker: \"fetchAccountIdWithNativeBroker\",\n\n /**\n * acquireToken API in NativeInteractionClient class (msal-browser).\n * Used to acquire a token from Native component when native brokering is enabled.\n */\n NativeInteractionClientAcquireToken: \"nativeInteractionClientAcquireToken\",\n /**\n * Time spent creating default headers for requests to token endpoint\n */\n BaseClientCreateTokenRequestHeaders: \"baseClientCreateTokenRequestHeaders\",\n /**\n * Time spent sending/waiting for the response of a request to the token endpoint\n */\n NetworkClientSendPostRequestAsync: \"networkClientSendPostRequestAsync\",\n RefreshTokenClientExecutePostToTokenEndpoint:\n \"refreshTokenClientExecutePostToTokenEndpoint\",\n AuthorizationCodeClientExecutePostToTokenEndpoint:\n \"authorizationCodeClientExecutePostToTokenEndpoint\",\n /**\n * Used to measure the time taken for completing embedded-broker handshake (PW-Broker).\n */\n BrokerHandhshake: \"brokerHandshake\",\n /**\n * acquireTokenByRefreshToken API in BrokerClientApplication (PW-Broker) .\n */\n AcquireTokenByRefreshTokenInBroker: \"acquireTokenByRefreshTokenInBroker\",\n /**\n * Time taken for token acquisition by broker\n */\n AcquireTokenByBroker: \"acquireTokenByBroker\",\n\n /**\n * Time spent on the network for refresh token acquisition\n */\n RefreshTokenClientExecuteTokenRequest:\n \"refreshTokenClientExecuteTokenRequest\",\n\n /**\n * Time taken for acquiring refresh token , records RT size\n */\n RefreshTokenClientAcquireToken: \"refreshTokenClientAcquireToken\",\n\n /**\n * Time taken for acquiring cached refresh token\n */\n RefreshTokenClientAcquireTokenWithCachedRefreshToken:\n \"refreshTokenClientAcquireTokenWithCachedRefreshToken\",\n\n /**\n * acquireTokenByRefreshToken API in RefreshTokenClient (msal-common).\n */\n RefreshTokenClientAcquireTokenByRefreshToken:\n \"refreshTokenClientAcquireTokenByRefreshToken\",\n\n /**\n * Helper function to create token request body in RefreshTokenClient (msal-common).\n */\n RefreshTokenClientCreateTokenRequestBody:\n \"refreshTokenClientCreateTokenRequestBody\",\n\n /**\n * acquireTokenFromCache (msal-browser).\n * Internal API for acquiring token from cache\n */\n AcquireTokenFromCache: \"acquireTokenFromCache\",\n SilentFlowClientAcquireCachedToken: \"silentFlowClientAcquireCachedToken\",\n SilentFlowClientGenerateResultFromCacheRecord:\n \"silentFlowClientGenerateResultFromCacheRecord\",\n\n /**\n * acquireTokenBySilentIframe (msal-browser).\n * Internal API for acquiring token by silent Iframe\n */\n AcquireTokenBySilentIframe: \"acquireTokenBySilentIframe\",\n\n /**\n * Internal API for initializing base request in BaseInteractionClient (msal-browser)\n */\n InitializeBaseRequest: \"initializeBaseRequest\",\n\n /**\n * Internal API for initializing silent request in SilentCacheClient (msal-browser)\n */\n InitializeSilentRequest: \"initializeSilentRequest\",\n\n InitializeClientApplication: \"initializeClientApplication\",\n\n InitializeCache: \"initializeCache\",\n\n /**\n * Helper function in SilentIframeClient class (msal-browser).\n */\n SilentIframeClientTokenHelper: \"silentIframeClientTokenHelper\",\n\n /**\n * SilentHandler\n */\n SilentHandlerInitiateAuthRequest: \"silentHandlerInitiateAuthRequest\",\n SilentHandlerMonitorIframeForHash: \"silentHandlerMonitorIframeForHash\",\n SilentHandlerLoadFrame: \"silentHandlerLoadFrame\",\n SilentHandlerLoadFrameSync: \"silentHandlerLoadFrameSync\",\n\n /**\n * Helper functions in StandardInteractionClient class (msal-browser)\n */\n StandardInteractionClientCreateAuthCodeClient:\n \"standardInteractionClientCreateAuthCodeClient\",\n StandardInteractionClientGetClientConfiguration:\n \"standardInteractionClientGetClientConfiguration\",\n StandardInteractionClientInitializeAuthorizationRequest:\n \"standardInteractionClientInitializeAuthorizationRequest\",\n\n /**\n * getAuthCodeUrl API (msal-browser and msal-node).\n */\n GetAuthCodeUrl: \"getAuthCodeUrl\",\n GetStandardParams: \"getStandardParams\",\n\n /**\n * Functions from InteractionHandler (msal-browser)\n */\n HandleCodeResponseFromServer: \"handleCodeResponseFromServer\",\n HandleCodeResponse: \"handleCodeResponse\",\n HandleResponseEar: \"handleResponseEar\",\n HandleResponsePlatformBroker: \"handleResponsePlatformBroker\",\n HandleResponseCode: \"handleResponseCode\",\n UpdateTokenEndpointAuthority: \"updateTokenEndpointAuthority\",\n\n /**\n * APIs in Authorization Code Client (msal-common)\n */\n AuthClientAcquireToken: \"authClientAcquireToken\",\n AuthClientExecuteTokenRequest: \"authClientExecuteTokenRequest\",\n AuthClientCreateTokenRequestBody: \"authClientCreateTokenRequestBody\",\n\n /**\n * Generate functions in PopTokenGenerator (msal-common)\n */\n PopTokenGenerateCnf: \"popTokenGenerateCnf\",\n PopTokenGenerateKid: \"popTokenGenerateKid\",\n\n /**\n * handleServerTokenResponse API in ResponseHandler (msal-common)\n */\n HandleServerTokenResponse: \"handleServerTokenResponse\",\n DeserializeResponse: \"deserializeResponse\",\n\n /**\n * Authority functions\n */\n AuthorityFactoryCreateDiscoveredInstance:\n \"authorityFactoryCreateDiscoveredInstance\",\n AuthorityResolveEndpointsAsync: \"authorityResolveEndpointsAsync\",\n AuthorityResolveEndpointsFromLocalSources:\n \"authorityResolveEndpointsFromLocalSources\",\n AuthorityGetCloudDiscoveryMetadataFromNetwork:\n \"authorityGetCloudDiscoveryMetadataFromNetwork\",\n AuthorityUpdateCloudDiscoveryMetadata:\n \"authorityUpdateCloudDiscoveryMetadata\",\n AuthorityGetEndpointMetadataFromNetwork:\n \"authorityGetEndpointMetadataFromNetwork\",\n AuthorityUpdateEndpointMetadata: \"authorityUpdateEndpointMetadata\",\n AuthorityUpdateMetadataWithRegionalInformation:\n \"authorityUpdateMetadataWithRegionalInformation\",\n\n /**\n * Region Discovery functions\n */\n RegionDiscoveryDetectRegion: \"regionDiscoveryDetectRegion\",\n RegionDiscoveryGetRegionFromIMDS: \"regionDiscoveryGetRegionFromIMDS\",\n RegionDiscoveryGetCurrentVersion: \"regionDiscoveryGetCurrentVersion\",\n\n AcquireTokenByCodeAsync: \"acquireTokenByCodeAsync\",\n\n GetEndpointMetadataFromNetwork: \"getEndpointMetadataFromNetwork\",\n GetCloudDiscoveryMetadataFromNetworkMeasurement:\n \"getCloudDiscoveryMetadataFromNetworkMeasurement\",\n\n HandleRedirectPromiseMeasurement: \"handleRedirectPromise\",\n HandleNativeRedirectPromiseMeasurement: \"handleNativeRedirectPromise\",\n\n UpdateCloudDiscoveryMetadataMeasurement:\n \"updateCloudDiscoveryMetadataMeasurement\",\n\n UsernamePasswordClientAcquireToken: \"usernamePasswordClientAcquireToken\",\n\n NativeMessageHandlerHandshake: \"nativeMessageHandlerHandshake\",\n\n NativeGenerateAuthResult: \"nativeGenerateAuthResult\",\n\n RemoveHiddenIframe: \"removeHiddenIframe\",\n\n /**\n * Cache operations\n */\n ClearTokensAndKeysWithClaims: \"clearTokensAndKeysWithClaims\",\n CacheManagerGetRefreshToken: \"cacheManagerGetRefreshToken\",\n ImportExistingCache: \"importExistingCache\",\n SetUserData: \"setUserData\",\n LocalStorageUpdated: \"localStorageUpdated\",\n\n /**\n * Crypto Operations\n */\n GeneratePkceCodes: \"generatePkceCodes\",\n GenerateCodeVerifier: \"generateCodeVerifier\",\n GenerateCodeChallengeFromVerifier: \"generateCodeChallengeFromVerifier\",\n Sha256Digest: \"sha256Digest\",\n GetRandomValues: \"getRandomValues\",\n GenerateHKDF: \"generateHKDF\",\n GenerateBaseKey: \"generateBaseKey\",\n Base64Decode: \"base64Decode\",\n UrlEncodeArr: \"urlEncodeArr\",\n Encrypt: \"encrypt\",\n Decrypt: \"decrypt\",\n GenerateEarKey: \"generateEarKey\",\n DecryptEarResponse: \"decryptEarResponse\",\n} as const;\nexport type PerformanceEvents =\n (typeof PerformanceEvents)[keyof typeof PerformanceEvents];\n\nexport const PerformanceEventAbbreviations: ReadonlyMap =\n new Map([\n [PerformanceEvents.AcquireTokenByCode, \"ATByCode\"],\n [PerformanceEvents.AcquireTokenByRefreshToken, \"ATByRT\"],\n [PerformanceEvents.AcquireTokenSilent, \"ATS\"],\n [PerformanceEvents.AcquireTokenSilentAsync, \"ATSAsync\"],\n [PerformanceEvents.AcquireTokenPopup, \"ATPopup\"],\n [PerformanceEvents.AcquireTokenRedirect, \"ATRedirect\"],\n [\n PerformanceEvents.CryptoOptsGetPublicKeyThumbprint,\n \"CryptoGetPKThumb\",\n ],\n [PerformanceEvents.CryptoOptsSignJwt, \"CryptoSignJwt\"],\n [PerformanceEvents.SilentCacheClientAcquireToken, \"SltCacheClientAT\"],\n [PerformanceEvents.SilentIframeClientAcquireToken, \"SltIframeClientAT\"],\n [PerformanceEvents.SilentRefreshClientAcquireToken, \"SltRClientAT\"],\n [PerformanceEvents.SsoSilent, \"SsoSlt\"],\n [\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\n \"StdIntClientGetDiscAuth\",\n ],\n [\n PerformanceEvents.FetchAccountIdWithNativeBroker,\n \"FetchAccIdWithNtvBroker\",\n ],\n [\n PerformanceEvents.NativeInteractionClientAcquireToken,\n \"NtvIntClientAT\",\n ],\n [\n PerformanceEvents.BaseClientCreateTokenRequestHeaders,\n \"BaseClientCreateTReqHead\",\n ],\n [\n PerformanceEvents.NetworkClientSendPostRequestAsync,\n \"NetClientSendPost\",\n ],\n [\n PerformanceEvents.RefreshTokenClientExecutePostToTokenEndpoint,\n \"RTClientExecPost\",\n ],\n [\n PerformanceEvents.AuthorizationCodeClientExecutePostToTokenEndpoint,\n \"AuthCodeClientExecPost\",\n ],\n [PerformanceEvents.BrokerHandhshake, \"BrokerHandshake\"],\n [\n PerformanceEvents.AcquireTokenByRefreshTokenInBroker,\n \"ATByRTInBroker\",\n ],\n [PerformanceEvents.AcquireTokenByBroker, \"ATByBroker\"],\n [\n PerformanceEvents.RefreshTokenClientExecuteTokenRequest,\n \"RTClientExecTReq\",\n ],\n [PerformanceEvents.RefreshTokenClientAcquireToken, \"RTClientAT\"],\n [\n PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken,\n \"RTClientATWithCachedRT\",\n ],\n [\n PerformanceEvents.RefreshTokenClientAcquireTokenByRefreshToken,\n \"RTClientATByRT\",\n ],\n [\n PerformanceEvents.RefreshTokenClientCreateTokenRequestBody,\n \"RTClientCreateTReqBody\",\n ],\n [PerformanceEvents.AcquireTokenFromCache, \"ATFromCache\"],\n [\n PerformanceEvents.SilentFlowClientAcquireCachedToken,\n \"SltFlowClientATCached\",\n ],\n [\n PerformanceEvents.SilentFlowClientGenerateResultFromCacheRecord,\n \"SltFlowClientGenResFromCache\",\n ],\n [PerformanceEvents.AcquireTokenBySilentIframe, \"ATBySltIframe\"],\n [PerformanceEvents.InitializeBaseRequest, \"InitBaseReq\"],\n [PerformanceEvents.InitializeSilentRequest, \"InitSltReq\"],\n [\n PerformanceEvents.InitializeClientApplication,\n \"InitClientApplication\",\n ],\n [PerformanceEvents.InitializeCache, \"InitCache\"],\n [PerformanceEvents.ImportExistingCache, \"importCache\"],\n [PerformanceEvents.SetUserData, \"setUserData\"],\n [PerformanceEvents.LocalStorageUpdated, \"localStorageUpdated\"],\n [PerformanceEvents.SilentIframeClientTokenHelper, \"SIClientTHelper\"],\n [\n PerformanceEvents.SilentHandlerInitiateAuthRequest,\n \"SHandlerInitAuthReq\",\n ],\n [\n PerformanceEvents.SilentHandlerMonitorIframeForHash,\n \"SltHandlerMonitorIframeForHash\",\n ],\n [PerformanceEvents.SilentHandlerLoadFrame, \"SHandlerLoadFrame\"],\n [PerformanceEvents.SilentHandlerLoadFrameSync, \"SHandlerLoadFrameSync\"],\n\n [\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\n \"StdIntClientCreateAuthCodeClient\",\n ],\n [\n PerformanceEvents.StandardInteractionClientGetClientConfiguration,\n \"StdIntClientGetClientConf\",\n ],\n [\n PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,\n \"StdIntClientInitAuthReq\",\n ],\n\n [PerformanceEvents.GetAuthCodeUrl, \"GetAuthCodeUrl\"],\n\n [\n PerformanceEvents.HandleCodeResponseFromServer,\n \"HandleCodeResFromServer\",\n ],\n [PerformanceEvents.HandleCodeResponse, \"HandleCodeResp\"],\n [PerformanceEvents.HandleResponseEar, \"HandleRespEar\"],\n [PerformanceEvents.HandleResponseCode, \"HandleRespCode\"],\n [\n PerformanceEvents.HandleResponsePlatformBroker,\n \"HandleRespPlatBroker\",\n ],\n [PerformanceEvents.UpdateTokenEndpointAuthority, \"UpdTEndpointAuth\"],\n\n [PerformanceEvents.AuthClientAcquireToken, \"AuthClientAT\"],\n [PerformanceEvents.AuthClientExecuteTokenRequest, \"AuthClientExecTReq\"],\n [\n PerformanceEvents.AuthClientCreateTokenRequestBody,\n \"AuthClientCreateTReqBody\",\n ],\n [PerformanceEvents.PopTokenGenerateCnf, \"PopTGenCnf\"],\n [PerformanceEvents.PopTokenGenerateKid, \"PopTGenKid\"],\n [PerformanceEvents.HandleServerTokenResponse, \"HandleServerTRes\"],\n [PerformanceEvents.DeserializeResponse, \"DeserializeRes\"],\n [\n PerformanceEvents.AuthorityFactoryCreateDiscoveredInstance,\n \"AuthFactCreateDiscInst\",\n ],\n [\n PerformanceEvents.AuthorityResolveEndpointsAsync,\n \"AuthResolveEndpointsAsync\",\n ],\n [\n PerformanceEvents.AuthorityResolveEndpointsFromLocalSources,\n \"AuthResolveEndpointsFromLocal\",\n ],\n [\n PerformanceEvents.AuthorityGetCloudDiscoveryMetadataFromNetwork,\n \"AuthGetCDMetaFromNet\",\n ],\n [\n PerformanceEvents.AuthorityUpdateCloudDiscoveryMetadata,\n \"AuthUpdCDMeta\",\n ],\n [\n PerformanceEvents.AuthorityGetEndpointMetadataFromNetwork,\n \"AuthUpdCDMetaFromNet\",\n ],\n [\n PerformanceEvents.AuthorityUpdateEndpointMetadata,\n \"AuthUpdEndpointMeta\",\n ],\n [\n PerformanceEvents.AuthorityUpdateMetadataWithRegionalInformation,\n \"AuthUpdMetaWithRegInfo\",\n ],\n [PerformanceEvents.RegionDiscoveryDetectRegion, \"RegDiscDetectReg\"],\n [\n PerformanceEvents.RegionDiscoveryGetRegionFromIMDS,\n \"RegDiscGetRegFromIMDS\",\n ],\n [\n PerformanceEvents.RegionDiscoveryGetCurrentVersion,\n \"RegDiscGetCurrentVer\",\n ],\n [PerformanceEvents.AcquireTokenByCodeAsync, \"ATByCodeAsync\"],\n [\n PerformanceEvents.GetEndpointMetadataFromNetwork,\n \"GetEndpointMetaFromNet\",\n ],\n [\n PerformanceEvents.GetCloudDiscoveryMetadataFromNetworkMeasurement,\n \"GetCDMetaFromNet\",\n ],\n [\n PerformanceEvents.HandleRedirectPromiseMeasurement,\n \"HandleRedirectPromise\",\n ],\n [\n PerformanceEvents.HandleNativeRedirectPromiseMeasurement,\n \"HandleNtvRedirectPromise\",\n ],\n [\n PerformanceEvents.UpdateCloudDiscoveryMetadataMeasurement,\n \"UpdateCDMeta\",\n ],\n [\n PerformanceEvents.UsernamePasswordClientAcquireToken,\n \"UserPassClientAT\",\n ],\n [\n PerformanceEvents.NativeMessageHandlerHandshake,\n \"NtvMsgHandlerHandshake\",\n ],\n [PerformanceEvents.NativeGenerateAuthResult, \"NtvGenAuthRes\"],\n [PerformanceEvents.RemoveHiddenIframe, \"RemoveHiddenIframe\"],\n [\n PerformanceEvents.ClearTokensAndKeysWithClaims,\n \"ClearTAndKeysWithClaims\",\n ],\n [PerformanceEvents.CacheManagerGetRefreshToken, \"CacheManagerGetRT\"],\n [PerformanceEvents.GeneratePkceCodes, \"GenPkceCodes\"],\n [PerformanceEvents.GenerateCodeVerifier, \"GenCodeVerifier\"],\n [\n PerformanceEvents.GenerateCodeChallengeFromVerifier,\n \"GenCodeChallengeFromVerifier\",\n ],\n [PerformanceEvents.Sha256Digest, \"Sha256Digest\"],\n [PerformanceEvents.GetRandomValues, \"GetRandomValues\"],\n [PerformanceEvents.GenerateHKDF, \"genHKDF\"],\n [PerformanceEvents.GenerateBaseKey, \"genBaseKey\"],\n [PerformanceEvents.Base64Decode, \"b64Decode\"],\n [PerformanceEvents.UrlEncodeArr, \"urlEncArr\"],\n [PerformanceEvents.Encrypt, \"encrypt\"],\n [PerformanceEvents.Decrypt, \"decrypt\"],\n [PerformanceEvents.GenerateEarKey, \"genEarKey\"],\n [PerformanceEvents.DecryptEarResponse, \"decryptEarResp\"],\n ]);\n\n/**\n * State of the performance event.\n *\n * @export\n * @enum {number}\n */\nexport const PerformanceEventStatus = {\n NotStarted: 0,\n InProgress: 1,\n Completed: 2,\n} as const;\nexport type PerformanceEventStatus =\n (typeof PerformanceEventStatus)[keyof typeof PerformanceEventStatus];\n\nexport type SubMeasurement = {\n name: string;\n startTimeMs: number;\n};\n\n/**\n * Performance measurement taken by the library, including metadata about the request and application.\n *\n * @export\n * @typedef {PerformanceEvent}\n */\nexport type PerformanceEvent = {\n /**\n * Unique id for the event\n *\n * @type {string}\n */\n eventId: string;\n\n /**\n * State of the perforance measure.\n *\n * @type {PerformanceEventStatus}\n */\n status: PerformanceEventStatus;\n\n /**\n * Login authority used for the request\n *\n * @type {string}\n */\n authority: string;\n\n /**\n * Client id for the application\n *\n * @type {string}\n */\n clientId: string;\n\n /**\n * Correlation ID used for the request\n *\n * @type {string}\n */\n correlationId: string;\n\n /**\n * End-to-end duration in milliseconds.\n * @date 3/22/2022 - 3:40:05 PM\n *\n * @type {number}\n */\n durationMs?: number;\n\n /**\n * Visibility of the page when the event completed.\n * Read from: https://developer.mozilla.org/docs/Web/API/Page_Visibility_API\n *\n * @type {?(string | null)}\n */\n endPageVisibility?: string | null;\n\n /**\n * Whether the result was retrieved from the cache.\n *\n * @type {(boolean | null)}\n */\n fromCache?: boolean | null;\n\n /**\n * Event name (usually in the form of classNameFunctionName)\n *\n * @type {string}\n */\n name: string;\n\n /**\n * Visibility of the page when the event completed.\n * Read from: https://developer.mozilla.org/docs/Web/API/Page_Visibility_API\n *\n * @type {?(string | null)}\n */\n startPageVisibility?: string | null;\n\n /**\n * Unix millisecond timestamp when the event was initiated.\n *\n * @type {number}\n */\n startTimeMs: number;\n\n /**\n * Whether or the operation completed successfully.\n *\n * @type {(boolean | null)}\n */\n success?: boolean | null;\n\n /**\n * Add specific error code in case of failure\n *\n * @type {string}\n */\n errorCode?: string;\n\n /**\n * Add specific sub error code in case of failure\n *\n * @type {string}\n */\n subErrorCode?: string;\n\n /**\n * Server error number\n */\n serverErrorNo?: string;\n\n /**\n * Name of the library used for the operation.\n *\n * @type {string}\n */\n libraryName: string;\n\n /**\n * Version of the library used for the operation.\n *\n * @type {string}\n */\n libraryVersion: string;\n\n /**\n * Version of the library used last. Used to track upgrades and downgrades\n */\n previousLibraryVersion?: string;\n\n /**\n * Whether the response is from a native component (e.g., WAM)\n *\n * @type {?boolean}\n */\n isNativeBroker?: boolean;\n\n /**\n * Platform-specific fields, when calling STS and/or broker for token requests\n */\n isPlatformAuthorizeRequest?: boolean;\n isPlatformBrokerRequest?: boolean;\n brokerErrorName?: string;\n brokerErrorCode?: string;\n\n /**\n * Request ID returned from the response\n *\n * @type {?string}\n */\n requestId?: string;\n\n /**\n * Cache lookup policy\n *\n * @type {?number}\n */\n cacheLookupPolicy?: number | undefined;\n\n /**\n * Cache Outcome\n * @type {?number}\n */\n cacheOutcome?: number;\n\n /**\n * Amount of time spent in the JS queue in milliseconds.\n *\n * @type {?number}\n */\n queuedTimeMs?: number;\n\n /**\n * Sub-measurements for internal use. To be deleted before flushing.\n */\n incompleteSubMeasurements?: Map;\n\n visibilityChangeCount?: number;\n incompleteSubsCount?: number;\n\n /**\n * CorrelationId of the in progress iframe request that was awaited\n */\n awaitIframeCorrelationId?: string;\n /**\n * Amount of times queued in the JS event queue.\n *\n * @type {?number}\n */\n queuedCount?: number;\n /**\n * Amount of manually completed queue events.\n *\n * @type {?number}\n */\n queuedManuallyCompletedCount?: number;\n\n /**\n * Size of the id token\n *\n * @type {number}\n */\n idTokenSize?: number;\n\n /**\n *\n * Size of the access token\n *\n * @type {number}\n */\n\n accessTokenSize?: number;\n\n /**\n *\n * Size of the refresh token\n *\n * @type {number}\n */\n\n refreshTokenSize?: number | undefined;\n\n /**\n * Application name as specified by the app.\n *\n * @type {?string}\n */\n appName?: string;\n\n /**\n * Application version as specified by the app.\n *\n * @type {?string}\n */\n appVersion?: string;\n\n /**\n * The following are fields that may be emitted in native broker scenarios\n */\n extensionId?: string;\n extensionVersion?: string;\n matsBrokerVersion?: string;\n matsAccountJoinOnStart?: string;\n matsAccountJoinOnEnd?: string;\n matsDeviceJoin?: string;\n matsPromptBehavior?: string;\n matsApiErrorCode?: number;\n matsUiVisible?: boolean;\n matsSilentCode?: number;\n matsSilentBiSubCode?: number;\n matsSilentMessage?: string;\n matsSilentStatus?: number;\n matsHttpStatus?: number;\n matsHttpEventCount?: number;\n\n /**\n * Http POST metadata\n */\n httpVerToken?: string;\n httpStatus?: number;\n contentTypeHeader?: string;\n contentLengthHeader?: string;\n\n /**\n * Platform broker fields\n */\n allowPlatformBroker?: boolean;\n extensionInstalled?: boolean;\n extensionHandshakeTimeoutMs?: number;\n extensionHandshakeTimedOut?: boolean;\n\n /**\n * Nested App Auth Fields\n */\n nestedAppAuthRequest?: boolean;\n\n /**\n * Multiple matched access/id/refresh tokens in the cache\n */\n multiMatchedAT?: number;\n multiMatchedID?: number;\n multiMatchedRT?: number;\n\n errorName?: string;\n errorStack?: string[];\n\n // Event context as JSON string\n context?: string;\n\n // Cache Data\n cacheLocation?: string;\n cacheRetentionDays?: number;\n\n // Number of tokens in the cache to be reported when cache quota is exceeded\n cacheRtCount?: number;\n cacheIdCount?: number;\n cacheAtCount?: number;\n\n // Scenario id to track custom user prompts\n scenarioId?: string;\n\n accountType?: \"AAD\" | \"MSA\" | \"B2C\";\n\n /**\n * Server error that triggers a request retry\n *\n * @type {string}\n */\n retryError?: string;\n\n embeddedClientId?: string;\n embeddedRedirectUri?: string;\n\n isAsyncPopup?: boolean;\n\n rtExpiresOnMs?: number;\n\n sidFromClaims?: boolean;\n sidFromRequest?: boolean;\n loginHintFromRequest?: boolean;\n loginHintFromUpn?: boolean;\n loginHintFromClaim?: boolean;\n domainHintFromRequest?: boolean;\n\n prompt?: string;\n\n usePreGeneratedPkce?: boolean;\n\n // Number of MSAL JS instances in the frame\n msalInstanceCount?: number;\n // Number of MSAL JS instances using the same client id in the frame\n sameClientIdInstanceCount?: number;\n\n navigateCallbackResult?: boolean;\n};\n\nexport type PerformanceEventContext = {\n dur?: number;\n err?: string;\n subErr?: string;\n fail?: number;\n};\n\nexport type PerformanceEventStackedContext = PerformanceEventContext & {\n name?: string;\n childErr?: string;\n};\n\nexport const IntFields: ReadonlySet = new Set([\n \"accessTokenSize\",\n \"durationMs\",\n \"idTokenSize\",\n \"matsSilentStatus\",\n \"matsHttpStatus\",\n \"refreshTokenSize\",\n \"queuedTimeMs\",\n \"startTimeMs\",\n \"status\",\n \"multiMatchedAT\",\n \"multiMatchedID\",\n \"multiMatchedRT\",\n \"unencryptedCacheCount\",\n \"encryptedCacheExpiredCount\",\n \"oldAccountCount\",\n \"oldAccessCount\",\n \"oldIdCount\",\n \"oldRefreshCount\",\n \"currAccountCount\",\n \"currAccessCount\",\n \"currIdCount\",\n \"currRefreshCount\",\n \"expiredCacheRemovedCount\",\n \"upgradedCacheCount\",\n]);\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n IPerformanceClient,\n InProgressPerformanceEvent,\n} from \"./IPerformanceClient.js\";\nimport { IPerformanceMeasurement } from \"./IPerformanceMeasurement.js\";\nimport {\n PerformanceEvent,\n PerformanceEventStatus,\n} from \"./PerformanceEvent.js\";\n\nexport class StubPerformanceMeasurement implements IPerformanceMeasurement {\n startMeasurement(): void {\n return;\n }\n endMeasurement(): void {\n return;\n }\n flushMeasurement(): number | null {\n return null;\n }\n}\n\nexport class StubPerformanceClient implements IPerformanceClient {\n generateId(): string {\n return \"callback-id\";\n }\n\n startMeasurement(\n measureName: string,\n correlationId?: string | undefined\n ): InProgressPerformanceEvent {\n return {\n end: () => null,\n discard: () => {},\n add: () => {},\n increment: () => {},\n event: {\n eventId: this.generateId(),\n status: PerformanceEventStatus.InProgress,\n authority: \"\",\n libraryName: \"\",\n libraryVersion: \"\",\n clientId: \"\",\n name: measureName,\n startTimeMs: Date.now(),\n correlationId: correlationId || \"\",\n },\n measurement: new StubPerformanceMeasurement(),\n };\n }\n\n startPerformanceMeasurement(): IPerformanceMeasurement {\n return new StubPerformanceMeasurement();\n }\n calculateQueuedTime(): number {\n return 0;\n }\n\n addQueueMeasurement(): void {\n return;\n }\n\n setPreQueueTime(): void {\n return;\n }\n\n endMeasurement(): PerformanceEvent | null {\n return null;\n }\n\n discardMeasurements(): void {\n return;\n }\n\n removePerformanceCallback(): boolean {\n return true;\n }\n\n addPerformanceCallback(): string {\n return \"\";\n }\n\n emitEvents(): void {\n return;\n }\n\n addFields(): void {\n return;\n }\n\n incrementFields(): void {\n return;\n }\n\n cacheEventByCorrelationId(): void {\n return;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { INetworkModule } from \"../network/INetworkModule.js\";\nimport { DEFAULT_CRYPTO_IMPLEMENTATION, ICrypto } from \"../crypto/ICrypto.js\";\nimport { ILoggerCallback, Logger, LogLevel } from \"../logger/Logger.js\";\nimport {\n Constants,\n DEFAULT_TOKEN_RENEWAL_OFFSET_SEC,\n} from \"../utils/Constants.js\";\nimport { version } from \"../packageMetadata.js\";\nimport type { Authority } from \"../authority/Authority.js\";\nimport { AzureCloudInstance } from \"../authority/AuthorityOptions.js\";\nimport { CacheManager, DefaultStorageClass } from \"../cache/CacheManager.js\";\nimport { ServerTelemetryManager } from \"../telemetry/server/ServerTelemetryManager.js\";\nimport { ICachePlugin } from \"../cache/interface/ICachePlugin.js\";\nimport { ISerializableTokenCache } from \"../cache/interface/ISerializableTokenCache.js\";\nimport { ClientCredentials } from \"../account/ClientCredentials.js\";\nimport { ProtocolMode } from \"../authority/ProtocolMode.js\";\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n} from \"../error/ClientAuthError.js\";\nimport { StubPerformanceClient } from \"../telemetry/performance/StubPerformanceClient.js\";\n\n/**\n * Use the configuration object to configure MSAL Modules and initialize the base interfaces for MSAL.\n *\n * This object allows you to configure important elements of MSAL functionality:\n * - authOptions - Authentication for application\n * - cryptoInterface - Implementation of crypto functions\n * - libraryInfo - Library metadata\n * - telemetry - Telemetry options and data\n * - loggerOptions - Logging for application\n * - networkInterface - Network implementation\n * - storageInterface - Storage implementation\n * - systemOptions - Additional library options\n * - clientCredentials - Credentials options for confidential clients\n * @internal\n */\nexport type ClientConfiguration = {\n authOptions: AuthOptions;\n systemOptions?: SystemOptions;\n loggerOptions?: LoggerOptions;\n cacheOptions?: CacheOptions;\n storageInterface?: CacheManager;\n networkInterface?: INetworkModule;\n cryptoInterface?: ICrypto;\n clientCredentials?: ClientCredentials;\n libraryInfo?: LibraryInfo;\n telemetry?: TelemetryOptions;\n serverTelemetryManager?: ServerTelemetryManager | null;\n persistencePlugin?: ICachePlugin | null;\n serializableCache?: ISerializableTokenCache | null;\n};\n\nexport type CommonClientConfiguration = {\n authOptions: Required;\n systemOptions: Required;\n loggerOptions: Required;\n cacheOptions: Required;\n storageInterface: CacheManager;\n networkInterface: INetworkModule;\n cryptoInterface: Required;\n libraryInfo: LibraryInfo;\n telemetry: Required;\n serverTelemetryManager: ServerTelemetryManager | null;\n clientCredentials: ClientCredentials;\n persistencePlugin: ICachePlugin | null;\n serializableCache: ISerializableTokenCache | null;\n};\n\n/**\n * Use this to configure the auth options in the ClientConfiguration object\n *\n * - clientId - Client ID of your app registered with our Application registration portal : https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredAppsPreview in Microsoft Identity Platform\n * - authority - You can configure a specific authority, defaults to \" \" or \"https://login.microsoftonline.com/common\"\n * - knownAuthorities - An array of URIs that are known to be valid. Used in B2C scenarios.\n * - cloudDiscoveryMetadata - A string containing the cloud discovery response. Used in AAD scenarios.\n * - clientCapabilities - Array of capabilities which will be added to the claims.access_token.xms_cc request property on every network request.\n * - protocolMode - Enum that represents the protocol that msal follows. Used for configuring proper endpoints.\n * - skipAuthorityMetadataCache - A flag to choose whether to use or not use the local metadata cache during authority initialization. Defaults to false.\n * - instanceAware - A flag of whether the STS will send back additional parameters to specify where the tokens should be retrieved from.\n * - redirectUri - The redirect URI where authentication responses can be received by your application. It must exactly match one of the redirect URIs registered in the Azure portal.\n * - encodeExtraQueryParams - A flag to choose whether to encode the extra query parameters or not. Defaults to false.\n * @internal\n */\nexport type AuthOptions = {\n clientId: string;\n authority: Authority;\n redirectUri: string;\n clientCapabilities?: Array;\n azureCloudOptions?: AzureCloudOptions;\n skipAuthorityMetadataCache?: boolean;\n instanceAware?: boolean;\n /**\n * @deprecated This flag is deprecated and will be removed in the next major version where all extra query params will be encoded by default.\n */\n encodeExtraQueryParams?: boolean;\n};\n\n/**\n * Use this to configure token renewal info in the Configuration object\n *\n * - tokenRenewalOffsetSeconds - Sets the window of offset needed to renew the token before expiry\n */\nexport type SystemOptions = {\n tokenRenewalOffsetSeconds?: number;\n preventCorsPreflight?: boolean;\n};\n\n/**\n * Use this to configure the logging that MSAL does, by configuring logger options in the Configuration object\n *\n * - loggerCallback - Callback for logger\n * - piiLoggingEnabled - Sets whether pii logging is enabled\n * - logLevel - Sets the level at which logging happens\n * - correlationId - Sets the correlationId printed by the logger\n */\nexport type LoggerOptions = {\n loggerCallback?: ILoggerCallback;\n piiLoggingEnabled?: boolean;\n logLevel?: LogLevel;\n correlationId?: string;\n};\n\n/**\n * Use this to configure credential cache preferences in the ClientConfiguration object\n *\n * - claimsBasedCachingEnabled - Sets whether tokens should be cached based on the claims hash. Default is false.\n */\nexport type CacheOptions = {\n /**\n * @deprecated claimsBasedCachingEnabled is deprecated and will be removed in the next major version.\n */\n claimsBasedCachingEnabled?: boolean;\n};\n\n/**\n * Library-specific options\n */\nexport type LibraryInfo = {\n sku: string;\n version: string;\n cpu: string;\n os: string;\n};\n\n/**\n * AzureCloudInstance specific options\n *\n * - azureCloudInstance - string enum providing short notation for soverign and public cloud authorities\n * - tenant - provision to provide the tenant info\n */\nexport type AzureCloudOptions = {\n azureCloudInstance: AzureCloudInstance;\n tenant?: string;\n};\n\nexport type TelemetryOptions = {\n application: ApplicationTelemetry;\n};\n\n/**\n * Telemetry information sent on request\n * - appName: Unique string name of an application\n * - appVersion: Version of the application using MSAL\n */\nexport type ApplicationTelemetry = {\n appName: string;\n appVersion: string;\n};\n\nexport const DEFAULT_SYSTEM_OPTIONS: Required = {\n tokenRenewalOffsetSeconds: DEFAULT_TOKEN_RENEWAL_OFFSET_SEC,\n preventCorsPreflight: false,\n};\n\nconst DEFAULT_LOGGER_IMPLEMENTATION: Required = {\n loggerCallback: () => {\n // allow users to not set loggerCallback\n },\n piiLoggingEnabled: false,\n logLevel: LogLevel.Info,\n correlationId: Constants.EMPTY_STRING,\n};\n\nconst DEFAULT_CACHE_OPTIONS: Required = {\n claimsBasedCachingEnabled: false,\n};\n\nconst DEFAULT_NETWORK_IMPLEMENTATION: INetworkModule = {\n async sendGetRequestAsync(): Promise {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n },\n async sendPostRequestAsync(): Promise {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n },\n};\n\nconst DEFAULT_LIBRARY_INFO: LibraryInfo = {\n sku: Constants.SKU,\n version: version,\n cpu: Constants.EMPTY_STRING,\n os: Constants.EMPTY_STRING,\n};\n\nconst DEFAULT_CLIENT_CREDENTIALS: ClientCredentials = {\n clientSecret: Constants.EMPTY_STRING,\n clientAssertion: undefined,\n};\n\nconst DEFAULT_AZURE_CLOUD_OPTIONS: AzureCloudOptions = {\n azureCloudInstance: AzureCloudInstance.None,\n tenant: `${Constants.DEFAULT_COMMON_TENANT}`,\n};\n\nconst DEFAULT_TELEMETRY_OPTIONS: Required = {\n application: {\n appName: \"\",\n appVersion: \"\",\n },\n};\n\n/**\n * Function that sets the default options when not explicitly configured from app developer\n *\n * @param Configuration\n *\n * @returns Configuration\n */\nexport function buildClientConfiguration({\n authOptions: userAuthOptions,\n systemOptions: userSystemOptions,\n loggerOptions: userLoggerOption,\n cacheOptions: userCacheOptions,\n storageInterface: storageImplementation,\n networkInterface: networkImplementation,\n cryptoInterface: cryptoImplementation,\n clientCredentials: clientCredentials,\n libraryInfo: libraryInfo,\n telemetry: telemetry,\n serverTelemetryManager: serverTelemetryManager,\n persistencePlugin: persistencePlugin,\n serializableCache: serializableCache,\n}: ClientConfiguration): CommonClientConfiguration {\n const loggerOptions = {\n ...DEFAULT_LOGGER_IMPLEMENTATION,\n ...userLoggerOption,\n };\n\n return {\n authOptions: buildAuthOptions(userAuthOptions),\n systemOptions: { ...DEFAULT_SYSTEM_OPTIONS, ...userSystemOptions },\n loggerOptions: loggerOptions,\n cacheOptions: { ...DEFAULT_CACHE_OPTIONS, ...userCacheOptions },\n storageInterface:\n storageImplementation ||\n new DefaultStorageClass(\n userAuthOptions.clientId,\n DEFAULT_CRYPTO_IMPLEMENTATION,\n new Logger(loggerOptions),\n new StubPerformanceClient()\n ),\n networkInterface:\n networkImplementation || DEFAULT_NETWORK_IMPLEMENTATION,\n cryptoInterface: cryptoImplementation || DEFAULT_CRYPTO_IMPLEMENTATION,\n clientCredentials: clientCredentials || DEFAULT_CLIENT_CREDENTIALS,\n libraryInfo: { ...DEFAULT_LIBRARY_INFO, ...libraryInfo },\n telemetry: { ...DEFAULT_TELEMETRY_OPTIONS, ...telemetry },\n serverTelemetryManager: serverTelemetryManager || null,\n persistencePlugin: persistencePlugin || null,\n serializableCache: serializableCache || null,\n };\n}\n\n/**\n * Construct authoptions from the client and platform passed values\n * @param authOptions\n */\nfunction buildAuthOptions(authOptions: AuthOptions): Required {\n return {\n clientCapabilities: [],\n azureCloudOptions: DEFAULT_AZURE_CLOUD_OPTIONS,\n skipAuthorityMetadataCache: false,\n instanceAware: false,\n encodeExtraQueryParams: false,\n ...authOptions,\n };\n}\n\n/**\n * Returns true if config has protocolMode set to ProtocolMode.OIDC, false otherwise\n * @param ClientConfiguration\n */\nexport function isOidcProtocolMode(config: ClientConfiguration): boolean {\n return (\n config.authOptions.authority.options.protocolMode === ProtocolMode.OIDC\n );\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport type CcsCredential = {\n credential: string;\n type: CcsCredentialType;\n};\n\nexport const CcsCredentialType = {\n HOME_ACCOUNT_ID: \"home_account_id\",\n UPN: \"UPN\",\n} as const;\nexport type CcsCredentialType =\n (typeof CcsCredentialType)[keyof typeof CcsCredentialType];\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n createClientAuthError,\n ClientAuthErrorCodes,\n} from \"../error/ClientAuthError.js\";\nimport { Separators, Constants } from \"../utils/Constants.js\";\n\n/**\n * Client info object which consists of two IDs. Need to add more info here.\n */\nexport type ClientInfo = {\n uid: string;\n utid: string;\n};\n\n/**\n * Function to build a client info object from server clientInfo string\n * @param rawClientInfo\n * @param crypto\n */\nexport function buildClientInfo(\n rawClientInfo: string,\n base64Decode: (input: string) => string\n): ClientInfo {\n if (!rawClientInfo) {\n throw createClientAuthError(ClientAuthErrorCodes.clientInfoEmptyError);\n }\n\n try {\n const decodedClientInfo: string = base64Decode(rawClientInfo);\n return JSON.parse(decodedClientInfo) as ClientInfo;\n } catch (e) {\n throw createClientAuthError(\n ClientAuthErrorCodes.clientInfoDecodingError\n );\n }\n}\n\n/**\n * Function to build a client info object from cached homeAccountId string\n * @param homeAccountId\n */\nexport function buildClientInfoFromHomeAccountId(\n homeAccountId: string\n): ClientInfo {\n if (!homeAccountId) {\n throw createClientAuthError(\n ClientAuthErrorCodes.clientInfoDecodingError\n );\n }\n const clientInfoParts: string[] = homeAccountId.split(\n Separators.CLIENT_INFO_SEPARATOR,\n 2\n );\n return {\n uid: clientInfoParts[0],\n utid:\n clientInfoParts.length < 2\n ? Constants.EMPTY_STRING\n : clientInfoParts[1],\n };\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const CLIENT_ID = \"client_id\";\nexport const REDIRECT_URI = \"redirect_uri\";\nexport const RESPONSE_TYPE = \"response_type\";\nexport const RESPONSE_MODE = \"response_mode\";\nexport const GRANT_TYPE = \"grant_type\";\nexport const CLAIMS = \"claims\";\nexport const SCOPE = \"scope\";\nexport const ERROR = \"error\";\nexport const ERROR_DESCRIPTION = \"error_description\";\nexport const ACCESS_TOKEN = \"access_token\";\nexport const ID_TOKEN = \"id_token\";\nexport const REFRESH_TOKEN = \"refresh_token\";\nexport const EXPIRES_IN = \"expires_in\";\nexport const REFRESH_TOKEN_EXPIRES_IN = \"refresh_token_expires_in\";\nexport const STATE = \"state\";\nexport const NONCE = \"nonce\";\nexport const PROMPT = \"prompt\";\nexport const SESSION_STATE = \"session_state\";\nexport const CLIENT_INFO = \"client_info\";\nexport const CODE = \"code\";\nexport const CODE_CHALLENGE = \"code_challenge\";\nexport const CODE_CHALLENGE_METHOD = \"code_challenge_method\";\nexport const CODE_VERIFIER = \"code_verifier\";\nexport const CLIENT_REQUEST_ID = \"client-request-id\";\nexport const X_CLIENT_SKU = \"x-client-SKU\";\nexport const X_CLIENT_VER = \"x-client-VER\";\nexport const X_CLIENT_OS = \"x-client-OS\";\nexport const X_CLIENT_CPU = \"x-client-CPU\";\nexport const X_CLIENT_CURR_TELEM = \"x-client-current-telemetry\";\nexport const X_CLIENT_LAST_TELEM = \"x-client-last-telemetry\";\nexport const X_MS_LIB_CAPABILITY = \"x-ms-lib-capability\";\nexport const X_APP_NAME = \"x-app-name\";\nexport const X_APP_VER = \"x-app-ver\";\nexport const POST_LOGOUT_URI = \"post_logout_redirect_uri\";\nexport const ID_TOKEN_HINT = \"id_token_hint\";\nexport const DEVICE_CODE = \"device_code\";\nexport const CLIENT_SECRET = \"client_secret\";\nexport const CLIENT_ASSERTION = \"client_assertion\";\nexport const CLIENT_ASSERTION_TYPE = \"client_assertion_type\";\nexport const TOKEN_TYPE = \"token_type\";\nexport const REQ_CNF = \"req_cnf\";\nexport const OBO_ASSERTION = \"assertion\";\nexport const REQUESTED_TOKEN_USE = \"requested_token_use\";\nexport const ON_BEHALF_OF = \"on_behalf_of\";\nexport const FOCI = \"foci\";\nexport const CCS_HEADER = \"X-AnchorMailbox\";\nexport const RETURN_SPA_CODE = \"return_spa_code\";\nexport const NATIVE_BROKER = \"nativebroker\";\nexport const LOGOUT_HINT = \"logout_hint\";\nexport const SID = \"sid\";\nexport const LOGIN_HINT = \"login_hint\";\nexport const DOMAIN_HINT = \"domain_hint\";\nexport const X_CLIENT_EXTRA_SKU = \"x-client-xtra-sku\";\nexport const BROKER_CLIENT_ID = \"brk_client_id\";\nexport const BROKER_REDIRECT_URI = \"brk_redirect_uri\";\nexport const INSTANCE_AWARE = \"instance_aware\";\nexport const EAR_JWK = \"ear_jwk\";\nexport const EAR_JWE_CRYPTO = \"ear_jwe_crypto\";\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ResponseMode,\n CLIENT_INFO,\n AuthenticationScheme,\n ClaimsRequestKeys,\n PasswordGrantConstants,\n OIDC_DEFAULT_SCOPES,\n ThrottlingConstants,\n HeaderNames,\n OAuthResponseType,\n} from \"../utils/Constants.js\";\nimport * as AADServerParamKeys from \"../constants/AADServerParamKeys.js\";\nimport { ScopeSet } from \"./ScopeSet.js\";\nimport {\n createClientConfigurationError,\n ClientConfigurationErrorCodes,\n} from \"../error/ClientConfigurationError.js\";\nimport { StringDict } from \"../utils/MsalTypes.js\";\nimport {\n ApplicationTelemetry,\n LibraryInfo,\n} from \"../config/ClientConfiguration.js\";\nimport { ServerTelemetryManager } from \"../telemetry/server/ServerTelemetryManager.js\";\nimport { ClientInfo } from \"../account/ClientInfo.js\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\n\nexport function instrumentBrokerParams(\n parameters: Map,\n correlationId?: string,\n performanceClient?: IPerformanceClient\n): void {\n if (!correlationId) {\n return;\n }\n\n const clientId = parameters.get(AADServerParamKeys.CLIENT_ID);\n if (clientId && parameters.has(AADServerParamKeys.BROKER_CLIENT_ID)) {\n performanceClient?.addFields(\n {\n embeddedClientId: clientId,\n embeddedRedirectUri: parameters.get(\n AADServerParamKeys.REDIRECT_URI\n ),\n },\n correlationId\n );\n }\n}\n\n/**\n * Add the given response_type\n * @param parameters\n * @param responseType\n */\nexport function addResponseType(\n parameters: Map,\n responseType: OAuthResponseType\n): void {\n parameters.set(AADServerParamKeys.RESPONSE_TYPE, responseType);\n}\n\n/**\n * add response_mode. defaults to query.\n * @param responseMode\n */\nexport function addResponseMode(\n parameters: Map,\n responseMode?: ResponseMode\n): void {\n parameters.set(\n AADServerParamKeys.RESPONSE_MODE,\n responseMode ? responseMode : ResponseMode.QUERY\n );\n}\n\n/**\n * Add flag to indicate STS should attempt to use WAM if available\n */\nexport function addNativeBroker(parameters: Map): void {\n parameters.set(AADServerParamKeys.NATIVE_BROKER, \"1\");\n}\n\n/**\n * add scopes. set addOidcScopes to false to prevent default scopes in non-user scenarios\n * @param scopeSet\n * @param addOidcScopes\n */\nexport function addScopes(\n parameters: Map,\n scopes: string[],\n addOidcScopes: boolean = true,\n defaultScopes: Array = OIDC_DEFAULT_SCOPES\n): void {\n // Always add openid to the scopes when adding OIDC scopes\n if (\n addOidcScopes &&\n !defaultScopes.includes(\"openid\") &&\n !scopes.includes(\"openid\")\n ) {\n defaultScopes.push(\"openid\");\n }\n const requestScopes = addOidcScopes\n ? [...(scopes || []), ...defaultScopes]\n : scopes || [];\n const scopeSet = new ScopeSet(requestScopes);\n parameters.set(AADServerParamKeys.SCOPE, scopeSet.printScopes());\n}\n\n/**\n * add clientId\n * @param clientId\n */\nexport function addClientId(\n parameters: Map,\n clientId: string\n): void {\n parameters.set(AADServerParamKeys.CLIENT_ID, clientId);\n}\n\n/**\n * add redirect_uri\n * @param redirectUri\n */\nexport function addRedirectUri(\n parameters: Map,\n redirectUri: string\n): void {\n parameters.set(AADServerParamKeys.REDIRECT_URI, redirectUri);\n}\n\n/**\n * add post logout redirectUri\n * @param redirectUri\n */\nexport function addPostLogoutRedirectUri(\n parameters: Map,\n redirectUri: string\n): void {\n parameters.set(AADServerParamKeys.POST_LOGOUT_URI, redirectUri);\n}\n\n/**\n * add id_token_hint to logout request\n * @param idTokenHint\n */\nexport function addIdTokenHint(\n parameters: Map,\n idTokenHint: string\n): void {\n parameters.set(AADServerParamKeys.ID_TOKEN_HINT, idTokenHint);\n}\n\n/**\n * add domain_hint\n * @param domainHint\n */\nexport function addDomainHint(\n parameters: Map,\n domainHint: string\n): void {\n parameters.set(AADServerParamKeys.DOMAIN_HINT, domainHint);\n}\n\n/**\n * add login_hint\n * @param loginHint\n */\nexport function addLoginHint(\n parameters: Map,\n loginHint: string\n): void {\n parameters.set(AADServerParamKeys.LOGIN_HINT, loginHint);\n}\n\n/**\n * Adds the CCS (Cache Credential Service) query parameter for login_hint\n * @param loginHint\n */\nexport function addCcsUpn(\n parameters: Map,\n loginHint: string\n): void {\n parameters.set(HeaderNames.CCS_HEADER, `UPN:${loginHint}`);\n}\n\n/**\n * Adds the CCS (Cache Credential Service) query parameter for account object\n * @param loginHint\n */\nexport function addCcsOid(\n parameters: Map,\n clientInfo: ClientInfo\n): void {\n parameters.set(\n HeaderNames.CCS_HEADER,\n `Oid:${clientInfo.uid}@${clientInfo.utid}`\n );\n}\n\n/**\n * add sid\n * @param sid\n */\nexport function addSid(parameters: Map, sid: string): void {\n parameters.set(AADServerParamKeys.SID, sid);\n}\n\n/**\n * add claims\n * @param claims\n */\nexport function addClaims(\n parameters: Map,\n claims?: string,\n clientCapabilities?: Array\n): void {\n const mergedClaims = addClientCapabilitiesToClaims(\n claims,\n clientCapabilities\n );\n try {\n JSON.parse(mergedClaims);\n } catch (e) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.invalidClaims\n );\n }\n parameters.set(AADServerParamKeys.CLAIMS, mergedClaims);\n}\n\n/**\n * add correlationId\n * @param correlationId\n */\nexport function addCorrelationId(\n parameters: Map,\n correlationId: string\n): void {\n parameters.set(AADServerParamKeys.CLIENT_REQUEST_ID, correlationId);\n}\n\n/**\n * add library info query params\n * @param libraryInfo\n */\nexport function addLibraryInfo(\n parameters: Map,\n libraryInfo: LibraryInfo\n): void {\n // Telemetry Info\n parameters.set(AADServerParamKeys.X_CLIENT_SKU, libraryInfo.sku);\n parameters.set(AADServerParamKeys.X_CLIENT_VER, libraryInfo.version);\n if (libraryInfo.os) {\n parameters.set(AADServerParamKeys.X_CLIENT_OS, libraryInfo.os);\n }\n if (libraryInfo.cpu) {\n parameters.set(AADServerParamKeys.X_CLIENT_CPU, libraryInfo.cpu);\n }\n}\n\n/**\n * Add client telemetry parameters\n * @param appTelemetry\n */\nexport function addApplicationTelemetry(\n parameters: Map,\n appTelemetry: ApplicationTelemetry\n): void {\n if (appTelemetry?.appName) {\n parameters.set(AADServerParamKeys.X_APP_NAME, appTelemetry.appName);\n }\n\n if (appTelemetry?.appVersion) {\n parameters.set(AADServerParamKeys.X_APP_VER, appTelemetry.appVersion);\n }\n}\n\n/**\n * add prompt\n * @param prompt\n */\nexport function addPrompt(\n parameters: Map,\n prompt: string\n): void {\n parameters.set(AADServerParamKeys.PROMPT, prompt);\n}\n\n/**\n * add state\n * @param state\n */\nexport function addState(parameters: Map, state: string): void {\n if (state) {\n parameters.set(AADServerParamKeys.STATE, state);\n }\n}\n\n/**\n * add nonce\n * @param nonce\n */\nexport function addNonce(parameters: Map, nonce: string): void {\n parameters.set(AADServerParamKeys.NONCE, nonce);\n}\n\n/**\n * add code_challenge and code_challenge_method\n * - throw if either of them are not passed\n * @param codeChallenge\n * @param codeChallengeMethod\n */\nexport function addCodeChallengeParams(\n parameters: Map,\n codeChallenge?: string,\n codeChallengeMethod?: string\n): void {\n if (codeChallenge && codeChallengeMethod) {\n parameters.set(AADServerParamKeys.CODE_CHALLENGE, codeChallenge);\n parameters.set(\n AADServerParamKeys.CODE_CHALLENGE_METHOD,\n codeChallengeMethod\n );\n } else {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.pkceParamsMissing\n );\n }\n}\n\n/**\n * add the `authorization_code` passed by the user to exchange for a token\n * @param code\n */\nexport function addAuthorizationCode(\n parameters: Map,\n code: string\n): void {\n parameters.set(AADServerParamKeys.CODE, code);\n}\n\n/**\n * add the `authorization_code` passed by the user to exchange for a token\n * @param code\n */\nexport function addDeviceCode(\n parameters: Map,\n code: string\n): void {\n parameters.set(AADServerParamKeys.DEVICE_CODE, code);\n}\n\n/**\n * add the `refreshToken` passed by the user\n * @param refreshToken\n */\nexport function addRefreshToken(\n parameters: Map,\n refreshToken: string\n): void {\n parameters.set(AADServerParamKeys.REFRESH_TOKEN, refreshToken);\n}\n\n/**\n * add the `code_verifier` passed by the user to exchange for a token\n * @param codeVerifier\n */\nexport function addCodeVerifier(\n parameters: Map,\n codeVerifier: string\n): void {\n parameters.set(AADServerParamKeys.CODE_VERIFIER, codeVerifier);\n}\n\n/**\n * add client_secret\n * @param clientSecret\n */\nexport function addClientSecret(\n parameters: Map,\n clientSecret: string\n): void {\n parameters.set(AADServerParamKeys.CLIENT_SECRET, clientSecret);\n}\n\n/**\n * add clientAssertion for confidential client flows\n * @param clientAssertion\n */\nexport function addClientAssertion(\n parameters: Map,\n clientAssertion: string\n): void {\n if (clientAssertion) {\n parameters.set(AADServerParamKeys.CLIENT_ASSERTION, clientAssertion);\n }\n}\n\n/**\n * add clientAssertionType for confidential client flows\n * @param clientAssertionType\n */\nexport function addClientAssertionType(\n parameters: Map,\n clientAssertionType: string\n): void {\n if (clientAssertionType) {\n parameters.set(\n AADServerParamKeys.CLIENT_ASSERTION_TYPE,\n clientAssertionType\n );\n }\n}\n\n/**\n * add OBO assertion for confidential client flows\n * @param clientAssertion\n */\nexport function addOboAssertion(\n parameters: Map,\n oboAssertion: string\n): void {\n parameters.set(AADServerParamKeys.OBO_ASSERTION, oboAssertion);\n}\n\n/**\n * add grant type\n * @param grantType\n */\nexport function addRequestTokenUse(\n parameters: Map,\n tokenUse: string\n): void {\n parameters.set(AADServerParamKeys.REQUESTED_TOKEN_USE, tokenUse);\n}\n\n/**\n * add grant type\n * @param grantType\n */\nexport function addGrantType(\n parameters: Map,\n grantType: string\n): void {\n parameters.set(AADServerParamKeys.GRANT_TYPE, grantType);\n}\n\n/**\n * add client info\n *\n */\nexport function addClientInfo(parameters: Map): void {\n parameters.set(CLIENT_INFO, \"1\");\n}\n\nexport function addInstanceAware(parameters: Map): void {\n if (!parameters.has(AADServerParamKeys.INSTANCE_AWARE)) {\n parameters.set(AADServerParamKeys.INSTANCE_AWARE, \"true\");\n }\n}\n\n/**\n * add extraQueryParams\n * @param eQParams\n */\nexport function addExtraQueryParameters(\n parameters: Map,\n eQParams: StringDict\n): void {\n Object.entries(eQParams).forEach(([key, value]) => {\n if (!parameters.has(key) && value) {\n parameters.set(key, value);\n }\n });\n}\n\nexport function addClientCapabilitiesToClaims(\n claims?: string,\n clientCapabilities?: Array\n): string {\n let mergedClaims: object;\n\n // Parse provided claims into JSON object or initialize empty object\n if (!claims) {\n mergedClaims = {};\n } else {\n try {\n mergedClaims = JSON.parse(claims);\n } catch (e) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.invalidClaims\n );\n }\n }\n\n if (clientCapabilities && clientCapabilities.length > 0) {\n if (!mergedClaims.hasOwnProperty(ClaimsRequestKeys.ACCESS_TOKEN)) {\n // Add access_token key to claims object\n mergedClaims[ClaimsRequestKeys.ACCESS_TOKEN] = {};\n }\n\n // Add xms_cc claim with provided clientCapabilities to access_token key\n mergedClaims[ClaimsRequestKeys.ACCESS_TOKEN][ClaimsRequestKeys.XMS_CC] =\n {\n values: clientCapabilities,\n };\n }\n\n return JSON.stringify(mergedClaims);\n}\n\n/**\n * adds `username` for Password Grant flow\n * @param username\n */\nexport function addUsername(\n parameters: Map,\n username: string\n): void {\n parameters.set(PasswordGrantConstants.username, username);\n}\n\n/**\n * adds `password` for Password Grant flow\n * @param password\n */\nexport function addPassword(\n parameters: Map,\n password: string\n): void {\n parameters.set(PasswordGrantConstants.password, password);\n}\n\n/**\n * add pop_jwk to query params\n * @param cnfString\n */\nexport function addPopToken(\n parameters: Map,\n cnfString: string\n): void {\n if (cnfString) {\n parameters.set(AADServerParamKeys.TOKEN_TYPE, AuthenticationScheme.POP);\n parameters.set(AADServerParamKeys.REQ_CNF, cnfString);\n }\n}\n\n/**\n * add SSH JWK and key ID to query params\n */\nexport function addSshJwk(\n parameters: Map,\n sshJwkString: string\n): void {\n if (sshJwkString) {\n parameters.set(AADServerParamKeys.TOKEN_TYPE, AuthenticationScheme.SSH);\n parameters.set(AADServerParamKeys.REQ_CNF, sshJwkString);\n }\n}\n\n/**\n * add server telemetry fields\n * @param serverTelemetryManager\n */\nexport function addServerTelemetry(\n parameters: Map,\n serverTelemetryManager: ServerTelemetryManager\n): void {\n parameters.set(\n AADServerParamKeys.X_CLIENT_CURR_TELEM,\n serverTelemetryManager.generateCurrentRequestHeaderValue()\n );\n parameters.set(\n AADServerParamKeys.X_CLIENT_LAST_TELEM,\n serverTelemetryManager.generateLastRequestHeaderValue()\n );\n}\n\n/**\n * Adds parameter that indicates to the server that throttling is supported\n */\nexport function addThrottling(parameters: Map): void {\n parameters.set(\n AADServerParamKeys.X_MS_LIB_CAPABILITY,\n ThrottlingConstants.X_MS_LIB_CAPABILITY_VALUE\n );\n}\n\n/**\n * Adds logout_hint parameter for \"silent\" logout which prevent server account picker\n */\nexport function addLogoutHint(\n parameters: Map,\n logoutHint: string\n): void {\n parameters.set(AADServerParamKeys.LOGOUT_HINT, logoutHint);\n}\n\nexport function addBrokerParameters(\n parameters: Map,\n brokerClientId: string,\n brokerRedirectUri: string\n): void {\n if (!parameters.has(AADServerParamKeys.BROKER_CLIENT_ID)) {\n parameters.set(AADServerParamKeys.BROKER_CLIENT_ID, brokerClientId);\n }\n if (!parameters.has(AADServerParamKeys.BROKER_REDIRECT_URI)) {\n parameters.set(\n AADServerParamKeys.BROKER_REDIRECT_URI,\n brokerRedirectUri\n );\n }\n}\n\n/**\n * Add EAR (Encrypted Authorize Response) request parameters\n * @param parameters\n * @param jwk\n */\nexport function addEARParameters(\n parameters: Map,\n jwk: string\n): void {\n parameters.set(AADServerParamKeys.EAR_JWK, encodeURIComponent(jwk));\n\n // ear_jwe_crypto will always have value: {\"alg\":\"dir\",\"enc\":\"A256GCM\"} so we can hardcode this\n const jweCryptoB64Encoded = \"eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0\";\n parameters.set(AADServerParamKeys.EAR_JWE_CRYPTO, jweCryptoB64Encoded);\n}\n\n/**\n * Adds authorize body parameters to the request parameters\n * @param parameters\n * @param bodyParameters\n */\nexport function addPostBodyParameters(\n parameters: Map,\n bodyParameters: StringDict\n): void {\n Object.entries(bodyParameters).forEach(([key, value]) => {\n if (value) {\n parameters.set(key, value);\n }\n });\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Authority types supported by MSAL.\n */\nexport const AuthorityType = {\n Default: 0,\n Adfs: 1,\n Dsts: 2,\n Ciam: 3,\n} as const;\nexport type AuthorityType = (typeof AuthorityType)[keyof typeof AuthorityType];\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Tenant Discovery Response which contains the relevant OAuth endpoints and data needed for authentication and authorization.\n */\nexport type OpenIdConfigResponse = {\n authorization_endpoint: string;\n token_endpoint: string;\n end_session_endpoint?: string;\n issuer: string;\n jwks_uri: string;\n};\n\nexport function isOpenIdConfigResponse(response: object): boolean {\n return (\n response.hasOwnProperty(\"authorization_endpoint\") &&\n response.hasOwnProperty(\"token_endpoint\") &&\n response.hasOwnProperty(\"issuer\") &&\n response.hasOwnProperty(\"jwks_uri\")\n );\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { CloudDiscoveryMetadata } from \"./CloudDiscoveryMetadata.js\";\n\n/**\n * The OpenID Configuration Endpoint Response type. Used by the authority class to get relevant OAuth endpoints.\n */\nexport type CloudInstanceDiscoveryResponse = {\n tenant_discovery_endpoint: string;\n metadata: Array;\n};\n\nexport function isCloudInstanceDiscoveryResponse(response: object): boolean {\n return (\n response.hasOwnProperty(\"tenant_discovery_endpoint\") &&\n response.hasOwnProperty(\"metadata\")\n );\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * The OpenID Configuration Endpoint Response type. Used by the authority class to get relevant OAuth endpoints.\n */\nexport type CloudInstanceDiscoveryErrorResponse = {\n error: String;\n error_description: String;\n error_codes?: Array;\n timestamp?: String;\n trace_id?: String;\n correlation_id?: String;\n error_uri?: String;\n};\n\nexport function isCloudInstanceDiscoveryErrorResponse(\n response: object\n): boolean {\n return (\n response.hasOwnProperty(\"error\") &&\n response.hasOwnProperty(\"error_description\")\n );\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Logger } from \"../logger/Logger.js\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\n\n/**\n * Wraps a function with a performance measurement.\n * Usage: invoke(functionToCall, performanceClient, \"EventName\", \"correlationId\")(...argsToPassToFunction)\n * @param callback\n * @param eventName\n * @param logger\n * @param telemetryClient\n * @param correlationId\n * @returns\n * @internal\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const invoke = , U>(\n callback: (...args: T) => U,\n eventName: string,\n logger: Logger,\n telemetryClient?: IPerformanceClient,\n correlationId?: string\n) => {\n return (...args: T): U => {\n logger.trace(`Executing function ${eventName}`);\n const inProgressEvent = telemetryClient?.startMeasurement(\n eventName,\n correlationId\n );\n if (correlationId) {\n // Track number of times this API is called in a single request\n const eventCount = eventName + \"CallCount\";\n telemetryClient?.incrementFields(\n { [eventCount]: 1 },\n correlationId\n );\n }\n try {\n const result = callback(...args);\n inProgressEvent?.end({\n success: true,\n });\n logger.trace(`Returning result from ${eventName}`);\n return result;\n } catch (e) {\n logger.trace(`Error occurred in ${eventName}`);\n try {\n logger.trace(JSON.stringify(e));\n } catch (e) {\n logger.trace(\"Unable to print error message.\");\n }\n inProgressEvent?.end(\n {\n success: false,\n },\n e\n );\n throw e;\n }\n };\n};\n\n/**\n * Wraps an async function with a performance measurement.\n * Usage: invokeAsync(functionToCall, performanceClient, \"EventName\", \"correlationId\")(...argsToPassToFunction)\n * @param callback\n * @param eventName\n * @param logger\n * @param telemetryClient\n * @param correlationId\n * @returns\n * @internal\n *\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const invokeAsync = , U>(\n callback: (...args: T) => Promise,\n eventName: string,\n logger: Logger,\n telemetryClient?: IPerformanceClient,\n correlationId?: string\n) => {\n return (...args: T): Promise => {\n logger.trace(`Executing function ${eventName}`);\n const inProgressEvent = telemetryClient?.startMeasurement(\n eventName,\n correlationId\n );\n if (correlationId) {\n // Track number of times this API is called in a single request\n const eventCount = eventName + \"CallCount\";\n telemetryClient?.incrementFields(\n { [eventCount]: 1 },\n correlationId\n );\n }\n telemetryClient?.setPreQueueTime(eventName, correlationId);\n return callback(...args)\n .then((response) => {\n logger.trace(`Returning result from ${eventName}`);\n inProgressEvent?.end({\n success: true,\n });\n return response;\n })\n .catch((e) => {\n logger.trace(`Error occurred in ${eventName}`);\n try {\n logger.trace(JSON.stringify(e));\n } catch (e) {\n logger.trace(\"Unable to print error message.\");\n }\n inProgressEvent?.end(\n {\n success: false,\n },\n e\n );\n throw e;\n });\n };\n};\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { INetworkModule } from \"../network/INetworkModule.js\";\nimport { NetworkResponse } from \"../network/NetworkResponse.js\";\nimport { IMDSBadResponse } from \"../response/IMDSBadResponse.js\";\nimport {\n Constants,\n HttpStatus,\n RegionDiscoverySources,\n} from \"../utils/Constants.js\";\nimport { RegionDiscoveryMetadata } from \"./RegionDiscoveryMetadata.js\";\nimport { ImdsOptions } from \"./ImdsOptions.js\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\nimport { Logger } from \"../logger/Logger.js\";\n\nexport class RegionDiscovery {\n // Network interface to make requests with.\n protected networkInterface: INetworkModule;\n // Logger\n private logger: Logger;\n // Performance client\n protected performanceClient: IPerformanceClient | undefined;\n // CorrelationId\n protected correlationId: string | undefined;\n // Options for the IMDS endpoint request\n protected static IMDS_OPTIONS: ImdsOptions = {\n headers: {\n Metadata: \"true\",\n },\n };\n\n constructor(\n networkInterface: INetworkModule,\n logger: Logger,\n performanceClient?: IPerformanceClient,\n correlationId?: string\n ) {\n this.networkInterface = networkInterface;\n this.logger = logger;\n this.performanceClient = performanceClient;\n this.correlationId = correlationId;\n }\n\n /**\n * Detect the region from the application's environment.\n *\n * @returns Promise\n */\n public async detectRegion(\n environmentRegion: string | undefined,\n regionDiscoveryMetadata: RegionDiscoveryMetadata\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.RegionDiscoveryDetectRegion,\n this.correlationId\n );\n\n // Initialize auto detected region with the region from the envrionment\n let autodetectedRegionName = environmentRegion;\n\n // Check if a region was detected from the environment, if not, attempt to get the region from IMDS\n if (!autodetectedRegionName) {\n const options = RegionDiscovery.IMDS_OPTIONS;\n\n try {\n const localIMDSVersionResponse = await invokeAsync(\n this.getRegionFromIMDS.bind(this),\n PerformanceEvents.RegionDiscoveryGetRegionFromIMDS,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(Constants.IMDS_VERSION, options);\n if (localIMDSVersionResponse.status === HttpStatus.SUCCESS) {\n autodetectedRegionName = localIMDSVersionResponse.body;\n regionDiscoveryMetadata.region_source =\n RegionDiscoverySources.IMDS;\n }\n\n // If the response using the local IMDS version failed, try to fetch the current version of IMDS and retry.\n if (\n localIMDSVersionResponse.status === HttpStatus.BAD_REQUEST\n ) {\n const currentIMDSVersion = await invokeAsync(\n this.getCurrentVersion.bind(this),\n PerformanceEvents.RegionDiscoveryGetCurrentVersion,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(options);\n if (!currentIMDSVersion) {\n regionDiscoveryMetadata.region_source =\n RegionDiscoverySources.FAILED_AUTO_DETECTION;\n return null;\n }\n\n const currentIMDSVersionResponse = await invokeAsync(\n this.getRegionFromIMDS.bind(this),\n PerformanceEvents.RegionDiscoveryGetRegionFromIMDS,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(currentIMDSVersion, options);\n if (\n currentIMDSVersionResponse.status === HttpStatus.SUCCESS\n ) {\n autodetectedRegionName =\n currentIMDSVersionResponse.body;\n regionDiscoveryMetadata.region_source =\n RegionDiscoverySources.IMDS;\n }\n }\n } catch (e) {\n regionDiscoveryMetadata.region_source =\n RegionDiscoverySources.FAILED_AUTO_DETECTION;\n return null;\n }\n } else {\n regionDiscoveryMetadata.region_source =\n RegionDiscoverySources.ENVIRONMENT_VARIABLE;\n }\n\n // If no region was auto detected from the environment or from the IMDS endpoint, mark the attempt as a FAILED_AUTO_DETECTION\n if (!autodetectedRegionName) {\n regionDiscoveryMetadata.region_source =\n RegionDiscoverySources.FAILED_AUTO_DETECTION;\n }\n\n return autodetectedRegionName || null;\n }\n\n /**\n * Make the call to the IMDS endpoint\n *\n * @param imdsEndpointUrl\n * @returns Promise>\n */\n private async getRegionFromIMDS(\n version: string,\n options: ImdsOptions\n ): Promise> {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.RegionDiscoveryGetRegionFromIMDS,\n this.correlationId\n );\n return this.networkInterface.sendGetRequestAsync(\n `${Constants.IMDS_ENDPOINT}?api-version=${version}&format=text`,\n options,\n Constants.IMDS_TIMEOUT\n );\n }\n\n /**\n * Get the most recent version of the IMDS endpoint available\n *\n * @returns Promise\n */\n private async getCurrentVersion(\n options: ImdsOptions\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.RegionDiscoveryGetCurrentVersion,\n this.correlationId\n );\n try {\n const response =\n await this.networkInterface.sendGetRequestAsync(\n `${Constants.IMDS_ENDPOINT}?format=json`,\n options\n );\n\n // When IMDS endpoint is called without the api version query param, bad request response comes back with latest version.\n if (\n response.status === HttpStatus.BAD_REQUEST &&\n response.body &&\n response.body[\"newest-versions\"] &&\n response.body[\"newest-versions\"].length > 0\n ) {\n return response.body[\"newest-versions\"][0];\n }\n\n return null;\n } catch (e) {\n return null;\n }\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Utility functions for managing date and time operations.\n */\n\n/**\n * return the current time in Unix time (seconds).\n */\nexport function nowSeconds(): number {\n // Date.getTime() returns in milliseconds.\n return Math.round(new Date().getTime() / 1000.0);\n}\n\n/**\n * Converts JS Date object to seconds\n * @param date Date\n */\nexport function toSecondsFromDate(date: Date): number {\n // Convert date to seconds\n return date.getTime() / 1000;\n}\n\n/**\n * Convert seconds to JS Date object. Seconds can be in a number or string format or undefined (will still return a date).\n * @param seconds\n */\nexport function toDateFromSeconds(seconds: number | string | undefined): Date {\n if (seconds) {\n return new Date(Number(seconds) * 1000);\n }\n return new Date();\n}\n\n/**\n * check if a token is expired based on given UTC time in seconds.\n * @param expiresOn\n */\nexport function isTokenExpired(expiresOn: string, offset: number): boolean {\n // check for access token expiry\n const expirationSec = Number(expiresOn) || 0;\n const offsetCurrentTimeSec = nowSeconds() + offset;\n\n // If current time + offset is greater than token expiration time, then token is expired.\n return offsetCurrentTimeSec > expirationSec;\n}\n\n/**\n * Checks if a cache entry is expired based on the last updated time and cache retention days.\n * @param lastUpdatedAt\n * @param cacheRetentionDays\n * @returns\n */\nexport function isCacheExpired(\n lastUpdatedAt: string,\n cacheRetentionDays: number\n): boolean {\n const cacheExpirationTimestamp =\n Number(lastUpdatedAt) + cacheRetentionDays * 24 * 60 * 60 * 1000;\n return Date.now() > cacheExpirationTimestamp;\n}\n\n/**\n * If the current time is earlier than the time that a token was cached at, we must discard the token\n * i.e. The system clock was turned back after acquiring the cached token\n * @param cachedAt\n * @param offset\n */\nexport function wasClockTurnedBack(cachedAt: string): boolean {\n const cachedAtSec = Number(cachedAt);\n\n return cachedAtSec > nowSeconds();\n}\n\n/**\n * Waits for t number of milliseconds\n * @param t number\n * @param value T\n */\nexport function delay(t: number, value?: T): Promise {\n return new Promise((resolve) => setTimeout(() => resolve(value), t));\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { extractTokenClaims } from \"../../account/AuthToken.js\";\nimport { TokenClaims } from \"../../account/TokenClaims.js\";\nimport { CloudDiscoveryMetadata } from \"../../authority/CloudDiscoveryMetadata.js\";\nimport { OpenIdConfigResponse } from \"../../authority/OpenIdConfigResponse.js\";\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n} from \"../../error/ClientAuthError.js\";\nimport {\n APP_METADATA,\n AUTHORITY_METADATA_CONSTANTS,\n AuthenticationScheme,\n CredentialType,\n SERVER_TELEM_CONSTANTS,\n Separators,\n ThrottlingConstants,\n} from \"../../utils/Constants.js\";\nimport * as TimeUtils from \"../../utils/TimeUtils.js\";\nimport { AccessTokenEntity } from \"../entities/AccessTokenEntity.js\";\nimport { AppMetadataEntity } from \"../entities/AppMetadataEntity.js\";\nimport { AuthorityMetadataEntity } from \"../entities/AuthorityMetadataEntity.js\";\nimport { CredentialEntity } from \"../entities/CredentialEntity.js\";\nimport { IdTokenEntity } from \"../entities/IdTokenEntity.js\";\nimport { RefreshTokenEntity } from \"../entities/RefreshTokenEntity.js\";\n\n/**\n * Create IdTokenEntity\n * @param homeAccountId\n * @param authenticationResult\n * @param clientId\n * @param authority\n */\nexport function createIdTokenEntity(\n homeAccountId: string,\n environment: string,\n idToken: string,\n clientId: string,\n tenantId: string\n): IdTokenEntity {\n const idTokenEntity: IdTokenEntity = {\n credentialType: CredentialType.ID_TOKEN,\n homeAccountId: homeAccountId,\n environment: environment,\n clientId: clientId,\n secret: idToken,\n realm: tenantId,\n lastUpdatedAt: Date.now().toString(), // Set the last updated time to now\n };\n\n return idTokenEntity;\n}\n\n/**\n * Create AccessTokenEntity\n * @param homeAccountId\n * @param environment\n * @param accessToken\n * @param clientId\n * @param tenantId\n * @param scopes\n * @param expiresOn\n * @param extExpiresOn\n */\nexport function createAccessTokenEntity(\n homeAccountId: string,\n environment: string,\n accessToken: string,\n clientId: string,\n tenantId: string,\n scopes: string,\n expiresOn: number,\n extExpiresOn: number,\n base64Decode: (input: string) => string,\n refreshOn?: number,\n tokenType?: AuthenticationScheme,\n userAssertionHash?: string,\n keyId?: string,\n requestedClaims?: string,\n requestedClaimsHash?: string\n): AccessTokenEntity {\n const atEntity: AccessTokenEntity = {\n homeAccountId: homeAccountId,\n credentialType: CredentialType.ACCESS_TOKEN,\n secret: accessToken,\n cachedAt: TimeUtils.nowSeconds().toString(),\n expiresOn: expiresOn.toString(),\n extendedExpiresOn: extExpiresOn.toString(),\n environment: environment,\n clientId: clientId,\n realm: tenantId,\n target: scopes,\n tokenType: tokenType || AuthenticationScheme.BEARER,\n lastUpdatedAt: Date.now().toString(), // Set the last updated time to now\n };\n\n if (userAssertionHash) {\n atEntity.userAssertionHash = userAssertionHash;\n }\n\n if (refreshOn) {\n atEntity.refreshOn = refreshOn.toString();\n }\n\n if (requestedClaims) {\n atEntity.requestedClaims = requestedClaims;\n atEntity.requestedClaimsHash = requestedClaimsHash;\n }\n\n /*\n * Create Access Token With Auth Scheme instead of regular access token\n * Cast to lower to handle \"bearer\" from ADFS\n */\n if (\n atEntity.tokenType?.toLowerCase() !==\n AuthenticationScheme.BEARER.toLowerCase()\n ) {\n atEntity.credentialType = CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME;\n switch (atEntity.tokenType) {\n case AuthenticationScheme.POP:\n // Make sure keyId is present and add it to credential\n const tokenClaims: TokenClaims | null = extractTokenClaims(\n accessToken,\n base64Decode\n );\n if (!tokenClaims?.cnf?.kid) {\n throw createClientAuthError(\n ClientAuthErrorCodes.tokenClaimsCnfRequiredForSignedJwt\n );\n }\n atEntity.keyId = tokenClaims.cnf.kid;\n break;\n case AuthenticationScheme.SSH:\n atEntity.keyId = keyId;\n }\n }\n\n return atEntity;\n}\n\n/**\n * Create RefreshTokenEntity\n * @param homeAccountId\n * @param authenticationResult\n * @param clientId\n * @param authority\n */\nexport function createRefreshTokenEntity(\n homeAccountId: string,\n environment: string,\n refreshToken: string,\n clientId: string,\n familyId?: string,\n userAssertionHash?: string,\n expiresOn?: number\n): RefreshTokenEntity {\n const rtEntity: RefreshTokenEntity = {\n credentialType: CredentialType.REFRESH_TOKEN,\n homeAccountId: homeAccountId,\n environment: environment,\n clientId: clientId,\n secret: refreshToken,\n lastUpdatedAt: Date.now().toString(),\n };\n\n if (userAssertionHash) {\n rtEntity.userAssertionHash = userAssertionHash;\n }\n\n if (familyId) {\n rtEntity.familyId = familyId;\n }\n\n if (expiresOn) {\n rtEntity.expiresOn = expiresOn.toString();\n }\n\n return rtEntity;\n}\n\nexport function isCredentialEntity(entity: object): entity is CredentialEntity {\n return (\n entity.hasOwnProperty(\"homeAccountId\") &&\n entity.hasOwnProperty(\"environment\") &&\n entity.hasOwnProperty(\"credentialType\") &&\n entity.hasOwnProperty(\"clientId\") &&\n entity.hasOwnProperty(\"secret\")\n );\n}\n\n/**\n * Validates an entity: checks for all expected params\n * @param entity\n */\nexport function isAccessTokenEntity(\n entity: object\n): entity is AccessTokenEntity {\n if (!entity) {\n return false;\n }\n\n return (\n isCredentialEntity(entity) &&\n entity.hasOwnProperty(\"realm\") &&\n entity.hasOwnProperty(\"target\") &&\n (entity[\"credentialType\"] === CredentialType.ACCESS_TOKEN ||\n entity[\"credentialType\"] ===\n CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME)\n );\n}\n\n/**\n * Validates an entity: checks for all expected params\n * @param entity\n */\nexport function isIdTokenEntity(entity: object): entity is IdTokenEntity {\n if (!entity) {\n return false;\n }\n\n return (\n isCredentialEntity(entity) &&\n entity.hasOwnProperty(\"realm\") &&\n entity[\"credentialType\"] === CredentialType.ID_TOKEN\n );\n}\n\n/**\n * Validates an entity: checks for all expected params\n * @param entity\n */\nexport function isRefreshTokenEntity(\n entity: object\n): entity is RefreshTokenEntity {\n if (!entity) {\n return false;\n }\n\n return (\n isCredentialEntity(entity) &&\n entity[\"credentialType\"] === CredentialType.REFRESH_TOKEN\n );\n}\n\n/**\n * validates if a given cache entry is \"Telemetry\", parses \n * @param key\n * @param entity\n */\nexport function isServerTelemetryEntity(key: string, entity?: object): boolean {\n const validateKey: boolean =\n key.indexOf(SERVER_TELEM_CONSTANTS.CACHE_KEY) === 0;\n let validateEntity: boolean = true;\n\n if (entity) {\n validateEntity =\n entity.hasOwnProperty(\"failedRequests\") &&\n entity.hasOwnProperty(\"errors\") &&\n entity.hasOwnProperty(\"cacheHits\");\n }\n\n return validateKey && validateEntity;\n}\n\n/**\n * validates if a given cache entry is \"Throttling\", parses \n * @param key\n * @param entity\n */\nexport function isThrottlingEntity(key: string, entity?: object): boolean {\n let validateKey: boolean = false;\n if (key) {\n validateKey = key.indexOf(ThrottlingConstants.THROTTLING_PREFIX) === 0;\n }\n\n let validateEntity: boolean = true;\n if (entity) {\n validateEntity = entity.hasOwnProperty(\"throttleTime\");\n }\n\n return validateKey && validateEntity;\n}\n\n/**\n * Generate AppMetadata Cache Key as per the schema: appmetadata--\n */\nexport function generateAppMetadataKey({\n environment,\n clientId,\n}: AppMetadataEntity): string {\n const appMetaDataKeyArray: Array = [\n APP_METADATA,\n environment,\n clientId,\n ];\n return appMetaDataKeyArray\n .join(Separators.CACHE_KEY_SEPARATOR)\n .toLowerCase();\n}\n\n/*\n * Validates an entity: checks for all expected params\n * @param entity\n */\nexport function isAppMetadataEntity(key: string, entity: object): boolean {\n if (!entity) {\n return false;\n }\n\n return (\n key.indexOf(APP_METADATA) === 0 &&\n entity.hasOwnProperty(\"clientId\") &&\n entity.hasOwnProperty(\"environment\")\n );\n}\n\n/**\n * Validates an entity: checks for all expected params\n * @param entity\n */\nexport function isAuthorityMetadataEntity(\n key: string,\n entity: object\n): boolean {\n if (!entity) {\n return false;\n }\n\n return (\n key.indexOf(AUTHORITY_METADATA_CONSTANTS.CACHE_KEY) === 0 &&\n entity.hasOwnProperty(\"aliases\") &&\n entity.hasOwnProperty(\"preferred_cache\") &&\n entity.hasOwnProperty(\"preferred_network\") &&\n entity.hasOwnProperty(\"canonical_authority\") &&\n entity.hasOwnProperty(\"authorization_endpoint\") &&\n entity.hasOwnProperty(\"token_endpoint\") &&\n entity.hasOwnProperty(\"issuer\") &&\n entity.hasOwnProperty(\"aliasesFromNetwork\") &&\n entity.hasOwnProperty(\"endpointsFromNetwork\") &&\n entity.hasOwnProperty(\"expiresAt\") &&\n entity.hasOwnProperty(\"jwks_uri\")\n );\n}\n\n/**\n * Reset the exiresAt value\n */\nexport function generateAuthorityMetadataExpiresAt(): number {\n return (\n TimeUtils.nowSeconds() +\n AUTHORITY_METADATA_CONSTANTS.REFRESH_TIME_SECONDS\n );\n}\n\nexport function updateAuthorityEndpointMetadata(\n authorityMetadata: AuthorityMetadataEntity,\n updatedValues: OpenIdConfigResponse,\n fromNetwork: boolean\n): void {\n authorityMetadata.authorization_endpoint =\n updatedValues.authorization_endpoint;\n authorityMetadata.token_endpoint = updatedValues.token_endpoint;\n authorityMetadata.end_session_endpoint = updatedValues.end_session_endpoint;\n authorityMetadata.issuer = updatedValues.issuer;\n authorityMetadata.endpointsFromNetwork = fromNetwork;\n authorityMetadata.jwks_uri = updatedValues.jwks_uri;\n}\n\nexport function updateCloudDiscoveryMetadata(\n authorityMetadata: AuthorityMetadataEntity,\n updatedValues: CloudDiscoveryMetadata,\n fromNetwork: boolean\n): void {\n authorityMetadata.aliases = updatedValues.aliases;\n authorityMetadata.preferred_cache = updatedValues.preferred_cache;\n authorityMetadata.preferred_network = updatedValues.preferred_network;\n authorityMetadata.aliasesFromNetwork = fromNetwork;\n}\n\n/**\n * Returns whether or not the data needs to be refreshed\n */\nexport function isAuthorityMetadataExpired(\n metadata: AuthorityMetadataEntity\n): boolean {\n return metadata.expiresAt <= TimeUtils.nowSeconds();\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthorityType } from \"./AuthorityType.js\";\nimport {\n isOpenIdConfigResponse,\n OpenIdConfigResponse,\n} from \"./OpenIdConfigResponse.js\";\nimport { UrlString } from \"../url/UrlString.js\";\nimport { IUri } from \"../url/IUri.js\";\nimport {\n createClientAuthError,\n ClientAuthErrorCodes,\n} from \"../error/ClientAuthError.js\";\nimport { INetworkModule } from \"../network/INetworkModule.js\";\nimport {\n AADAuthorityConstants,\n AuthorityMetadataSource,\n Constants,\n RegionDiscoveryOutcomes,\n} from \"../utils/Constants.js\";\nimport {\n EndpointMetadata,\n getCloudDiscoveryMetadataFromHardcodedValues,\n getCloudDiscoveryMetadataFromNetworkResponse,\n InstanceDiscoveryMetadataAliases,\n} from \"./AuthorityMetadata.js\";\nimport {\n createClientConfigurationError,\n ClientConfigurationErrorCodes,\n} from \"../error/ClientConfigurationError.js\";\nimport { ProtocolMode } from \"./ProtocolMode.js\";\nimport { ICacheManager } from \"../cache/interface/ICacheManager.js\";\nimport { AuthorityMetadataEntity } from \"../cache/entities/AuthorityMetadataEntity.js\";\nimport {\n AuthorityOptions,\n AzureCloudInstance,\n StaticAuthorityOptions,\n} from \"./AuthorityOptions.js\";\nimport {\n CloudInstanceDiscoveryResponse,\n isCloudInstanceDiscoveryResponse,\n} from \"./CloudInstanceDiscoveryResponse.js\";\nimport {\n CloudInstanceDiscoveryErrorResponse,\n isCloudInstanceDiscoveryErrorResponse,\n} from \"./CloudInstanceDiscoveryErrorResponse.js\";\nimport { CloudDiscoveryMetadata } from \"./CloudDiscoveryMetadata.js\";\nimport { RegionDiscovery } from \"./RegionDiscovery.js\";\nimport { RegionDiscoveryMetadata } from \"./RegionDiscoveryMetadata.js\";\nimport { ImdsOptions } from \"./ImdsOptions.js\";\nimport type { AzureCloudOptions } from \"../config/ClientConfiguration.js\";\nimport { Logger } from \"../logger/Logger.js\";\nimport { AuthError } from \"../error/AuthError.js\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\nimport * as CacheHelpers from \"../cache/utils/CacheHelpers.js\";\n\n/**\n * The authority class validates the authority URIs used by the user, and retrieves the OpenID Configuration Data from the\n * endpoint. It will store the pertinent config data in this object for use during token calls.\n * @internal\n */\nexport class Authority {\n // Canonical authority url string\n private _canonicalAuthority: UrlString;\n // Canonicaly authority url components\n private _canonicalAuthorityUrlComponents: IUri | null;\n // Network interface to make requests with.\n protected networkInterface: INetworkModule;\n // Cache Manager to cache network responses\n protected cacheManager: ICacheManager;\n // Protocol mode to construct endpoints\n private authorityOptions: AuthorityOptions;\n // Authority metadata\n private metadata: AuthorityMetadataEntity;\n // Region discovery service\n private regionDiscovery: RegionDiscovery;\n // Region discovery metadata\n public regionDiscoveryMetadata: RegionDiscoveryMetadata;\n // Logger object\n private logger: Logger;\n // Performance client\n protected performanceClient: IPerformanceClient | undefined;\n // Correlation Id\n protected correlationId: string;\n // Indicates if the authority is fake, for the purpose of a Managed Identity Application\n private managedIdentity: boolean;\n // Reserved tenant domain names that will not be replaced with tenant id\n private static reservedTenantDomains: Set = new Set([\n \"{tenant}\",\n \"{tenantid}\",\n AADAuthorityConstants.COMMON,\n AADAuthorityConstants.CONSUMERS,\n AADAuthorityConstants.ORGANIZATIONS,\n ]);\n\n constructor(\n authority: string,\n networkInterface: INetworkModule,\n cacheManager: ICacheManager,\n authorityOptions: AuthorityOptions,\n logger: Logger,\n correlationId: string,\n performanceClient?: IPerformanceClient,\n managedIdentity?: boolean\n ) {\n this.canonicalAuthority = authority;\n this._canonicalAuthority.validateAsUri();\n this.networkInterface = networkInterface;\n this.cacheManager = cacheManager;\n this.authorityOptions = authorityOptions;\n this.regionDiscoveryMetadata = {\n region_used: undefined,\n region_source: undefined,\n region_outcome: undefined,\n };\n this.logger = logger;\n this.performanceClient = performanceClient;\n this.correlationId = correlationId;\n this.managedIdentity = managedIdentity || false;\n this.regionDiscovery = new RegionDiscovery(\n networkInterface,\n this.logger,\n this.performanceClient,\n this.correlationId\n );\n }\n\n /**\n * Get {@link AuthorityType}\n * @param authorityUri {@link IUri}\n * @private\n */\n private getAuthorityType(authorityUri: IUri): AuthorityType {\n // CIAM auth url pattern is being standardized as: .ciamlogin.com\n if (authorityUri.HostNameAndPort.endsWith(Constants.CIAM_AUTH_URL)) {\n return AuthorityType.Ciam;\n }\n\n const pathSegments = authorityUri.PathSegments;\n if (pathSegments.length) {\n switch (pathSegments[0].toLowerCase()) {\n case Constants.ADFS:\n return AuthorityType.Adfs;\n case Constants.DSTS:\n return AuthorityType.Dsts;\n default:\n break;\n }\n }\n return AuthorityType.Default;\n }\n\n // See above for AuthorityType\n public get authorityType(): AuthorityType {\n return this.getAuthorityType(this.canonicalAuthorityUrlComponents);\n }\n\n /**\n * ProtocolMode enum representing the way endpoints are constructed.\n */\n public get protocolMode(): ProtocolMode {\n return this.authorityOptions.protocolMode;\n }\n\n /**\n * Returns authorityOptions which can be used to reinstantiate a new authority instance\n */\n public get options(): AuthorityOptions {\n return this.authorityOptions;\n }\n\n /**\n * A URL that is the authority set by the developer\n */\n public get canonicalAuthority(): string {\n return this._canonicalAuthority.urlString;\n }\n\n /**\n * Sets canonical authority.\n */\n public set canonicalAuthority(url: string) {\n this._canonicalAuthority = new UrlString(url);\n this._canonicalAuthority.validateAsUri();\n this._canonicalAuthorityUrlComponents = null;\n }\n\n /**\n * Get authority components.\n */\n public get canonicalAuthorityUrlComponents(): IUri {\n if (!this._canonicalAuthorityUrlComponents) {\n this._canonicalAuthorityUrlComponents =\n this._canonicalAuthority.getUrlComponents();\n }\n\n return this._canonicalAuthorityUrlComponents;\n }\n\n /**\n * Get hostname and port i.e. login.microsoftonline.com\n */\n public get hostnameAndPort(): string {\n return this.canonicalAuthorityUrlComponents.HostNameAndPort.toLowerCase();\n }\n\n /**\n * Get tenant for authority.\n */\n public get tenant(): string {\n return this.canonicalAuthorityUrlComponents.PathSegments[0];\n }\n\n /**\n * OAuth /authorize endpoint for requests\n */\n public get authorizationEndpoint(): string {\n if (this.discoveryComplete()) {\n return this.replacePath(this.metadata.authorization_endpoint);\n } else {\n throw createClientAuthError(\n ClientAuthErrorCodes.endpointResolutionError\n );\n }\n }\n\n /**\n * OAuth /token endpoint for requests\n */\n public get tokenEndpoint(): string {\n if (this.discoveryComplete()) {\n return this.replacePath(this.metadata.token_endpoint);\n } else {\n throw createClientAuthError(\n ClientAuthErrorCodes.endpointResolutionError\n );\n }\n }\n\n public get deviceCodeEndpoint(): string {\n if (this.discoveryComplete()) {\n return this.replacePath(\n this.metadata.token_endpoint.replace(\"/token\", \"/devicecode\")\n );\n } else {\n throw createClientAuthError(\n ClientAuthErrorCodes.endpointResolutionError\n );\n }\n }\n\n /**\n * OAuth logout endpoint for requests\n */\n public get endSessionEndpoint(): string {\n if (this.discoveryComplete()) {\n // ROPC policies may not have end_session_endpoint set\n if (!this.metadata.end_session_endpoint) {\n throw createClientAuthError(\n ClientAuthErrorCodes.endSessionEndpointNotSupported\n );\n }\n return this.replacePath(this.metadata.end_session_endpoint);\n } else {\n throw createClientAuthError(\n ClientAuthErrorCodes.endpointResolutionError\n );\n }\n }\n\n /**\n * OAuth issuer for requests\n */\n public get selfSignedJwtAudience(): string {\n if (this.discoveryComplete()) {\n return this.replacePath(this.metadata.issuer);\n } else {\n throw createClientAuthError(\n ClientAuthErrorCodes.endpointResolutionError\n );\n }\n }\n\n /**\n * Jwks_uri for token signing keys\n */\n public get jwksUri(): string {\n if (this.discoveryComplete()) {\n return this.replacePath(this.metadata.jwks_uri);\n } else {\n throw createClientAuthError(\n ClientAuthErrorCodes.endpointResolutionError\n );\n }\n }\n\n /**\n * Returns a flag indicating that tenant name can be replaced in authority {@link IUri}\n * @param authorityUri {@link IUri}\n * @private\n */\n private canReplaceTenant(authorityUri: IUri): boolean {\n return (\n authorityUri.PathSegments.length === 1 &&\n !Authority.reservedTenantDomains.has(\n authorityUri.PathSegments[0]\n ) &&\n this.getAuthorityType(authorityUri) === AuthorityType.Default &&\n this.protocolMode !== ProtocolMode.OIDC\n );\n }\n\n /**\n * Replaces tenant in url path with current tenant. Defaults to common.\n * @param urlString\n */\n private replaceTenant(urlString: string): string {\n return urlString.replace(/{tenant}|{tenantid}/g, this.tenant);\n }\n\n /**\n * Replaces path such as tenant or policy with the current tenant or policy.\n * @param urlString\n */\n private replacePath(urlString: string): string {\n let endpoint = urlString;\n const cachedAuthorityUrl = new UrlString(\n this.metadata.canonical_authority\n );\n const cachedAuthorityUrlComponents =\n cachedAuthorityUrl.getUrlComponents();\n const cachedAuthorityParts = cachedAuthorityUrlComponents.PathSegments;\n const currentAuthorityParts =\n this.canonicalAuthorityUrlComponents.PathSegments;\n\n currentAuthorityParts.forEach((currentPart, index) => {\n let cachedPart = cachedAuthorityParts[index];\n if (\n index === 0 &&\n this.canReplaceTenant(cachedAuthorityUrlComponents)\n ) {\n const tenantId = new UrlString(\n this.metadata.authorization_endpoint\n ).getUrlComponents().PathSegments[0];\n /**\n * Check if AAD canonical authority contains tenant domain name, for example \"testdomain.onmicrosoft.com\",\n * by comparing its first path segment to the corresponding authorization endpoint path segment, which is\n * always resolved with tenant id by OIDC.\n */\n if (cachedPart !== tenantId) {\n this.logger.verbose(\n `Replacing tenant domain name ${cachedPart} with id ${tenantId}`\n );\n cachedPart = tenantId;\n }\n }\n if (currentPart !== cachedPart) {\n endpoint = endpoint.replace(\n `/${cachedPart}/`,\n `/${currentPart}/`\n );\n }\n });\n\n return this.replaceTenant(endpoint);\n }\n\n /**\n * The default open id configuration endpoint for any canonical authority.\n */\n protected get defaultOpenIdConfigurationEndpoint(): string {\n const canonicalAuthorityHost = this.hostnameAndPort;\n if (\n this.canonicalAuthority.endsWith(\"v2.0/\") ||\n this.authorityType === AuthorityType.Adfs ||\n (this.protocolMode === ProtocolMode.OIDC &&\n !this.isAliasOfKnownMicrosoftAuthority(canonicalAuthorityHost))\n ) {\n return `${this.canonicalAuthority}.well-known/openid-configuration`;\n }\n return `${this.canonicalAuthority}v2.0/.well-known/openid-configuration`;\n }\n\n /**\n * Boolean that returns whether or not tenant discovery has been completed.\n */\n discoveryComplete(): boolean {\n return !!this.metadata;\n }\n\n /**\n * Perform endpoint discovery to discover aliases, preferred_cache, preferred_network\n * and the /authorize, /token and logout endpoints.\n */\n public async resolveEndpointsAsync(): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthorityResolveEndpointsAsync,\n this.correlationId\n );\n\n const metadataEntity = this.getCurrentMetadataEntity();\n\n const cloudDiscoverySource = await invokeAsync(\n this.updateCloudDiscoveryMetadata.bind(this),\n PerformanceEvents.AuthorityUpdateCloudDiscoveryMetadata,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(metadataEntity);\n this.canonicalAuthority = this.canonicalAuthority.replace(\n this.hostnameAndPort,\n metadataEntity.preferred_network\n );\n const endpointSource = await invokeAsync(\n this.updateEndpointMetadata.bind(this),\n PerformanceEvents.AuthorityUpdateEndpointMetadata,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(metadataEntity);\n this.updateCachedMetadata(metadataEntity, cloudDiscoverySource, {\n source: endpointSource,\n });\n this.performanceClient?.addFields(\n {\n cloudDiscoverySource: cloudDiscoverySource,\n authorityEndpointSource: endpointSource,\n },\n this.correlationId\n );\n }\n\n /**\n * Returns metadata entity from cache if it exists, otherwiser returns a new metadata entity built\n * from the configured canonical authority\n * @returns\n */\n private getCurrentMetadataEntity(): AuthorityMetadataEntity {\n let metadataEntity: AuthorityMetadataEntity | null =\n this.cacheManager.getAuthorityMetadataByAlias(this.hostnameAndPort);\n\n if (!metadataEntity) {\n metadataEntity = {\n aliases: [],\n preferred_cache: this.hostnameAndPort,\n preferred_network: this.hostnameAndPort,\n canonical_authority: this.canonicalAuthority,\n authorization_endpoint: \"\",\n token_endpoint: \"\",\n end_session_endpoint: \"\",\n issuer: \"\",\n aliasesFromNetwork: false,\n endpointsFromNetwork: false,\n expiresAt: CacheHelpers.generateAuthorityMetadataExpiresAt(),\n jwks_uri: \"\",\n };\n }\n return metadataEntity;\n }\n\n /**\n * Updates cached metadata based on metadata source and sets the instance's metadata\n * property to the same value\n * @param metadataEntity\n * @param cloudDiscoverySource\n * @param endpointMetadataResult\n */\n private updateCachedMetadata(\n metadataEntity: AuthorityMetadataEntity,\n cloudDiscoverySource: AuthorityMetadataSource | null,\n endpointMetadataResult: {\n source: AuthorityMetadataSource;\n metadata?: OpenIdConfigResponse;\n } | null\n ): void {\n if (\n cloudDiscoverySource !== AuthorityMetadataSource.CACHE &&\n endpointMetadataResult?.source !== AuthorityMetadataSource.CACHE\n ) {\n // Reset the expiration time unless both values came from a successful cache lookup\n metadataEntity.expiresAt =\n CacheHelpers.generateAuthorityMetadataExpiresAt();\n metadataEntity.canonical_authority = this.canonicalAuthority;\n }\n\n const cacheKey = this.cacheManager.generateAuthorityMetadataCacheKey(\n metadataEntity.preferred_cache\n );\n this.cacheManager.setAuthorityMetadata(cacheKey, metadataEntity);\n this.metadata = metadataEntity;\n }\n\n /**\n * Update AuthorityMetadataEntity with new endpoints and return where the information came from\n * @param metadataEntity\n */\n private async updateEndpointMetadata(\n metadataEntity: AuthorityMetadataEntity\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthorityUpdateEndpointMetadata,\n this.correlationId\n );\n\n const localMetadata =\n this.updateEndpointMetadataFromLocalSources(metadataEntity);\n\n // Further update may be required for hardcoded metadata if regional metadata is preferred\n if (localMetadata) {\n if (\n localMetadata.source ===\n AuthorityMetadataSource.HARDCODED_VALUES\n ) {\n // If the user prefers to use an azure region replace the global endpoints with regional information.\n if (\n this.authorityOptions.azureRegionConfiguration?.azureRegion\n ) {\n if (localMetadata.metadata) {\n const hardcodedMetadata = await invokeAsync(\n this.updateMetadataWithRegionalInformation.bind(\n this\n ),\n PerformanceEvents.AuthorityUpdateMetadataWithRegionalInformation,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(localMetadata.metadata);\n CacheHelpers.updateAuthorityEndpointMetadata(\n metadataEntity,\n hardcodedMetadata,\n false\n );\n metadataEntity.canonical_authority =\n this.canonicalAuthority;\n }\n }\n }\n return localMetadata.source;\n }\n\n // Get metadata from network if local sources aren't available\n let metadata = await invokeAsync(\n this.getEndpointMetadataFromNetwork.bind(this),\n PerformanceEvents.AuthorityGetEndpointMetadataFromNetwork,\n this.logger,\n this.performanceClient,\n this.correlationId\n )();\n if (metadata) {\n // If the user prefers to use an azure region replace the global endpoints with regional information.\n if (this.authorityOptions.azureRegionConfiguration?.azureRegion) {\n metadata = await invokeAsync(\n this.updateMetadataWithRegionalInformation.bind(this),\n PerformanceEvents.AuthorityUpdateMetadataWithRegionalInformation,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(metadata);\n }\n\n CacheHelpers.updateAuthorityEndpointMetadata(\n metadataEntity,\n metadata,\n true\n );\n return AuthorityMetadataSource.NETWORK;\n } else {\n // Metadata could not be obtained from the config, cache, network or hardcoded values\n throw createClientAuthError(\n ClientAuthErrorCodes.openIdConfigError,\n this.defaultOpenIdConfigurationEndpoint\n );\n }\n }\n\n /**\n * Updates endpoint metadata from local sources and returns where the information was retrieved from and the metadata config\n * response if the source is hardcoded metadata\n * @param metadataEntity\n * @returns\n */\n private updateEndpointMetadataFromLocalSources(\n metadataEntity: AuthorityMetadataEntity\n ): {\n source: AuthorityMetadataSource;\n metadata?: OpenIdConfigResponse;\n } | null {\n this.logger.verbose(\n \"Attempting to get endpoint metadata from authority configuration\"\n );\n const configMetadata = this.getEndpointMetadataFromConfig();\n if (configMetadata) {\n this.logger.verbose(\n \"Found endpoint metadata in authority configuration\"\n );\n CacheHelpers.updateAuthorityEndpointMetadata(\n metadataEntity,\n configMetadata,\n false\n );\n return {\n source: AuthorityMetadataSource.CONFIG,\n };\n }\n\n this.logger.verbose(\n \"Did not find endpoint metadata in the config... Attempting to get endpoint metadata from the hardcoded values.\"\n );\n\n // skipAuthorityMetadataCache is used to bypass hardcoded authority metadata and force a network metadata cache lookup and network metadata request if no cached response is available.\n if (this.authorityOptions.skipAuthorityMetadataCache) {\n this.logger.verbose(\n \"Skipping hardcoded metadata cache since skipAuthorityMetadataCache is set to true. Attempting to get endpoint metadata from the network metadata cache.\"\n );\n } else {\n const hardcodedMetadata =\n this.getEndpointMetadataFromHardcodedValues();\n if (hardcodedMetadata) {\n CacheHelpers.updateAuthorityEndpointMetadata(\n metadataEntity,\n hardcodedMetadata,\n false\n );\n return {\n source: AuthorityMetadataSource.HARDCODED_VALUES,\n metadata: hardcodedMetadata,\n };\n } else {\n this.logger.verbose(\n \"Did not find endpoint metadata in hardcoded values... Attempting to get endpoint metadata from the network metadata cache.\"\n );\n }\n }\n\n // Check cached metadata entity expiration status\n const metadataEntityExpired =\n CacheHelpers.isAuthorityMetadataExpired(metadataEntity);\n if (\n this.isAuthoritySameType(metadataEntity) &&\n metadataEntity.endpointsFromNetwork &&\n !metadataEntityExpired\n ) {\n // No need to update\n this.logger.verbose(\"Found endpoint metadata in the cache.\");\n return { source: AuthorityMetadataSource.CACHE };\n } else if (metadataEntityExpired) {\n this.logger.verbose(\"The metadata entity is expired.\");\n }\n\n return null;\n }\n\n /**\n * Compares the number of url components after the domain to determine if the cached\n * authority metadata can be used for the requested authority. Protects against same domain different\n * authority such as login.microsoftonline.com/tenant and login.microsoftonline.com/tfp/tenant/policy\n * @param metadataEntity\n */\n private isAuthoritySameType(\n metadataEntity: AuthorityMetadataEntity\n ): boolean {\n const cachedAuthorityUrl = new UrlString(\n metadataEntity.canonical_authority\n );\n const cachedParts = cachedAuthorityUrl.getUrlComponents().PathSegments;\n\n return (\n cachedParts.length ===\n this.canonicalAuthorityUrlComponents.PathSegments.length\n );\n }\n\n /**\n * Parse authorityMetadata config option\n */\n private getEndpointMetadataFromConfig(): OpenIdConfigResponse | null {\n if (this.authorityOptions.authorityMetadata) {\n try {\n return JSON.parse(\n this.authorityOptions.authorityMetadata\n ) as OpenIdConfigResponse;\n } catch (e) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.invalidAuthorityMetadata\n );\n }\n }\n\n return null;\n }\n\n /**\n * Gets OAuth endpoints from the given OpenID configuration endpoint.\n *\n * @param hasHardcodedMetadata boolean\n */\n private async getEndpointMetadataFromNetwork(): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthorityGetEndpointMetadataFromNetwork,\n this.correlationId\n );\n\n const options: ImdsOptions = {};\n\n /*\n * TODO: Add a timeout if the authority exists in our library's\n * hardcoded list of metadata\n */\n\n const openIdConfigurationEndpoint =\n this.defaultOpenIdConfigurationEndpoint;\n this.logger.verbose(\n `Authority.getEndpointMetadataFromNetwork: attempting to retrieve OAuth endpoints from ${openIdConfigurationEndpoint}`\n );\n\n try {\n const response =\n await this.networkInterface.sendGetRequestAsync(\n openIdConfigurationEndpoint,\n options\n );\n const isValidResponse = isOpenIdConfigResponse(response.body);\n if (isValidResponse) {\n return response.body;\n } else {\n this.logger.verbose(\n `Authority.getEndpointMetadataFromNetwork: could not parse response as OpenID configuration`\n );\n return null;\n }\n } catch (e) {\n this.logger.verbose(\n `Authority.getEndpointMetadataFromNetwork: ${e}`\n );\n return null;\n }\n }\n\n /**\n * Get OAuth endpoints for common authorities.\n */\n private getEndpointMetadataFromHardcodedValues(): OpenIdConfigResponse | null {\n if (this.hostnameAndPort in EndpointMetadata) {\n return EndpointMetadata[this.hostnameAndPort];\n }\n\n return null;\n }\n\n /**\n * Update the retrieved metadata with regional information.\n * User selected Azure region will be used if configured.\n */\n private async updateMetadataWithRegionalInformation(\n metadata: OpenIdConfigResponse\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthorityUpdateMetadataWithRegionalInformation,\n this.correlationId\n );\n\n const userConfiguredAzureRegion =\n this.authorityOptions.azureRegionConfiguration?.azureRegion;\n\n if (userConfiguredAzureRegion) {\n if (\n userConfiguredAzureRegion !==\n Constants.AZURE_REGION_AUTO_DISCOVER_FLAG\n ) {\n this.regionDiscoveryMetadata.region_outcome =\n RegionDiscoveryOutcomes.CONFIGURED_NO_AUTO_DETECTION;\n this.regionDiscoveryMetadata.region_used =\n userConfiguredAzureRegion;\n return Authority.replaceWithRegionalInformation(\n metadata,\n userConfiguredAzureRegion\n );\n }\n\n const autodetectedRegionName = await invokeAsync(\n this.regionDiscovery.detectRegion.bind(this.regionDiscovery),\n PerformanceEvents.RegionDiscoveryDetectRegion,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(\n this.authorityOptions.azureRegionConfiguration\n ?.environmentRegion,\n this.regionDiscoveryMetadata\n );\n\n if (autodetectedRegionName) {\n this.regionDiscoveryMetadata.region_outcome =\n RegionDiscoveryOutcomes.AUTO_DETECTION_REQUESTED_SUCCESSFUL;\n this.regionDiscoveryMetadata.region_used =\n autodetectedRegionName;\n return Authority.replaceWithRegionalInformation(\n metadata,\n autodetectedRegionName\n );\n }\n\n this.regionDiscoveryMetadata.region_outcome =\n RegionDiscoveryOutcomes.AUTO_DETECTION_REQUESTED_FAILED;\n }\n\n return metadata;\n }\n\n /**\n * Updates the AuthorityMetadataEntity with new aliases, preferred_network and preferred_cache\n * and returns where the information was retrieved from\n * @param metadataEntity\n * @returns AuthorityMetadataSource\n */\n private async updateCloudDiscoveryMetadata(\n metadataEntity: AuthorityMetadataEntity\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthorityUpdateCloudDiscoveryMetadata,\n this.correlationId\n );\n const localMetadataSource =\n this.updateCloudDiscoveryMetadataFromLocalSources(metadataEntity);\n if (localMetadataSource) {\n return localMetadataSource;\n }\n\n // Fallback to network as metadata source\n const metadata = await invokeAsync(\n this.getCloudDiscoveryMetadataFromNetwork.bind(this),\n PerformanceEvents.AuthorityGetCloudDiscoveryMetadataFromNetwork,\n this.logger,\n this.performanceClient,\n this.correlationId\n )();\n\n if (metadata) {\n CacheHelpers.updateCloudDiscoveryMetadata(\n metadataEntity,\n metadata,\n true\n );\n return AuthorityMetadataSource.NETWORK;\n }\n\n // Metadata could not be obtained from the config, cache, network or hardcoded values\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.untrustedAuthority\n );\n }\n\n private updateCloudDiscoveryMetadataFromLocalSources(\n metadataEntity: AuthorityMetadataEntity\n ): AuthorityMetadataSource | null {\n this.logger.verbose(\n \"Attempting to get cloud discovery metadata from authority configuration\"\n );\n this.logger.verbosePii(\n `Known Authorities: ${\n this.authorityOptions.knownAuthorities ||\n Constants.NOT_APPLICABLE\n }`\n );\n this.logger.verbosePii(\n `Authority Metadata: ${\n this.authorityOptions.authorityMetadata ||\n Constants.NOT_APPLICABLE\n }`\n );\n this.logger.verbosePii(\n `Canonical Authority: ${\n metadataEntity.canonical_authority || Constants.NOT_APPLICABLE\n }`\n );\n const metadata = this.getCloudDiscoveryMetadataFromConfig();\n if (metadata) {\n this.logger.verbose(\n \"Found cloud discovery metadata in authority configuration\"\n );\n CacheHelpers.updateCloudDiscoveryMetadata(\n metadataEntity,\n metadata,\n false\n );\n return AuthorityMetadataSource.CONFIG;\n }\n\n // If the cached metadata came from config but that config was not passed to this instance, we must go to hardcoded values\n this.logger.verbose(\n \"Did not find cloud discovery metadata in the config... Attempting to get cloud discovery metadata from the hardcoded values.\"\n );\n\n if (this.options.skipAuthorityMetadataCache) {\n this.logger.verbose(\n \"Skipping hardcoded cloud discovery metadata cache since skipAuthorityMetadataCache is set to true. Attempting to get cloud discovery metadata from the network metadata cache.\"\n );\n } else {\n const hardcodedMetadata =\n getCloudDiscoveryMetadataFromHardcodedValues(\n this.hostnameAndPort\n );\n if (hardcodedMetadata) {\n this.logger.verbose(\n \"Found cloud discovery metadata from hardcoded values.\"\n );\n CacheHelpers.updateCloudDiscoveryMetadata(\n metadataEntity,\n hardcodedMetadata,\n false\n );\n return AuthorityMetadataSource.HARDCODED_VALUES;\n }\n\n this.logger.verbose(\n \"Did not find cloud discovery metadata in hardcoded values... Attempting to get cloud discovery metadata from the network metadata cache.\"\n );\n }\n\n const metadataEntityExpired =\n CacheHelpers.isAuthorityMetadataExpired(metadataEntity);\n if (\n this.isAuthoritySameType(metadataEntity) &&\n metadataEntity.aliasesFromNetwork &&\n !metadataEntityExpired\n ) {\n this.logger.verbose(\"Found cloud discovery metadata in the cache.\");\n // No need to update\n return AuthorityMetadataSource.CACHE;\n } else if (metadataEntityExpired) {\n this.logger.verbose(\"The metadata entity is expired.\");\n }\n\n return null;\n }\n\n /**\n * Parse cloudDiscoveryMetadata config or check knownAuthorities\n */\n private getCloudDiscoveryMetadataFromConfig(): CloudDiscoveryMetadata | null {\n // CIAM does not support cloud discovery metadata\n if (this.authorityType === AuthorityType.Ciam) {\n this.logger.verbose(\n \"CIAM authorities do not support cloud discovery metadata, generate the aliases from authority host.\"\n );\n return Authority.createCloudDiscoveryMetadataFromHost(\n this.hostnameAndPort\n );\n }\n\n // Check if network response was provided in config\n if (this.authorityOptions.cloudDiscoveryMetadata) {\n this.logger.verbose(\n \"The cloud discovery metadata has been provided as a network response, in the config.\"\n );\n try {\n this.logger.verbose(\n \"Attempting to parse the cloud discovery metadata.\"\n );\n const parsedResponse = JSON.parse(\n this.authorityOptions.cloudDiscoveryMetadata\n ) as CloudInstanceDiscoveryResponse;\n const metadata = getCloudDiscoveryMetadataFromNetworkResponse(\n parsedResponse.metadata,\n this.hostnameAndPort\n );\n this.logger.verbose(\"Parsed the cloud discovery metadata.\");\n if (metadata) {\n this.logger.verbose(\n \"There is returnable metadata attached to the parsed cloud discovery metadata.\"\n );\n return metadata;\n } else {\n this.logger.verbose(\n \"There is no metadata attached to the parsed cloud discovery metadata.\"\n );\n }\n } catch (e) {\n this.logger.verbose(\n \"Unable to parse the cloud discovery metadata. Throwing Invalid Cloud Discovery Metadata Error.\"\n );\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.invalidCloudDiscoveryMetadata\n );\n }\n }\n\n // If cloudDiscoveryMetadata is empty or does not contain the host, check knownAuthorities\n if (this.isInKnownAuthorities()) {\n this.logger.verbose(\n \"The host is included in knownAuthorities. Creating new cloud discovery metadata from the host.\"\n );\n return Authority.createCloudDiscoveryMetadataFromHost(\n this.hostnameAndPort\n );\n }\n\n return null;\n }\n\n /**\n * Called to get metadata from network if CloudDiscoveryMetadata was not populated by config\n *\n * @param hasHardcodedMetadata boolean\n */\n private async getCloudDiscoveryMetadataFromNetwork(): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthorityGetCloudDiscoveryMetadataFromNetwork,\n this.correlationId\n );\n const instanceDiscoveryEndpoint = `${Constants.AAD_INSTANCE_DISCOVERY_ENDPT}${this.canonicalAuthority}oauth2/v2.0/authorize`;\n const options: ImdsOptions = {};\n\n /*\n * TODO: Add a timeout if the authority exists in our library's\n * hardcoded list of metadata\n */\n\n let match = null;\n try {\n const response = await this.networkInterface.sendGetRequestAsync<\n | CloudInstanceDiscoveryResponse\n | CloudInstanceDiscoveryErrorResponse\n >(instanceDiscoveryEndpoint, options);\n let typedResponseBody:\n | CloudInstanceDiscoveryResponse\n | CloudInstanceDiscoveryErrorResponse;\n let metadata: Array;\n if (isCloudInstanceDiscoveryResponse(response.body)) {\n typedResponseBody =\n response.body as CloudInstanceDiscoveryResponse;\n metadata = typedResponseBody.metadata;\n\n this.logger.verbosePii(\n `tenant_discovery_endpoint is: ${typedResponseBody.tenant_discovery_endpoint}`\n );\n } else if (isCloudInstanceDiscoveryErrorResponse(response.body)) {\n this.logger.warning(\n `A CloudInstanceDiscoveryErrorResponse was returned. The cloud instance discovery network request's status code is: ${response.status}`\n );\n\n typedResponseBody =\n response.body as CloudInstanceDiscoveryErrorResponse;\n if (typedResponseBody.error === Constants.INVALID_INSTANCE) {\n this.logger.error(\n \"The CloudInstanceDiscoveryErrorResponse error is invalid_instance.\"\n );\n return null;\n }\n\n this.logger.warning(\n `The CloudInstanceDiscoveryErrorResponse error is ${typedResponseBody.error}`\n );\n this.logger.warning(\n `The CloudInstanceDiscoveryErrorResponse error description is ${typedResponseBody.error_description}`\n );\n\n this.logger.warning(\n \"Setting the value of the CloudInstanceDiscoveryMetadata (returned from the network) to []\"\n );\n metadata = [];\n } else {\n this.logger.error(\n \"AAD did not return a CloudInstanceDiscoveryResponse or CloudInstanceDiscoveryErrorResponse\"\n );\n return null;\n }\n\n this.logger.verbose(\n \"Attempting to find a match between the developer's authority and the CloudInstanceDiscoveryMetadata returned from the network request.\"\n );\n match = getCloudDiscoveryMetadataFromNetworkResponse(\n metadata,\n this.hostnameAndPort\n );\n } catch (error) {\n if (error instanceof AuthError) {\n this.logger.error(\n `There was a network error while attempting to get the cloud discovery instance metadata.\\nError: ${error.errorCode}\\nError Description: ${error.errorMessage}`\n );\n } else {\n const typedError = error as Error;\n this.logger.error(\n `A non-MSALJS error was thrown while attempting to get the cloud instance discovery metadata.\\nError: ${typedError.name}\\nError Description: ${typedError.message}`\n );\n }\n\n return null;\n }\n\n // Custom Domain scenario, host is trusted because Instance Discovery call succeeded\n if (!match) {\n this.logger.warning(\n \"The developer's authority was not found within the CloudInstanceDiscoveryMetadata returned from the network request.\"\n );\n this.logger.verbose(\n \"Creating custom Authority for custom domain scenario.\"\n );\n\n match = Authority.createCloudDiscoveryMetadataFromHost(\n this.hostnameAndPort\n );\n }\n return match;\n }\n\n /**\n * Helper function to determine if this host is included in the knownAuthorities config option\n */\n private isInKnownAuthorities(): boolean {\n const matches = this.authorityOptions.knownAuthorities.filter(\n (authority) => {\n return (\n authority &&\n UrlString.getDomainFromUrl(authority).toLowerCase() ===\n this.hostnameAndPort\n );\n }\n );\n return matches.length > 0;\n }\n\n /**\n * helper function to populate the authority based on azureCloudOptions\n * @param authorityString\n * @param azureCloudOptions\n */\n static generateAuthority(\n authorityString: string,\n azureCloudOptions?: AzureCloudOptions\n ): string {\n let authorityAzureCloudInstance;\n\n if (\n azureCloudOptions &&\n azureCloudOptions.azureCloudInstance !== AzureCloudInstance.None\n ) {\n const tenant = azureCloudOptions.tenant\n ? azureCloudOptions.tenant\n : Constants.DEFAULT_COMMON_TENANT;\n authorityAzureCloudInstance = `${azureCloudOptions.azureCloudInstance}/${tenant}/`;\n }\n\n return authorityAzureCloudInstance\n ? authorityAzureCloudInstance\n : authorityString;\n }\n\n /**\n * Creates cloud discovery metadata object from a given host\n * @param host\n */\n static createCloudDiscoveryMetadataFromHost(\n host: string\n ): CloudDiscoveryMetadata {\n return {\n preferred_network: host,\n preferred_cache: host,\n aliases: [host],\n };\n }\n\n /**\n * helper function to generate environment from authority object\n */\n getPreferredCache(): string {\n if (this.managedIdentity) {\n return Constants.DEFAULT_AUTHORITY_HOST;\n } else if (this.discoveryComplete()) {\n return this.metadata.preferred_cache;\n } else {\n throw createClientAuthError(\n ClientAuthErrorCodes.endpointResolutionError\n );\n }\n }\n\n /**\n * Returns whether or not the provided host is an alias of this authority instance\n * @param host\n */\n isAlias(host: string): boolean {\n return this.metadata.aliases.indexOf(host) > -1;\n }\n\n /**\n * Returns whether or not the provided host is an alias of a known Microsoft authority for purposes of endpoint discovery\n * @param host\n */\n isAliasOfKnownMicrosoftAuthority(host: string): boolean {\n return InstanceDiscoveryMetadataAliases.has(host);\n }\n\n /**\n * Checks whether the provided host is that of a public cloud authority\n *\n * @param authority string\n * @returns bool\n */\n static isPublicCloudAuthority(host: string): boolean {\n return Constants.KNOWN_PUBLIC_CLOUDS.indexOf(host) >= 0;\n }\n\n /**\n * Rebuild the authority string with the region\n *\n * @param host string\n * @param region string\n */\n static buildRegionalAuthorityString(\n host: string,\n region: string,\n queryString?: string\n ): string {\n // Create and validate a Url string object with the initial authority string\n const authorityUrlInstance = new UrlString(host);\n authorityUrlInstance.validateAsUri();\n\n const authorityUrlParts = authorityUrlInstance.getUrlComponents();\n\n let hostNameAndPort = `${region}.${authorityUrlParts.HostNameAndPort}`;\n\n if (this.isPublicCloudAuthority(authorityUrlParts.HostNameAndPort)) {\n hostNameAndPort = `${region}.${Constants.REGIONAL_AUTH_PUBLIC_CLOUD_SUFFIX}`;\n }\n\n // Include the query string portion of the url\n const url = UrlString.constructAuthorityUriFromObject({\n ...authorityUrlInstance.getUrlComponents(),\n HostNameAndPort: hostNameAndPort,\n }).urlString;\n\n // Add the query string if a query string was provided\n if (queryString) return `${url}?${queryString}`;\n\n return url;\n }\n\n /**\n * Replace the endpoints in the metadata object with their regional equivalents.\n *\n * @param metadata OpenIdConfigResponse\n * @param azureRegion string\n */\n static replaceWithRegionalInformation(\n metadata: OpenIdConfigResponse,\n azureRegion: string\n ): OpenIdConfigResponse {\n const regionalMetadata = { ...metadata };\n regionalMetadata.authorization_endpoint =\n Authority.buildRegionalAuthorityString(\n regionalMetadata.authorization_endpoint,\n azureRegion\n );\n\n regionalMetadata.token_endpoint =\n Authority.buildRegionalAuthorityString(\n regionalMetadata.token_endpoint,\n azureRegion\n );\n\n if (regionalMetadata.end_session_endpoint) {\n regionalMetadata.end_session_endpoint =\n Authority.buildRegionalAuthorityString(\n regionalMetadata.end_session_endpoint,\n azureRegion\n );\n }\n\n return regionalMetadata;\n }\n\n /**\n * Transform CIAM_AUTHORIY as per the below rules:\n * If no path segments found and it is a CIAM authority (hostname ends with .ciamlogin.com), then transform it\n *\n * NOTE: The transformation path should go away once STS supports CIAM with the format: `tenantIdorDomain.ciamlogin.com`\n * `ciamlogin.com` can also change in the future and we should accommodate the same\n *\n * @param authority\n */\n static transformCIAMAuthority(authority: string): string {\n let ciamAuthority = authority;\n const authorityUrl = new UrlString(authority);\n const authorityUrlComponents = authorityUrl.getUrlComponents();\n\n // check if transformation is needed\n if (\n authorityUrlComponents.PathSegments.length === 0 &&\n authorityUrlComponents.HostNameAndPort.endsWith(\n Constants.CIAM_AUTH_URL\n )\n ) {\n const tenantIdOrDomain =\n authorityUrlComponents.HostNameAndPort.split(\".\")[0];\n ciamAuthority = `${ciamAuthority}${tenantIdOrDomain}${Constants.AAD_TENANT_DOMAIN_SUFFIX}`;\n }\n\n return ciamAuthority;\n }\n}\n\n/**\n * Extract tenantId from authority\n */\nexport function getTenantFromAuthorityString(\n authority: string\n): string | undefined {\n const authorityUrl = new UrlString(authority);\n const authorityUrlComponents = authorityUrl.getUrlComponents();\n /**\n * For credential matching purposes, tenantId is the last path segment of the authority URL:\n * AAD Authority - domain/tenantId -> Credentials are cached with realm = tenantId\n * B2C Authority - domain/{tenantId}?/.../policy -> Credentials are cached with realm = policy\n * tenantId is downcased because B2C policies can have mixed case but tfp claim is downcased\n *\n * Note that we may not have any path segments in certain OIDC scenarios.\n */\n const tenantId =\n authorityUrlComponents.PathSegments.slice(-1)[0]?.toLowerCase();\n\n switch (tenantId) {\n case AADAuthorityConstants.COMMON:\n case AADAuthorityConstants.ORGANIZATIONS:\n case AADAuthorityConstants.CONSUMERS:\n return undefined;\n default:\n return tenantId;\n }\n}\n\nexport function formatAuthorityUri(authorityUri: string): string {\n return authorityUri.endsWith(Constants.FORWARD_SLASH)\n ? authorityUri\n : `${authorityUri}${Constants.FORWARD_SLASH}`;\n}\n\nexport function buildStaticAuthorityOptions(\n authOptions: Partial\n): StaticAuthorityOptions {\n const rawCloudDiscoveryMetadata = authOptions.cloudDiscoveryMetadata;\n let cloudDiscoveryMetadata: CloudInstanceDiscoveryResponse | undefined =\n undefined;\n if (rawCloudDiscoveryMetadata) {\n try {\n cloudDiscoveryMetadata = JSON.parse(rawCloudDiscoveryMetadata);\n } catch (e) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.invalidCloudDiscoveryMetadata\n );\n }\n }\n return {\n canonicalAuthority: authOptions.authority\n ? formatAuthorityUri(authOptions.authority)\n : undefined,\n knownAuthorities: authOptions.knownAuthorities,\n cloudDiscoveryMetadata: cloudDiscoveryMetadata,\n };\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Authority, formatAuthorityUri } from \"./Authority.js\";\nimport { INetworkModule } from \"../network/INetworkModule.js\";\nimport {\n createClientAuthError,\n ClientAuthErrorCodes,\n} from \"../error/ClientAuthError.js\";\nimport { ICacheManager } from \"../cache/interface/ICacheManager.js\";\nimport { AuthorityOptions } from \"./AuthorityOptions.js\";\nimport { Logger } from \"../logger/Logger.js\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\n\n/**\n * Create an authority object of the correct type based on the url\n * Performs basic authority validation - checks to see if the authority is of a valid type (i.e. aad, b2c, adfs)\n *\n * Also performs endpoint discovery.\n *\n * @param authorityUri\n * @param networkClient\n * @param protocolMode\n * @internal\n */\nexport async function createDiscoveredInstance(\n authorityUri: string,\n networkClient: INetworkModule,\n cacheManager: ICacheManager,\n authorityOptions: AuthorityOptions,\n logger: Logger,\n correlationId: string,\n performanceClient?: IPerformanceClient\n): Promise {\n performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthorityFactoryCreateDiscoveredInstance,\n correlationId\n );\n const authorityUriFinal = Authority.transformCIAMAuthority(\n formatAuthorityUri(authorityUri)\n );\n\n // Initialize authority and perform discovery endpoint check.\n const acquireTokenAuthority: Authority = new Authority(\n authorityUriFinal,\n networkClient,\n cacheManager,\n authorityOptions,\n logger,\n correlationId,\n performanceClient\n );\n\n try {\n await invokeAsync(\n acquireTokenAuthority.resolveEndpointsAsync.bind(\n acquireTokenAuthority\n ),\n PerformanceEvents.AuthorityResolveEndpointsAsync,\n logger,\n performanceClient,\n correlationId\n )();\n return acquireTokenAuthority;\n } catch (e) {\n throw createClientAuthError(\n ClientAuthErrorCodes.endpointResolutionError\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthError } from \"./AuthError.js\";\n\n/**\n * Error thrown when there is an error with the server code, for example, unavailability.\n */\nexport class ServerError extends AuthError {\n /**\n * Server error number;\n */\n readonly errorNo?: string;\n\n /**\n * Http status number;\n */\n readonly status?: number;\n\n constructor(\n errorCode?: string,\n errorMessage?: string,\n subError?: string,\n errorNo?: string,\n status?: number\n ) {\n super(errorCode, errorMessage, subError);\n this.name = \"ServerError\";\n this.errorNo = errorNo;\n this.status = status;\n\n Object.setPrototypeOf(this, ServerError.prototype);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ShrOptions } from \"../crypto/SignedHttpRequest.js\";\nimport { BaseAuthRequest } from \"../request/BaseAuthRequest.js\";\nimport { AuthenticationScheme } from \"../utils/Constants.js\";\n\n/**\n * Type representing a unique request thumbprint.\n */\nexport type RequestThumbprint = {\n clientId: string;\n authority: string;\n scopes: Array;\n homeAccountIdentifier?: string;\n claims?: string;\n authenticationScheme?: AuthenticationScheme;\n resourceRequestMethod?: string;\n resourceRequestUri?: string;\n shrClaims?: string;\n sshKid?: string;\n shrOptions?: ShrOptions;\n embeddedClientId?: string;\n};\n\nexport function getRequestThumbprint(\n clientId: string,\n request: BaseAuthRequest,\n homeAccountId?: string\n): RequestThumbprint {\n return {\n clientId: clientId,\n authority: request.authority,\n scopes: request.scopes,\n homeAccountIdentifier: homeAccountId,\n claims: request.claims,\n authenticationScheme: request.authenticationScheme,\n resourceRequestMethod: request.resourceRequestMethod,\n resourceRequestUri: request.resourceRequestUri,\n shrClaims: request.shrClaims,\n sshKid: request.sshKid,\n embeddedClientId:\n request.embeddedClientId || request.tokenBodyParameters?.clientId,\n };\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { NetworkResponse } from \"./NetworkResponse.js\";\nimport { ServerAuthorizationTokenResponse } from \"../response/ServerAuthorizationTokenResponse.js\";\nimport {\n HeaderNames,\n ThrottlingConstants,\n Constants,\n} from \"../utils/Constants.js\";\nimport { CacheManager } from \"../cache/CacheManager.js\";\nimport { ServerError } from \"../error/ServerError.js\";\nimport {\n getRequestThumbprint,\n RequestThumbprint,\n} from \"./RequestThumbprint.js\";\nimport { ThrottlingEntity } from \"../cache/entities/ThrottlingEntity.js\";\nimport { BaseAuthRequest } from \"../request/BaseAuthRequest.js\";\n\n/** @internal */\nexport class ThrottlingUtils {\n /**\n * Prepares a RequestThumbprint to be stored as a key.\n * @param thumbprint\n */\n static generateThrottlingStorageKey(thumbprint: RequestThumbprint): string {\n return `${ThrottlingConstants.THROTTLING_PREFIX}.${JSON.stringify(\n thumbprint\n )}`;\n }\n\n /**\n * Performs necessary throttling checks before a network request.\n * @param cacheManager\n * @param thumbprint\n */\n static preProcess(\n cacheManager: CacheManager,\n thumbprint: RequestThumbprint,\n correlationId: string\n ): void {\n const key = ThrottlingUtils.generateThrottlingStorageKey(thumbprint);\n const value = cacheManager.getThrottlingCache(key);\n\n if (value) {\n if (value.throttleTime < Date.now()) {\n cacheManager.removeItem(key, correlationId);\n return;\n }\n throw new ServerError(\n value.errorCodes?.join(\" \") || Constants.EMPTY_STRING,\n value.errorMessage,\n value.subError\n );\n }\n }\n\n /**\n * Performs necessary throttling checks after a network request.\n * @param cacheManager\n * @param thumbprint\n * @param response\n */\n static postProcess(\n cacheManager: CacheManager,\n thumbprint: RequestThumbprint,\n response: NetworkResponse,\n correlationId: string\n ): void {\n if (\n ThrottlingUtils.checkResponseStatus(response) ||\n ThrottlingUtils.checkResponseForRetryAfter(response)\n ) {\n const thumbprintValue: ThrottlingEntity = {\n throttleTime: ThrottlingUtils.calculateThrottleTime(\n parseInt(response.headers[HeaderNames.RETRY_AFTER])\n ),\n error: response.body.error,\n errorCodes: response.body.error_codes,\n errorMessage: response.body.error_description,\n subError: response.body.suberror,\n };\n cacheManager.setThrottlingCache(\n ThrottlingUtils.generateThrottlingStorageKey(thumbprint),\n thumbprintValue,\n correlationId\n );\n }\n }\n\n /**\n * Checks a NetworkResponse object's status codes against 429 or 5xx\n * @param response\n */\n static checkResponseStatus(\n response: NetworkResponse\n ): boolean {\n return (\n response.status === 429 ||\n (response.status >= 500 && response.status < 600)\n );\n }\n\n /**\n * Checks a NetworkResponse object's RetryAfter header\n * @param response\n */\n static checkResponseForRetryAfter(\n response: NetworkResponse\n ): boolean {\n if (response.headers) {\n return (\n response.headers.hasOwnProperty(HeaderNames.RETRY_AFTER) &&\n (response.status < 200 || response.status >= 300)\n );\n }\n return false;\n }\n\n /**\n * Calculates the Unix-time value for a throttle to expire given throttleTime in seconds.\n * @param throttleTime\n */\n static calculateThrottleTime(throttleTime: number): number {\n const time = throttleTime <= 0 ? 0 : throttleTime;\n\n const currentSeconds = Date.now() / 1000;\n return Math.floor(\n Math.min(\n currentSeconds +\n (time || ThrottlingConstants.DEFAULT_THROTTLE_TIME_SECONDS),\n currentSeconds +\n ThrottlingConstants.DEFAULT_MAX_THROTTLE_TIME_SECONDS\n ) * 1000\n );\n }\n\n static removeThrottle(\n cacheManager: CacheManager,\n clientId: string,\n request: BaseAuthRequest,\n homeAccountIdentifier?: string\n ): void {\n const thumbprint = getRequestThumbprint(\n clientId,\n request,\n homeAccountIdentifier\n );\n const key = this.generateThrottlingStorageKey(thumbprint);\n cacheManager.removeItem(key, request.correlationId);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthError } from \"./AuthError.js\";\n\n/**\n * Represents network related errors\n */\nexport class NetworkError extends AuthError {\n error: AuthError;\n httpStatus?: number;\n responseHeaders?: Record;\n\n constructor(\n error: AuthError,\n httpStatus?: number,\n responseHeaders?: Record\n ) {\n super(error.errorCode, error.errorMessage, error.subError);\n\n Object.setPrototypeOf(this, NetworkError.prototype);\n this.name = \"NetworkError\";\n this.error = error;\n this.httpStatus = httpStatus;\n this.responseHeaders = responseHeaders;\n }\n}\n\n/**\n * Creates NetworkError object for a failed network request\n * @param error - Error to be thrown back to the caller\n * @param httpStatus - Status code of the network request\n * @param responseHeaders - Response headers of the network request, when available\n * @returns NetworkError object\n */\nexport function createNetworkError(\n error: AuthError,\n httpStatus?: number,\n responseHeaders?: Record,\n additionalError?: Error\n): NetworkError {\n error.errorMessage = `${error.errorMessage}, additionalErrorInfo: error.name:${additionalError?.name}, error.message:${additionalError?.message}`;\n return new NetworkError(error, httpStatus, responseHeaders);\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ClientConfiguration,\n buildClientConfiguration,\n CommonClientConfiguration,\n} from \"../config/ClientConfiguration.js\";\nimport {\n INetworkModule,\n NetworkRequestOptions,\n} from \"../network/INetworkModule.js\";\nimport { NetworkResponse } from \"../network/NetworkResponse.js\";\nimport { ICrypto } from \"../crypto/ICrypto.js\";\nimport { Authority } from \"../authority/Authority.js\";\nimport { Logger } from \"../logger/Logger.js\";\nimport { Constants, HeaderNames } from \"../utils/Constants.js\";\nimport { ServerAuthorizationTokenResponse } from \"../response/ServerAuthorizationTokenResponse.js\";\nimport { CacheManager } from \"../cache/CacheManager.js\";\nimport { ServerTelemetryManager } from \"../telemetry/server/ServerTelemetryManager.js\";\nimport { RequestThumbprint } from \"../network/RequestThumbprint.js\";\nimport { version, name } from \"../packageMetadata.js\";\nimport { CcsCredential, CcsCredentialType } from \"../account/CcsCredential.js\";\nimport { buildClientInfoFromHomeAccountId } from \"../account/ClientInfo.js\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\nimport * as RequestParameterBuilder from \"../request/RequestParameterBuilder.js\";\nimport * as UrlUtils from \"../utils/UrlUtils.js\";\nimport { BaseAuthRequest } from \"../request/BaseAuthRequest.js\";\nimport { createDiscoveredInstance } from \"../authority/AuthorityFactory.js\";\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\nimport { ThrottlingUtils } from \"../network/ThrottlingUtils.js\";\nimport { AuthError } from \"../error/AuthError.js\";\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n} from \"../error/ClientAuthError.js\";\nimport { NetworkError } from \"../error/NetworkError.js\";\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\n\n/**\n * Base application class which will construct requests to send to and handle responses from the Microsoft STS using the authorization code flow.\n * @internal\n */\nexport abstract class BaseClient {\n // Logger object\n public logger: Logger;\n\n // Application config\n protected config: CommonClientConfiguration;\n\n // Crypto Interface\n protected cryptoUtils: ICrypto;\n\n // Storage Interface\n protected cacheManager: CacheManager;\n\n // Network Interface\n protected networkClient: INetworkModule;\n\n // Server Telemetry Manager\n protected serverTelemetryManager: ServerTelemetryManager | null;\n\n // Default authority object\n public authority: Authority;\n\n // Performance telemetry client\n protected performanceClient?: IPerformanceClient;\n\n protected constructor(\n configuration: ClientConfiguration,\n performanceClient?: IPerformanceClient\n ) {\n // Set the configuration\n this.config = buildClientConfiguration(configuration);\n\n // Initialize the logger\n this.logger = new Logger(this.config.loggerOptions, name, version);\n\n // Initialize crypto\n this.cryptoUtils = this.config.cryptoInterface;\n\n // Initialize storage interface\n this.cacheManager = this.config.storageInterface;\n\n // Set the network interface\n this.networkClient = this.config.networkInterface;\n\n // Set TelemetryManager\n this.serverTelemetryManager = this.config.serverTelemetryManager;\n\n // set Authority\n this.authority = this.config.authOptions.authority;\n\n // set performance telemetry client\n this.performanceClient = performanceClient;\n }\n\n /**\n * Creates default headers for requests to token endpoint\n */\n protected createTokenRequestHeaders(\n ccsCred?: CcsCredential\n ): Record {\n const headers: Record = {};\n headers[HeaderNames.CONTENT_TYPE] = Constants.URL_FORM_CONTENT_TYPE;\n if (!this.config.systemOptions.preventCorsPreflight && ccsCred) {\n switch (ccsCred.type) {\n case CcsCredentialType.HOME_ACCOUNT_ID:\n try {\n const clientInfo = buildClientInfoFromHomeAccountId(\n ccsCred.credential\n );\n headers[\n HeaderNames.CCS_HEADER\n ] = `Oid:${clientInfo.uid}@${clientInfo.utid}`;\n } catch (e) {\n this.logger.verbose(\n \"Could not parse home account ID for CCS Header: \" +\n e\n );\n }\n break;\n case CcsCredentialType.UPN:\n headers[\n HeaderNames.CCS_HEADER\n ] = `UPN: ${ccsCred.credential}`;\n break;\n }\n }\n return headers;\n }\n\n /**\n * Http post to token endpoint\n * @param tokenEndpoint\n * @param queryString\n * @param headers\n * @param thumbprint\n */\n protected async executePostToTokenEndpoint(\n tokenEndpoint: string,\n queryString: string,\n headers: Record,\n thumbprint: RequestThumbprint,\n correlationId: string,\n queuedEvent?: string\n ): Promise> {\n if (queuedEvent) {\n this.performanceClient?.addQueueMeasurement(\n queuedEvent,\n correlationId\n );\n }\n\n const response =\n await this.sendPostRequest(\n thumbprint,\n tokenEndpoint,\n { body: queryString, headers: headers },\n correlationId\n );\n\n if (\n this.config.serverTelemetryManager &&\n response.status < 500 &&\n response.status !== 429\n ) {\n // Telemetry data successfully logged by server, clear Telemetry cache\n this.config.serverTelemetryManager.clearTelemetryCache();\n }\n\n return response;\n }\n\n /**\n * Wraps sendPostRequestAsync with necessary preflight and postflight logic\n * @param thumbprint - Request thumbprint for throttling\n * @param tokenEndpoint - Endpoint to make the POST to\n * @param options - Body and Headers to include on the POST request\n * @param correlationId - CorrelationId for telemetry\n */\n async sendPostRequest(\n thumbprint: RequestThumbprint,\n tokenEndpoint: string,\n options: NetworkRequestOptions,\n correlationId: string\n ): Promise> {\n ThrottlingUtils.preProcess(\n this.cacheManager,\n thumbprint,\n correlationId\n );\n\n let response;\n try {\n response = await invokeAsync(\n this.networkClient.sendPostRequestAsync.bind(\n this.networkClient\n ),\n PerformanceEvents.NetworkClientSendPostRequestAsync,\n this.logger,\n this.performanceClient,\n correlationId\n )(tokenEndpoint, options);\n const responseHeaders = response.headers || {};\n this.performanceClient?.addFields(\n {\n refreshTokenSize: response.body.refresh_token?.length || 0,\n httpVerToken:\n responseHeaders[HeaderNames.X_MS_HTTP_VERSION] || \"\",\n requestId:\n responseHeaders[HeaderNames.X_MS_REQUEST_ID] || \"\",\n },\n correlationId\n );\n } catch (e) {\n if (e instanceof NetworkError) {\n const responseHeaders = e.responseHeaders;\n if (responseHeaders) {\n this.performanceClient?.addFields(\n {\n httpVerToken:\n responseHeaders[\n HeaderNames.X_MS_HTTP_VERSION\n ] || \"\",\n requestId:\n responseHeaders[HeaderNames.X_MS_REQUEST_ID] ||\n \"\",\n contentTypeHeader:\n responseHeaders[HeaderNames.CONTENT_TYPE] ||\n undefined,\n contentLengthHeader:\n responseHeaders[HeaderNames.CONTENT_LENGTH] ||\n undefined,\n httpStatus: e.httpStatus,\n },\n correlationId\n );\n }\n throw e.error;\n }\n if (e instanceof AuthError) {\n throw e;\n } else {\n throw createClientAuthError(ClientAuthErrorCodes.networkError);\n }\n }\n\n ThrottlingUtils.postProcess(\n this.cacheManager,\n thumbprint,\n response,\n correlationId\n );\n\n return response;\n }\n\n /**\n * Updates the authority object of the client. Endpoint discovery must be completed.\n * @param updatedAuthority\n */\n async updateAuthority(\n cloudInstanceHostname: string,\n correlationId: string\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.UpdateTokenEndpointAuthority,\n correlationId\n );\n const cloudInstanceAuthorityUri = `https://${cloudInstanceHostname}/${this.authority.tenant}/`;\n const cloudInstanceAuthority = await createDiscoveredInstance(\n cloudInstanceAuthorityUri,\n this.networkClient,\n this.cacheManager,\n this.authority.options,\n this.logger,\n correlationId,\n this.performanceClient\n );\n this.authority = cloudInstanceAuthority;\n }\n\n /**\n * Creates query string for the /token request\n * @param request\n */\n createTokenQueryParameters(request: BaseAuthRequest): string {\n const parameters = new Map();\n\n if (request.embeddedClientId) {\n RequestParameterBuilder.addBrokerParameters(\n parameters,\n this.config.authOptions.clientId,\n this.config.authOptions.redirectUri\n );\n }\n\n if (request.tokenQueryParameters) {\n RequestParameterBuilder.addExtraQueryParameters(\n parameters,\n request.tokenQueryParameters\n );\n }\n\n RequestParameterBuilder.addCorrelationId(\n parameters,\n request.correlationId\n );\n\n RequestParameterBuilder.instrumentBrokerParams(\n parameters,\n request.correlationId,\n this.performanceClient\n );\n return UrlUtils.mapToQueryString(parameters);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Type which describes Id Token claims known by MSAL.\n */\nexport type TokenClaims = {\n /**\n * Audience\n */\n aud?: string;\n /**\n * Issuer\n */\n iss?: string;\n /**\n * Issued at\n */\n iat?: number;\n /**\n * Not valid before\n */\n nbf?: number;\n /**\n * Immutable object identifier, this ID uniquely identifies the user across applications\n */\n oid?: string;\n /**\n * Immutable subject identifier, this is a pairwise identifier - it is unique to a particular application ID\n */\n sub?: string;\n /**\n * Users' tenant or '9188040d-6c67-4c5b-b112-36a304b66dad' for personal accounts.\n */\n tid?: string;\n /**\n * Trusted Framework Policy (B2C) The name of the policy that was used to acquire the ID token.\n */\n tfp?: string;\n /**\n * Authentication Context Class Reference (B2C) Used only with older policies.\n */\n acr?: string;\n ver?: string;\n upn?: string;\n preferred_username?: string;\n login_hint?: string;\n emails?: string[];\n name?: string;\n nonce?: string;\n /**\n * Expiration\n */\n exp?: number;\n home_oid?: string;\n sid?: string;\n cloud_instance_host_name?: string;\n cnf?: {\n kid: string;\n };\n x5c_ca?: string[];\n ts?: number;\n at?: string;\n u?: string;\n p?: string;\n m?: string;\n roles?: string[];\n amr?: string[];\n idp?: string;\n auth_time?: number;\n /**\n * \tRegion of the resource tenant\n */\n tenant_region_scope?: string;\n tenant_region_sub_scope?: string;\n};\n\n/**\n * Gets tenantId from available ID token claims to set as credential realm with the following precedence:\n * 1. tid - if the token is acquired from an Azure AD tenant tid will be present\n * 2. tfp - if the token is acquired from a modern B2C tenant tfp should be present\n * 3. acr - if the token is acquired from a legacy B2C tenant acr should be present\n * Downcased to match the realm case-insensitive comparison requirements\n * @param idTokenClaims\n * @returns\n */\nexport function getTenantIdFromIdTokenClaims(\n idTokenClaims?: TokenClaims\n): string | null {\n if (idTokenClaims) {\n const tenantId =\n idTokenClaims.tid || idTokenClaims.tfp || idTokenClaims.acr;\n return tenantId || null;\n }\n return null;\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { CacheAccountType } from \"../../utils/Constants.js\";\nimport type { Authority } from \"../../authority/Authority.js\";\nimport { ICrypto } from \"../../crypto/ICrypto.js\";\nimport { ClientInfo, buildClientInfo } from \"../../account/ClientInfo.js\";\nimport {\n AccountInfo,\n TenantProfile,\n buildTenantProfile,\n} from \"../../account/AccountInfo.js\";\nimport {\n createClientAuthError,\n ClientAuthErrorCodes,\n} from \"../../error/ClientAuthError.js\";\nimport { AuthorityType } from \"../../authority/AuthorityType.js\";\nimport { Logger } from \"../../logger/Logger.js\";\nimport {\n TokenClaims,\n getTenantIdFromIdTokenClaims,\n} from \"../../account/TokenClaims.js\";\nimport { ProtocolMode } from \"../../authority/ProtocolMode.js\";\n\n/**\n * Type that defines required and optional parameters for an Account field (based on universal cache schema implemented by all MSALs).\n *\n * Key : Value Schema\n *\n * Key: --\n *\n * Value Schema:\n * {\n * homeAccountId: home account identifier for the auth scheme,\n * environment: entity that issued the token, represented as a full host\n * realm: Full tenant or organizational identifier that the account belongs to\n * localAccountId: Original tenant-specific accountID, usually used for legacy cases\n * username: primary username that represents the user, usually corresponds to preferred_username in the v2 endpt\n * authorityType: Accounts authority type as a string\n * name: Full name for the account, including given name and family name,\n * lastModificationTime: last time this entity was modified in the cache\n * lastModificationApp:\n * nativeAccountId: Account identifier on the native device\n * tenantProfiles: Array of tenant profile objects for each tenant that the account has authenticated with in the browser\n * }\n * @internal\n */\nexport class AccountEntity {\n homeAccountId: string;\n environment: string;\n realm: string;\n localAccountId: string;\n username: string;\n authorityType: string;\n loginHint?: string;\n clientInfo?: string;\n name?: string;\n lastModificationTime?: string;\n lastModificationApp?: string;\n cloudGraphHostName?: string;\n msGraphHost?: string;\n nativeAccountId?: string;\n tenantProfiles?: Array;\n lastUpdatedAt: string;\n\n /**\n * Returns the AccountInfo interface for this account.\n */\n getAccountInfo(): AccountInfo {\n return {\n homeAccountId: this.homeAccountId,\n environment: this.environment,\n tenantId: this.realm,\n username: this.username,\n localAccountId: this.localAccountId,\n loginHint: this.loginHint,\n name: this.name,\n nativeAccountId: this.nativeAccountId,\n authorityType: this.authorityType,\n // Deserialize tenant profiles array into a Map\n tenantProfiles: new Map(\n (this.tenantProfiles || []).map((tenantProfile) => {\n return [tenantProfile.tenantId, tenantProfile];\n })\n ),\n };\n }\n\n /**\n * Returns true if the account entity is in single tenant format (outdated), false otherwise\n */\n isSingleTenant(): boolean {\n return !this.tenantProfiles;\n }\n\n /**\n * Build Account cache from IdToken, clientInfo and authority/policy. Associated with AAD.\n * @param accountDetails\n */\n static createAccount(\n accountDetails: {\n homeAccountId: string;\n idTokenClaims?: TokenClaims;\n clientInfo?: string;\n cloudGraphHostName?: string;\n msGraphHost?: string;\n environment?: string;\n nativeAccountId?: string;\n tenantProfiles?: Array;\n },\n authority: Authority,\n base64Decode?: (input: string) => string\n ): AccountEntity {\n const account: AccountEntity = new AccountEntity();\n\n if (authority.authorityType === AuthorityType.Adfs) {\n account.authorityType = CacheAccountType.ADFS_ACCOUNT_TYPE;\n } else if (authority.protocolMode === ProtocolMode.OIDC) {\n account.authorityType = CacheAccountType.GENERIC_ACCOUNT_TYPE;\n } else {\n account.authorityType = CacheAccountType.MSSTS_ACCOUNT_TYPE;\n }\n\n let clientInfo: ClientInfo | undefined;\n\n if (accountDetails.clientInfo && base64Decode) {\n clientInfo = buildClientInfo(\n accountDetails.clientInfo,\n base64Decode\n );\n }\n\n account.clientInfo = accountDetails.clientInfo;\n account.homeAccountId = accountDetails.homeAccountId;\n account.nativeAccountId = accountDetails.nativeAccountId;\n\n const env =\n accountDetails.environment ||\n (authority && authority.getPreferredCache());\n\n if (!env) {\n throw createClientAuthError(\n ClientAuthErrorCodes.invalidCacheEnvironment\n );\n }\n\n account.environment = env;\n // non AAD scenarios can have empty realm\n account.realm =\n clientInfo?.utid ||\n getTenantIdFromIdTokenClaims(accountDetails.idTokenClaims) ||\n \"\";\n\n // How do you account for MSA CID here?\n account.localAccountId =\n clientInfo?.uid ||\n accountDetails.idTokenClaims?.oid ||\n accountDetails.idTokenClaims?.sub ||\n \"\";\n\n /*\n * In B2C scenarios the emails claim is used instead of preferred_username and it is an array.\n * In most cases it will contain a single email. This field should not be relied upon if a custom\n * policy is configured to return more than 1 email.\n */\n const preferredUsername =\n accountDetails.idTokenClaims?.preferred_username ||\n accountDetails.idTokenClaims?.upn;\n const email = accountDetails.idTokenClaims?.emails\n ? accountDetails.idTokenClaims.emails[0]\n : null;\n\n account.username = preferredUsername || email || \"\";\n account.loginHint = accountDetails.idTokenClaims?.login_hint;\n account.name = accountDetails.idTokenClaims?.name || \"\";\n\n account.cloudGraphHostName = accountDetails.cloudGraphHostName;\n account.msGraphHost = accountDetails.msGraphHost;\n\n if (accountDetails.tenantProfiles) {\n account.tenantProfiles = accountDetails.tenantProfiles;\n } else {\n const tenantProfile = buildTenantProfile(\n accountDetails.homeAccountId,\n account.localAccountId,\n account.realm,\n accountDetails.idTokenClaims\n );\n account.tenantProfiles = [tenantProfile];\n }\n\n return account;\n }\n\n /**\n * Creates an AccountEntity object from AccountInfo\n * @param accountInfo\n * @param cloudGraphHostName\n * @param msGraphHost\n * @returns\n */\n static createFromAccountInfo(\n accountInfo: AccountInfo,\n cloudGraphHostName?: string,\n msGraphHost?: string\n ): AccountEntity {\n const account: AccountEntity = new AccountEntity();\n\n account.authorityType =\n accountInfo.authorityType || CacheAccountType.GENERIC_ACCOUNT_TYPE;\n account.homeAccountId = accountInfo.homeAccountId;\n account.localAccountId = accountInfo.localAccountId;\n account.nativeAccountId = accountInfo.nativeAccountId;\n\n account.realm = accountInfo.tenantId;\n account.environment = accountInfo.environment;\n\n account.username = accountInfo.username;\n account.name = accountInfo.name;\n account.loginHint = accountInfo.loginHint;\n\n account.cloudGraphHostName = cloudGraphHostName;\n account.msGraphHost = msGraphHost;\n // Serialize tenant profiles map into an array\n account.tenantProfiles = Array.from(\n accountInfo.tenantProfiles?.values() || []\n );\n\n return account;\n }\n\n /**\n * Generate HomeAccountId from server response\n * @param serverClientInfo\n * @param authType\n */\n static generateHomeAccountId(\n serverClientInfo: string,\n authType: AuthorityType,\n logger: Logger,\n cryptoObj: ICrypto,\n idTokenClaims?: TokenClaims\n ): string {\n // since ADFS/DSTS do not have tid and does not set client_info\n if (\n !(\n authType === AuthorityType.Adfs ||\n authType === AuthorityType.Dsts\n )\n ) {\n // for cases where there is clientInfo\n if (serverClientInfo) {\n try {\n const clientInfo = buildClientInfo(\n serverClientInfo,\n cryptoObj.base64Decode\n );\n if (clientInfo.uid && clientInfo.utid) {\n return `${clientInfo.uid}.${clientInfo.utid}`;\n }\n } catch (e) {}\n }\n logger.warning(\"No client info in response\");\n }\n\n // default to \"sub\" claim\n return idTokenClaims?.sub || \"\";\n }\n\n /**\n * Validates an entity: checks for all expected params\n * @param entity\n */\n static isAccountEntity(entity: object): boolean {\n if (!entity) {\n return false;\n }\n\n return (\n entity.hasOwnProperty(\"homeAccountId\") &&\n entity.hasOwnProperty(\"environment\") &&\n entity.hasOwnProperty(\"realm\") &&\n entity.hasOwnProperty(\"localAccountId\") &&\n entity.hasOwnProperty(\"username\") &&\n entity.hasOwnProperty(\"authorityType\")\n );\n }\n\n /**\n * Helper function to determine whether 2 accountInfo objects represent the same account\n * @param accountA\n * @param accountB\n * @param compareClaims - If set to true idTokenClaims will also be compared to determine account equality\n */\n static accountInfoIsEqual(\n accountA: AccountInfo | null,\n accountB: AccountInfo | null,\n compareClaims?: boolean\n ): boolean {\n if (!accountA || !accountB) {\n return false;\n }\n\n let claimsMatch = true; // default to true so as to not fail comparison below if compareClaims: false\n if (compareClaims) {\n const accountAClaims = (accountA.idTokenClaims ||\n {}) as TokenClaims;\n const accountBClaims = (accountB.idTokenClaims ||\n {}) as TokenClaims;\n\n // issued at timestamp and nonce are expected to change each time a new id token is acquired\n claimsMatch =\n accountAClaims.iat === accountBClaims.iat &&\n accountAClaims.nonce === accountBClaims.nonce;\n }\n\n return (\n accountA.homeAccountId === accountB.homeAccountId &&\n accountA.localAccountId === accountB.localAccountId &&\n accountA.username === accountB.username &&\n accountA.tenantId === accountB.tenantId &&\n accountA.loginHint === accountB.loginHint &&\n accountA.environment === accountB.environment &&\n accountA.nativeAccountId === accountB.nativeAccountId &&\n claimsMatch\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n// Codes defined by MSAL\nexport const noTokensFound = \"no_tokens_found\";\nexport const nativeAccountUnavailable = \"native_account_unavailable\";\nexport const refreshTokenExpired = \"refresh_token_expired\";\nexport const uxNotAllowed = \"ux_not_allowed\";\n\n// Codes potentially returned by server\nexport const interactionRequired = \"interaction_required\";\nexport const consentRequired = \"consent_required\";\nexport const loginRequired = \"login_required\";\nexport const badToken = \"bad_token\";\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Constants } from \"../utils/Constants.js\";\nimport { AuthError } from \"./AuthError.js\";\nimport * as InteractionRequiredAuthErrorCodes from \"./InteractionRequiredAuthErrorCodes.js\";\nexport { InteractionRequiredAuthErrorCodes };\n\n/**\n * InteractionRequiredServerErrorMessage contains string constants used by error codes and messages returned by the server indicating interaction is required\n */\nexport const InteractionRequiredServerErrorMessage = [\n InteractionRequiredAuthErrorCodes.interactionRequired,\n InteractionRequiredAuthErrorCodes.consentRequired,\n InteractionRequiredAuthErrorCodes.loginRequired,\n InteractionRequiredAuthErrorCodes.badToken,\n InteractionRequiredAuthErrorCodes.uxNotAllowed,\n];\n\nexport const InteractionRequiredAuthSubErrorMessage = [\n \"message_only\",\n \"additional_action\",\n \"basic_action\",\n \"user_password_expired\",\n \"consent_required\",\n \"bad_token\",\n];\n\nconst InteractionRequiredAuthErrorMessages = {\n [InteractionRequiredAuthErrorCodes.noTokensFound]:\n \"No refresh token found in the cache. Please sign-in.\",\n [InteractionRequiredAuthErrorCodes.nativeAccountUnavailable]:\n \"The requested account is not available in the native broker. It may have been deleted or logged out. Please sign-in again using an interactive API.\",\n [InteractionRequiredAuthErrorCodes.refreshTokenExpired]:\n \"Refresh token has expired.\",\n [InteractionRequiredAuthErrorCodes.badToken]:\n \"Identity provider returned bad_token due to an expired or invalid refresh token. Please invoke an interactive API to resolve.\",\n [InteractionRequiredAuthErrorCodes.uxNotAllowed]:\n \"`canShowUI` flag in Edge was set to false. User interaction required on web page. Please invoke an interactive API to resolve.\",\n};\n\n/**\n * Interaction required errors defined by the SDK\n * @deprecated Use InteractionRequiredAuthErrorCodes instead\n */\nexport const InteractionRequiredAuthErrorMessage = {\n noTokensFoundError: {\n code: InteractionRequiredAuthErrorCodes.noTokensFound,\n desc: InteractionRequiredAuthErrorMessages[\n InteractionRequiredAuthErrorCodes.noTokensFound\n ],\n },\n native_account_unavailable: {\n code: InteractionRequiredAuthErrorCodes.nativeAccountUnavailable,\n desc: InteractionRequiredAuthErrorMessages[\n InteractionRequiredAuthErrorCodes.nativeAccountUnavailable\n ],\n },\n bad_token: {\n code: InteractionRequiredAuthErrorCodes.badToken,\n desc: InteractionRequiredAuthErrorMessages[\n InteractionRequiredAuthErrorCodes.badToken\n ],\n },\n};\n\n/**\n * Error thrown when user interaction is required.\n */\nexport class InteractionRequiredAuthError extends AuthError {\n /**\n * The time the error occured at\n */\n timestamp: string;\n\n /**\n * TraceId associated with the error\n */\n traceId: string;\n\n /**\n * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/claims-challenge.md\n *\n * A string with extra claims needed for the token request to succeed\n * web site: redirect the user to the authorization page and set the extra claims\n * web api: include the claims in the WWW-Authenticate header that are sent back to the client so that it knows to request a token with the extra claims\n * desktop application or browser context: include the claims when acquiring the token interactively\n * app to app context (client_credentials): include the claims in the AcquireTokenByClientCredential request\n */\n claims: string;\n\n /**\n * Server error number;\n */\n readonly errorNo?: string;\n\n constructor(\n errorCode?: string,\n errorMessage?: string,\n subError?: string,\n timestamp?: string,\n traceId?: string,\n correlationId?: string,\n claims?: string,\n errorNo?: string\n ) {\n super(errorCode, errorMessage, subError);\n Object.setPrototypeOf(this, InteractionRequiredAuthError.prototype);\n\n this.timestamp = timestamp || Constants.EMPTY_STRING;\n this.traceId = traceId || Constants.EMPTY_STRING;\n this.correlationId = correlationId || Constants.EMPTY_STRING;\n this.claims = claims || Constants.EMPTY_STRING;\n this.name = \"InteractionRequiredAuthError\";\n this.errorNo = errorNo;\n }\n}\n\n/**\n * Helper function used to determine if an error thrown by the server requires interaction to resolve\n * @param errorCode\n * @param errorString\n * @param subError\n */\nexport function isInteractionRequiredError(\n errorCode?: string,\n errorString?: string,\n subError?: string\n): boolean {\n const isInteractionRequiredErrorCode =\n !!errorCode &&\n InteractionRequiredServerErrorMessage.indexOf(errorCode) > -1;\n const isInteractionRequiredSubError =\n !!subError &&\n InteractionRequiredAuthSubErrorMessage.indexOf(subError) > -1;\n const isInteractionRequiredErrorDesc =\n !!errorString &&\n InteractionRequiredServerErrorMessage.some((irErrorCode) => {\n return errorString.indexOf(irErrorCode) > -1;\n });\n\n return (\n isInteractionRequiredErrorCode ||\n isInteractionRequiredErrorDesc ||\n isInteractionRequiredSubError\n );\n}\n\n/**\n * Creates an InteractionRequiredAuthError\n */\nexport function createInteractionRequiredAuthError(\n errorCode: string\n): InteractionRequiredAuthError {\n return new InteractionRequiredAuthError(\n errorCode,\n InteractionRequiredAuthErrorMessages[errorCode]\n );\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Constants } from \"./Constants.js\";\nimport { ICrypto } from \"../crypto/ICrypto.js\";\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n} from \"../error/ClientAuthError.js\";\n\n/**\n * Type which defines the object that is stringified, encoded and sent in the state value.\n * Contains the following:\n * - id - unique identifier for this request\n * - ts - timestamp for the time the request was made. Used to ensure that token expiration is not calculated incorrectly.\n * - platformState - string value sent from the platform.\n */\nexport type LibraryStateObject = {\n id: string;\n meta?: Record;\n};\n\n/**\n * Type which defines the stringified and encoded object sent to the service in the authorize request.\n */\nexport type RequestStateObject = {\n userRequestState: string;\n libraryState: LibraryStateObject;\n};\n\n/**\n * Class which provides helpers for OAuth 2.0 protocol specific values\n */\nexport class ProtocolUtils {\n /**\n * Appends user state with random guid, or returns random guid.\n * @param userState\n * @param randomGuid\n */\n static setRequestState(\n cryptoObj: ICrypto,\n userState?: string,\n meta?: Record\n ): string {\n const libraryState = ProtocolUtils.generateLibraryState(\n cryptoObj,\n meta\n );\n return userState\n ? `${libraryState}${Constants.RESOURCE_DELIM}${userState}`\n : libraryState;\n }\n\n /**\n * Generates the state value used by the common library.\n * @param randomGuid\n * @param cryptoObj\n */\n static generateLibraryState(\n cryptoObj: ICrypto,\n meta?: Record\n ): string {\n if (!cryptoObj) {\n throw createClientAuthError(ClientAuthErrorCodes.noCryptoObject);\n }\n\n // Create a state object containing a unique id and the timestamp of the request creation\n const stateObj: LibraryStateObject = {\n id: cryptoObj.createNewGuid(),\n };\n\n if (meta) {\n stateObj.meta = meta;\n }\n\n const stateString = JSON.stringify(stateObj);\n\n return cryptoObj.base64Encode(stateString);\n }\n\n /**\n * Parses the state into the RequestStateObject, which contains the LibraryState info and the state passed by the user.\n * @param state\n * @param cryptoObj\n */\n static parseRequestState(\n cryptoObj: ICrypto,\n state: string\n ): RequestStateObject {\n if (!cryptoObj) {\n throw createClientAuthError(ClientAuthErrorCodes.noCryptoObject);\n }\n\n if (!state) {\n throw createClientAuthError(ClientAuthErrorCodes.invalidState);\n }\n\n try {\n // Split the state between library state and user passed state and decode them separately\n const splitState = state.split(Constants.RESOURCE_DELIM);\n const libraryState = splitState[0];\n const userState =\n splitState.length > 1\n ? splitState.slice(1).join(Constants.RESOURCE_DELIM)\n : Constants.EMPTY_STRING;\n const libraryStateString = cryptoObj.base64Decode(libraryState);\n const libraryStateObj = JSON.parse(\n libraryStateString\n ) as LibraryStateObject;\n return {\n userRequestState: userState || Constants.EMPTY_STRING,\n libraryState: libraryStateObj,\n };\n } catch (e) {\n throw createClientAuthError(ClientAuthErrorCodes.invalidState);\n }\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ICrypto, SignedHttpRequestParameters } from \"./ICrypto.js\";\nimport * as TimeUtils from \"../utils/TimeUtils.js\";\nimport { UrlString } from \"../url/UrlString.js\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\nimport { Logger } from \"../logger/Logger.js\";\n\n/**\n * See eSTS docs for more info.\n * - A kid element, with the value containing an RFC 7638-compliant JWK thumbprint that is base64 encoded.\n * - xms_ksl element, representing the storage location of the key's secret component on the client device. One of two values:\n * - sw: software storage\n * - uhw: hardware storage\n */\ntype ReqCnf = {\n kid: string;\n xms_ksl: KeyLocation;\n};\n\nexport type ReqCnfData = {\n kid: string;\n reqCnfString: string;\n};\n\nconst KeyLocation = {\n SW: \"sw\",\n UHW: \"uhw\",\n} as const;\nexport type KeyLocation = (typeof KeyLocation)[keyof typeof KeyLocation];\n\n/** @internal */\nexport class PopTokenGenerator {\n private cryptoUtils: ICrypto;\n private performanceClient?: IPerformanceClient;\n\n constructor(cryptoUtils: ICrypto, performanceClient?: IPerformanceClient) {\n this.cryptoUtils = cryptoUtils;\n this.performanceClient = performanceClient;\n }\n\n /**\n * Generates the req_cnf validated at the RP in the POP protocol for SHR parameters\n * and returns an object containing the keyid, the full req_cnf string and the req_cnf string hash\n * @param request\n * @returns\n */\n async generateCnf(\n request: SignedHttpRequestParameters,\n logger: Logger\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.PopTokenGenerateCnf,\n request.correlationId\n );\n\n const reqCnf = await invokeAsync(\n this.generateKid.bind(this),\n PerformanceEvents.PopTokenGenerateCnf,\n logger,\n this.performanceClient,\n request.correlationId\n )(request);\n const reqCnfString: string = this.cryptoUtils.base64UrlEncode(\n JSON.stringify(reqCnf)\n );\n\n return {\n kid: reqCnf.kid,\n reqCnfString,\n };\n }\n\n /**\n * Generates key_id for a SHR token request\n * @param request\n * @returns\n */\n async generateKid(request: SignedHttpRequestParameters): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.PopTokenGenerateKid,\n request.correlationId\n );\n\n const kidThumbprint = await this.cryptoUtils.getPublicKeyThumbprint(\n request\n );\n\n return {\n kid: kidThumbprint,\n xms_ksl: KeyLocation.SW,\n };\n }\n\n /**\n * Signs the POP access_token with the local generated key-pair\n * @param accessToken\n * @param request\n * @returns\n */\n async signPopToken(\n accessToken: string,\n keyId: string,\n request: SignedHttpRequestParameters\n ): Promise {\n return this.signPayload(accessToken, keyId, request);\n }\n\n /**\n * Utility function to generate the signed JWT for an access_token\n * @param payload\n * @param kid\n * @param request\n * @param claims\n * @returns\n */\n async signPayload(\n payload: string,\n keyId: string,\n request: SignedHttpRequestParameters,\n claims?: object\n ): Promise {\n // Deconstruct request to extract SHR parameters\n const {\n resourceRequestMethod,\n resourceRequestUri,\n shrClaims,\n shrNonce,\n shrOptions,\n } = request;\n\n const resourceUrlString = resourceRequestUri\n ? new UrlString(resourceRequestUri)\n : undefined;\n const resourceUrlComponents = resourceUrlString?.getUrlComponents();\n return this.cryptoUtils.signJwt(\n {\n at: payload,\n ts: TimeUtils.nowSeconds(),\n m: resourceRequestMethod?.toUpperCase(),\n u: resourceUrlComponents?.HostNameAndPort,\n nonce: shrNonce || this.cryptoUtils.createNewGuid(),\n p: resourceUrlComponents?.AbsolutePath,\n q: resourceUrlComponents?.QueryString\n ? [[], resourceUrlComponents.QueryString]\n : undefined,\n client_claims: shrClaims || undefined,\n ...claims,\n },\n keyId,\n shrOptions,\n request.correlationId\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ISerializableTokenCache } from \"../interface/ISerializableTokenCache.js\";\n\n/**\n * This class instance helps track the memory changes facilitating\n * decisions to read from and write to the persistent cache\n */ export class TokenCacheContext {\n /**\n * boolean indicating cache change\n */\n hasChanged: boolean;\n /**\n * serializable token cache interface\n */\n cache: ISerializableTokenCache;\n\n constructor(tokenCache: ISerializableTokenCache, hasChanged: boolean) {\n this.cache = tokenCache;\n this.hasChanged = hasChanged;\n }\n\n /**\n * boolean which indicates the changes in cache\n */\n get cacheHasChanged(): boolean {\n return this.hasChanged;\n }\n\n /**\n * function to retrieve the token cache\n */\n get tokenCache(): ISerializableTokenCache {\n return this.cache;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ServerAuthorizationTokenResponse } from \"./ServerAuthorizationTokenResponse.js\";\nimport { ICrypto } from \"../crypto/ICrypto.js\";\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n} from \"../error/ClientAuthError.js\";\nimport { Logger } from \"../logger/Logger.js\";\nimport { ServerError } from \"../error/ServerError.js\";\nimport { ScopeSet } from \"../request/ScopeSet.js\";\nimport { AuthenticationResult } from \"./AuthenticationResult.js\";\nimport { AccountEntity } from \"../cache/entities/AccountEntity.js\";\nimport { Authority } from \"../authority/Authority.js\";\nimport { IdTokenEntity } from \"../cache/entities/IdTokenEntity.js\";\nimport { AccessTokenEntity } from \"../cache/entities/AccessTokenEntity.js\";\nimport { RefreshTokenEntity } from \"../cache/entities/RefreshTokenEntity.js\";\nimport {\n InteractionRequiredAuthError,\n isInteractionRequiredError,\n} from \"../error/InteractionRequiredAuthError.js\";\nimport { CacheRecord } from \"../cache/entities/CacheRecord.js\";\nimport { CacheManager } from \"../cache/CacheManager.js\";\nimport { ProtocolUtils, RequestStateObject } from \"../utils/ProtocolUtils.js\";\nimport {\n AuthenticationScheme,\n Constants,\n THE_FAMILY_ID,\n HttpStatus,\n} from \"../utils/Constants.js\";\nimport { PopTokenGenerator } from \"../crypto/PopTokenGenerator.js\";\nimport { AppMetadataEntity } from \"../cache/entities/AppMetadataEntity.js\";\nimport { ICachePlugin } from \"../cache/interface/ICachePlugin.js\";\nimport { TokenCacheContext } from \"../cache/persistence/TokenCacheContext.js\";\nimport { ISerializableTokenCache } from \"../cache/interface/ISerializableTokenCache.js\";\nimport { AuthorizationCodePayload } from \"./AuthorizationCodePayload.js\";\nimport { BaseAuthRequest } from \"../request/BaseAuthRequest.js\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\nimport { checkMaxAge, extractTokenClaims } from \"../account/AuthToken.js\";\nimport {\n TokenClaims,\n getTenantIdFromIdTokenClaims,\n} from \"../account/TokenClaims.js\";\nimport {\n AccountInfo,\n buildTenantProfile,\n updateAccountTenantProfileData,\n} from \"../account/AccountInfo.js\";\nimport * as CacheHelpers from \"../cache/utils/CacheHelpers.js\";\nimport * as TimeUtils from \"../utils/TimeUtils.js\";\n\n/**\n * Class that handles response parsing.\n * @internal\n */\nexport class ResponseHandler {\n private clientId: string;\n private cacheStorage: CacheManager;\n private cryptoObj: ICrypto;\n private logger: Logger;\n private homeAccountIdentifier: string;\n private serializableCache: ISerializableTokenCache | null;\n private persistencePlugin: ICachePlugin | null;\n private performanceClient?: IPerformanceClient;\n\n constructor(\n clientId: string,\n cacheStorage: CacheManager,\n cryptoObj: ICrypto,\n logger: Logger,\n serializableCache: ISerializableTokenCache | null,\n persistencePlugin: ICachePlugin | null,\n performanceClient?: IPerformanceClient\n ) {\n this.clientId = clientId;\n this.cacheStorage = cacheStorage;\n this.cryptoObj = cryptoObj;\n this.logger = logger;\n this.serializableCache = serializableCache;\n this.persistencePlugin = persistencePlugin;\n this.performanceClient = performanceClient;\n }\n\n /**\n * Function which validates server authorization token response.\n * @param serverResponse\n * @param refreshAccessToken\n */\n validateTokenResponse(\n serverResponse: ServerAuthorizationTokenResponse,\n refreshAccessToken?: boolean\n ): void {\n // Check for error\n if (\n serverResponse.error ||\n serverResponse.error_description ||\n serverResponse.suberror\n ) {\n const errString = `Error(s): ${\n serverResponse.error_codes || Constants.NOT_AVAILABLE\n } - Timestamp: ${\n serverResponse.timestamp || Constants.NOT_AVAILABLE\n } - Description: ${\n serverResponse.error_description || Constants.NOT_AVAILABLE\n } - Correlation ID: ${\n serverResponse.correlation_id || Constants.NOT_AVAILABLE\n } - Trace ID: ${\n serverResponse.trace_id || Constants.NOT_AVAILABLE\n }`;\n const serverErrorNo = serverResponse.error_codes?.length\n ? serverResponse.error_codes[0]\n : undefined;\n const serverError = new ServerError(\n serverResponse.error,\n errString,\n serverResponse.suberror,\n serverErrorNo,\n serverResponse.status\n );\n\n // check if 500 error\n if (\n refreshAccessToken &&\n serverResponse.status &&\n serverResponse.status >= HttpStatus.SERVER_ERROR_RANGE_START &&\n serverResponse.status <= HttpStatus.SERVER_ERROR_RANGE_END\n ) {\n this.logger.warning(\n `executeTokenRequest:validateTokenResponse - AAD is currently unavailable and the access token is unable to be refreshed.\\n${serverError}`\n );\n\n // don't throw an exception, but alert the user via a log that the token was unable to be refreshed\n return;\n // check if 400 error\n } else if (\n refreshAccessToken &&\n serverResponse.status &&\n serverResponse.status >= HttpStatus.CLIENT_ERROR_RANGE_START &&\n serverResponse.status <= HttpStatus.CLIENT_ERROR_RANGE_END\n ) {\n this.logger.warning(\n `executeTokenRequest:validateTokenResponse - AAD is currently available but is unable to refresh the access token.\\n${serverError}`\n );\n\n // don't throw an exception, but alert the user via a log that the token was unable to be refreshed\n return;\n }\n\n if (\n isInteractionRequiredError(\n serverResponse.error,\n serverResponse.error_description,\n serverResponse.suberror\n )\n ) {\n throw new InteractionRequiredAuthError(\n serverResponse.error,\n serverResponse.error_description,\n serverResponse.suberror,\n serverResponse.timestamp || Constants.EMPTY_STRING,\n serverResponse.trace_id || Constants.EMPTY_STRING,\n serverResponse.correlation_id || Constants.EMPTY_STRING,\n serverResponse.claims || Constants.EMPTY_STRING,\n serverErrorNo\n );\n }\n\n throw serverError;\n }\n }\n\n /**\n * Returns a constructed token response based on given string. Also manages the cache updates and cleanups.\n * @param serverTokenResponse\n * @param authority\n */\n async handleServerTokenResponse(\n serverTokenResponse: ServerAuthorizationTokenResponse,\n authority: Authority,\n reqTimestamp: number,\n request: BaseAuthRequest,\n authCodePayload?: AuthorizationCodePayload,\n userAssertionHash?: string,\n handlingRefreshTokenResponse?: boolean,\n forceCacheRefreshTokenResponse?: boolean,\n serverRequestId?: string\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.HandleServerTokenResponse,\n serverTokenResponse.correlation_id\n );\n\n // create an idToken object (not entity)\n let idTokenClaims: TokenClaims | undefined;\n if (serverTokenResponse.id_token) {\n idTokenClaims = extractTokenClaims(\n serverTokenResponse.id_token || Constants.EMPTY_STRING,\n this.cryptoObj.base64Decode\n );\n\n // token nonce check (TODO: Add a warning if no nonce is given?)\n if (authCodePayload && authCodePayload.nonce) {\n if (idTokenClaims.nonce !== authCodePayload.nonce) {\n throw createClientAuthError(\n ClientAuthErrorCodes.nonceMismatch\n );\n }\n }\n\n // token max_age check\n if (request.maxAge || request.maxAge === 0) {\n const authTime = idTokenClaims.auth_time;\n if (!authTime) {\n throw createClientAuthError(\n ClientAuthErrorCodes.authTimeNotFound\n );\n }\n\n checkMaxAge(authTime, request.maxAge);\n }\n }\n\n // generate homeAccountId\n this.homeAccountIdentifier = AccountEntity.generateHomeAccountId(\n serverTokenResponse.client_info || Constants.EMPTY_STRING,\n authority.authorityType,\n this.logger,\n this.cryptoObj,\n idTokenClaims\n );\n\n // save the response tokens\n let requestStateObj: RequestStateObject | undefined;\n if (!!authCodePayload && !!authCodePayload.state) {\n requestStateObj = ProtocolUtils.parseRequestState(\n this.cryptoObj,\n authCodePayload.state\n );\n }\n\n // Add keyId from request to serverTokenResponse if defined\n serverTokenResponse.key_id =\n serverTokenResponse.key_id || request.sshKid || undefined;\n\n const cacheRecord = this.generateCacheRecord(\n serverTokenResponse,\n authority,\n reqTimestamp,\n request,\n idTokenClaims,\n userAssertionHash,\n authCodePayload\n );\n let cacheContext;\n try {\n if (this.persistencePlugin && this.serializableCache) {\n this.logger.verbose(\n \"Persistence enabled, calling beforeCacheAccess\"\n );\n cacheContext = new TokenCacheContext(\n this.serializableCache,\n true\n );\n await this.persistencePlugin.beforeCacheAccess(cacheContext);\n }\n /*\n * When saving a refreshed tokens to the cache, it is expected that the account that was used is present in the cache.\n * If not present, we should return null, as it's the case that another application called removeAccount in between\n * the calls to getAllAccounts and acquireTokenSilent. We should not overwrite that removal, unless explicitly flagged by\n * the developer, as in the case of refresh token flow used in ADAL Node to MSAL Node migration.\n */\n if (\n handlingRefreshTokenResponse &&\n !forceCacheRefreshTokenResponse &&\n cacheRecord.account\n ) {\n const key = this.cacheStorage.generateAccountKey(\n cacheRecord.account.getAccountInfo()\n );\n const account = this.cacheStorage.getAccount(\n key,\n request.correlationId\n );\n if (!account) {\n this.logger.warning(\n \"Account used to refresh tokens not in persistence, refreshed tokens will not be stored in the cache\"\n );\n return await ResponseHandler.generateAuthenticationResult(\n this.cryptoObj,\n authority,\n cacheRecord,\n false,\n request,\n idTokenClaims,\n requestStateObj,\n undefined,\n serverRequestId\n );\n }\n }\n await this.cacheStorage.saveCacheRecord(\n cacheRecord,\n request.correlationId,\n request.storeInCache\n );\n } finally {\n if (\n this.persistencePlugin &&\n this.serializableCache &&\n cacheContext\n ) {\n this.logger.verbose(\n \"Persistence enabled, calling afterCacheAccess\"\n );\n await this.persistencePlugin.afterCacheAccess(cacheContext);\n }\n }\n\n return ResponseHandler.generateAuthenticationResult(\n this.cryptoObj,\n authority,\n cacheRecord,\n false,\n request,\n idTokenClaims,\n requestStateObj,\n serverTokenResponse,\n serverRequestId\n );\n }\n\n /**\n * Generates CacheRecord\n * @param serverTokenResponse\n * @param idTokenObj\n * @param authority\n */\n private generateCacheRecord(\n serverTokenResponse: ServerAuthorizationTokenResponse,\n authority: Authority,\n reqTimestamp: number,\n request: BaseAuthRequest,\n idTokenClaims?: TokenClaims,\n userAssertionHash?: string,\n authCodePayload?: AuthorizationCodePayload\n ): CacheRecord {\n const env = authority.getPreferredCache();\n if (!env) {\n throw createClientAuthError(\n ClientAuthErrorCodes.invalidCacheEnvironment\n );\n }\n\n const claimsTenantId = getTenantIdFromIdTokenClaims(idTokenClaims);\n\n // IdToken: non AAD scenarios can have empty realm\n let cachedIdToken: IdTokenEntity | undefined;\n let cachedAccount: AccountEntity | undefined;\n if (serverTokenResponse.id_token && !!idTokenClaims) {\n cachedIdToken = CacheHelpers.createIdTokenEntity(\n this.homeAccountIdentifier,\n env,\n serverTokenResponse.id_token,\n this.clientId,\n claimsTenantId || \"\"\n );\n\n cachedAccount = buildAccountToCache(\n this.cacheStorage,\n authority,\n this.homeAccountIdentifier,\n this.cryptoObj.base64Decode,\n request.correlationId,\n idTokenClaims,\n serverTokenResponse.client_info,\n env,\n claimsTenantId,\n authCodePayload,\n undefined, // nativeAccountId\n this.logger\n );\n }\n\n // AccessToken\n let cachedAccessToken: AccessTokenEntity | null = null;\n if (serverTokenResponse.access_token) {\n // If scopes not returned in server response, use request scopes\n const responseScopes = serverTokenResponse.scope\n ? ScopeSet.fromString(serverTokenResponse.scope)\n : new ScopeSet(request.scopes || []);\n\n /*\n * Use timestamp calculated before request\n * Server may return timestamps as strings, parse to numbers if so.\n */\n const expiresIn: number =\n (typeof serverTokenResponse.expires_in === \"string\"\n ? parseInt(serverTokenResponse.expires_in, 10)\n : serverTokenResponse.expires_in) || 0;\n const extExpiresIn: number =\n (typeof serverTokenResponse.ext_expires_in === \"string\"\n ? parseInt(serverTokenResponse.ext_expires_in, 10)\n : serverTokenResponse.ext_expires_in) || 0;\n const refreshIn: number | undefined =\n (typeof serverTokenResponse.refresh_in === \"string\"\n ? parseInt(serverTokenResponse.refresh_in, 10)\n : serverTokenResponse.refresh_in) || undefined;\n const tokenExpirationSeconds = reqTimestamp + expiresIn;\n const extendedTokenExpirationSeconds =\n tokenExpirationSeconds + extExpiresIn;\n const refreshOnSeconds =\n refreshIn && refreshIn > 0\n ? reqTimestamp + refreshIn\n : undefined;\n\n // non AAD scenarios can have empty realm\n cachedAccessToken = CacheHelpers.createAccessTokenEntity(\n this.homeAccountIdentifier,\n env,\n serverTokenResponse.access_token,\n this.clientId,\n claimsTenantId || authority.tenant || \"\",\n responseScopes.printScopes(),\n tokenExpirationSeconds,\n extendedTokenExpirationSeconds,\n this.cryptoObj.base64Decode,\n refreshOnSeconds,\n serverTokenResponse.token_type,\n userAssertionHash,\n serverTokenResponse.key_id,\n request.claims,\n request.requestedClaimsHash\n );\n }\n\n // refreshToken\n let cachedRefreshToken: RefreshTokenEntity | null = null;\n if (serverTokenResponse.refresh_token) {\n let rtExpiresOn: number | undefined;\n if (serverTokenResponse.refresh_token_expires_in) {\n const rtExpiresIn: number =\n typeof serverTokenResponse.refresh_token_expires_in ===\n \"string\"\n ? parseInt(\n serverTokenResponse.refresh_token_expires_in,\n 10\n )\n : serverTokenResponse.refresh_token_expires_in;\n rtExpiresOn = reqTimestamp + rtExpiresIn;\n }\n cachedRefreshToken = CacheHelpers.createRefreshTokenEntity(\n this.homeAccountIdentifier,\n env,\n serverTokenResponse.refresh_token,\n this.clientId,\n serverTokenResponse.foci,\n userAssertionHash,\n rtExpiresOn\n );\n }\n\n // appMetadata\n let cachedAppMetadata: AppMetadataEntity | null = null;\n if (serverTokenResponse.foci) {\n cachedAppMetadata = {\n clientId: this.clientId,\n environment: env,\n familyId: serverTokenResponse.foci,\n };\n }\n\n return {\n account: cachedAccount,\n idToken: cachedIdToken,\n accessToken: cachedAccessToken,\n refreshToken: cachedRefreshToken,\n appMetadata: cachedAppMetadata,\n };\n }\n\n /**\n * Creates an @AuthenticationResult from @CacheRecord , @IdToken , and a boolean that states whether or not the result is from cache.\n *\n * Optionally takes a state string that is set as-is in the response.\n *\n * @param cacheRecord\n * @param idTokenObj\n * @param fromTokenCache\n * @param stateString\n */\n static async generateAuthenticationResult(\n cryptoObj: ICrypto,\n authority: Authority,\n cacheRecord: CacheRecord,\n fromTokenCache: boolean,\n request: BaseAuthRequest,\n idTokenClaims?: TokenClaims,\n requestState?: RequestStateObject,\n serverTokenResponse?: ServerAuthorizationTokenResponse,\n requestId?: string\n ): Promise {\n let accessToken: string = Constants.EMPTY_STRING;\n let responseScopes: Array = [];\n let expiresOn: Date | null = null;\n let extExpiresOn: Date | undefined;\n let refreshOn: Date | undefined;\n let familyId: string = Constants.EMPTY_STRING;\n\n if (cacheRecord.accessToken) {\n /*\n * if the request object has `popKid` property, `signPopToken` will be set to false and\n * the token will be returned unsigned\n */\n if (\n cacheRecord.accessToken.tokenType ===\n AuthenticationScheme.POP &&\n !request.popKid\n ) {\n const popTokenGenerator: PopTokenGenerator =\n new PopTokenGenerator(cryptoObj);\n const { secret, keyId } = cacheRecord.accessToken;\n\n if (!keyId) {\n throw createClientAuthError(\n ClientAuthErrorCodes.keyIdMissing\n );\n }\n\n accessToken = await popTokenGenerator.signPopToken(\n secret,\n keyId,\n request\n );\n } else {\n accessToken = cacheRecord.accessToken.secret;\n }\n responseScopes = ScopeSet.fromString(\n cacheRecord.accessToken.target\n ).asArray();\n // Access token expiresOn cached in seconds, converting to Date for AuthenticationResult\n expiresOn = TimeUtils.toDateFromSeconds(\n cacheRecord.accessToken.expiresOn\n );\n extExpiresOn = TimeUtils.toDateFromSeconds(\n cacheRecord.accessToken.extendedExpiresOn\n );\n if (cacheRecord.accessToken.refreshOn) {\n refreshOn = TimeUtils.toDateFromSeconds(\n cacheRecord.accessToken.refreshOn\n );\n }\n }\n\n if (cacheRecord.appMetadata) {\n familyId =\n cacheRecord.appMetadata.familyId === THE_FAMILY_ID\n ? THE_FAMILY_ID\n : \"\";\n }\n const uid = idTokenClaims?.oid || idTokenClaims?.sub || \"\";\n const tid = idTokenClaims?.tid || \"\";\n\n // for hybrid + native bridge enablement, send back the native account Id\n if (serverTokenResponse?.spa_accountid && !!cacheRecord.account) {\n cacheRecord.account.nativeAccountId =\n serverTokenResponse?.spa_accountid;\n }\n\n const accountInfo: AccountInfo | null = cacheRecord.account\n ? updateAccountTenantProfileData(\n cacheRecord.account.getAccountInfo(),\n undefined, // tenantProfile optional\n idTokenClaims,\n cacheRecord.idToken?.secret\n )\n : null;\n\n return {\n authority: authority.canonicalAuthority,\n uniqueId: uid,\n tenantId: tid,\n scopes: responseScopes,\n account: accountInfo,\n idToken: cacheRecord?.idToken?.secret || \"\",\n idTokenClaims: idTokenClaims || {},\n accessToken: accessToken,\n fromCache: fromTokenCache,\n expiresOn: expiresOn,\n extExpiresOn: extExpiresOn,\n refreshOn: refreshOn,\n correlationId: request.correlationId,\n requestId: requestId || Constants.EMPTY_STRING,\n familyId: familyId,\n tokenType:\n cacheRecord.accessToken?.tokenType || Constants.EMPTY_STRING,\n state: requestState\n ? requestState.userRequestState\n : Constants.EMPTY_STRING,\n cloudGraphHostName:\n cacheRecord.account?.cloudGraphHostName ||\n Constants.EMPTY_STRING,\n msGraphHost:\n cacheRecord.account?.msGraphHost || Constants.EMPTY_STRING,\n code: serverTokenResponse?.spa_code,\n fromNativeBroker: false,\n };\n }\n}\n\nexport function buildAccountToCache(\n cacheStorage: CacheManager,\n authority: Authority,\n homeAccountId: string,\n base64Decode: (input: string) => string,\n correlationId: string,\n idTokenClaims?: TokenClaims,\n clientInfo?: string,\n environment?: string,\n claimsTenantId?: string | null,\n authCodePayload?: AuthorizationCodePayload,\n nativeAccountId?: string,\n logger?: Logger\n): AccountEntity {\n logger?.verbose(\"setCachedAccount called\");\n\n // Check if base account is already cached\n const accountKeys = cacheStorage.getAccountKeys();\n const baseAccountKey = accountKeys.find((accountKey: string) => {\n return accountKey.startsWith(homeAccountId);\n });\n\n let cachedAccount: AccountEntity | null = null;\n if (baseAccountKey) {\n cachedAccount = cacheStorage.getAccount(baseAccountKey, correlationId);\n }\n\n const baseAccount =\n cachedAccount ||\n AccountEntity.createAccount(\n {\n homeAccountId,\n idTokenClaims,\n clientInfo,\n environment,\n cloudGraphHostName: authCodePayload?.cloud_graph_host_name,\n msGraphHost: authCodePayload?.msgraph_host,\n nativeAccountId: nativeAccountId,\n },\n authority,\n base64Decode\n );\n\n const tenantProfiles = baseAccount.tenantProfiles || [];\n const tenantId = claimsTenantId || baseAccount.realm;\n if (\n tenantId &&\n !tenantProfiles.find((tenantProfile) => {\n return tenantProfile.tenantId === tenantId;\n })\n ) {\n const newTenantProfile = buildTenantProfile(\n homeAccountId,\n baseAccount.localAccountId,\n tenantId,\n idTokenClaims\n );\n tenantProfiles.push(newTenantProfile);\n }\n baseAccount.tenantProfiles = tenantProfiles;\n\n return baseAccount;\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ClientAssertionCallback,\n ClientAssertionConfig,\n} from \"../account/ClientCredentials.js\";\n\nexport async function getClientAssertion(\n clientAssertion: string | ClientAssertionCallback,\n clientId: string,\n tokenEndpoint?: string\n): Promise {\n if (typeof clientAssertion === \"string\") {\n return clientAssertion;\n } else {\n const config: ClientAssertionConfig = {\n clientId: clientId,\n tokenEndpoint: tokenEndpoint,\n };\n return clientAssertion(config);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { BaseClient } from \"./BaseClient.js\";\nimport { CommonAuthorizationCodeRequest } from \"../request/CommonAuthorizationCodeRequest.js\";\nimport { Authority } from \"../authority/Authority.js\";\nimport * as RequestParameterBuilder from \"../request/RequestParameterBuilder.js\";\nimport * as UrlUtils from \"../utils/UrlUtils.js\";\nimport {\n GrantType,\n AuthenticationScheme,\n Separators,\n HeaderNames,\n} from \"../utils/Constants.js\";\nimport * as AADServerParamKeys from \"../constants/AADServerParamKeys.js\";\nimport {\n ClientConfiguration,\n isOidcProtocolMode,\n} from \"../config/ClientConfiguration.js\";\nimport { ServerAuthorizationTokenResponse } from \"../response/ServerAuthorizationTokenResponse.js\";\nimport { NetworkResponse } from \"../network/NetworkResponse.js\";\nimport { ResponseHandler } from \"../response/ResponseHandler.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { StringUtils } from \"../utils/StringUtils.js\";\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n} from \"../error/ClientAuthError.js\";\nimport { UrlString } from \"../url/UrlString.js\";\nimport { CommonEndSessionRequest } from \"../request/CommonEndSessionRequest.js\";\nimport { PopTokenGenerator } from \"../crypto/PopTokenGenerator.js\";\nimport { AuthorizationCodePayload } from \"../response/AuthorizationCodePayload.js\";\nimport * as TimeUtils from \"../utils/TimeUtils.js\";\nimport {\n buildClientInfoFromHomeAccountId,\n buildClientInfo,\n} from \"../account/ClientInfo.js\";\nimport { CcsCredentialType, CcsCredential } from \"../account/CcsCredential.js\";\nimport {\n createClientConfigurationError,\n ClientConfigurationErrorCodes,\n} from \"../error/ClientConfigurationError.js\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\nimport { ClientAssertion } from \"../account/ClientCredentials.js\";\nimport { getClientAssertion } from \"../utils/ClientAssertionUtils.js\";\nimport { getRequestThumbprint } from \"../network/RequestThumbprint.js\";\n\n/**\n * Oauth2.0 Authorization Code client\n * @internal\n */\nexport class AuthorizationCodeClient extends BaseClient {\n // Flag to indicate if client is for hybrid spa auth code redemption\n protected includeRedirectUri: boolean = true;\n private oidcDefaultScopes;\n\n constructor(\n configuration: ClientConfiguration,\n performanceClient?: IPerformanceClient\n ) {\n super(configuration, performanceClient);\n this.oidcDefaultScopes =\n this.config.authOptions.authority.options.OIDCOptions?.defaultScopes;\n }\n\n /**\n * API to acquire a token in exchange of 'authorization_code` acquired by the user in the first leg of the\n * authorization_code_grant\n * @param request\n */\n async acquireToken(\n request: CommonAuthorizationCodeRequest,\n authCodePayload?: AuthorizationCodePayload\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthClientAcquireToken,\n request.correlationId\n );\n\n if (!request.code) {\n throw createClientAuthError(\n ClientAuthErrorCodes.requestCannotBeMade\n );\n }\n\n const reqTimestamp = TimeUtils.nowSeconds();\n const response = await invokeAsync(\n this.executeTokenRequest.bind(this),\n PerformanceEvents.AuthClientExecuteTokenRequest,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(this.authority, request);\n\n // Retrieve requestId from response headers\n const requestId = response.headers?.[HeaderNames.X_MS_REQUEST_ID];\n\n const responseHandler = new ResponseHandler(\n this.config.authOptions.clientId,\n this.cacheManager,\n this.cryptoUtils,\n this.logger,\n this.config.serializableCache,\n this.config.persistencePlugin,\n this.performanceClient\n );\n\n // Validate response. This function throws a server error if an error is returned by the server.\n responseHandler.validateTokenResponse(response.body);\n\n return invokeAsync(\n responseHandler.handleServerTokenResponse.bind(responseHandler),\n PerformanceEvents.HandleServerTokenResponse,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(\n response.body,\n this.authority,\n reqTimestamp,\n request,\n authCodePayload,\n undefined,\n undefined,\n undefined,\n requestId\n );\n }\n\n /**\n * Used to log out the current user, and redirect the user to the postLogoutRedirectUri.\n * Default behaviour is to redirect the user to `window.location.href`.\n * @param authorityUri\n */\n getLogoutUri(logoutRequest: CommonEndSessionRequest): string {\n // Throw error if logoutRequest is null/undefined\n if (!logoutRequest) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.logoutRequestEmpty\n );\n }\n const queryString = this.createLogoutUrlQueryString(logoutRequest);\n\n // Construct logout URI\n return UrlString.appendQueryString(\n this.authority.endSessionEndpoint,\n queryString\n );\n }\n\n /**\n * Executes POST request to token endpoint\n * @param authority\n * @param request\n */\n private async executeTokenRequest(\n authority: Authority,\n request: CommonAuthorizationCodeRequest\n ): Promise> {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthClientExecuteTokenRequest,\n request.correlationId\n );\n\n const queryParametersString = this.createTokenQueryParameters(request);\n const endpoint = UrlString.appendQueryString(\n authority.tokenEndpoint,\n queryParametersString\n );\n\n const requestBody = await invokeAsync(\n this.createTokenRequestBody.bind(this),\n PerformanceEvents.AuthClientCreateTokenRequestBody,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request);\n\n let ccsCredential: CcsCredential | undefined = undefined;\n if (request.clientInfo) {\n try {\n const clientInfo = buildClientInfo(\n request.clientInfo,\n this.cryptoUtils.base64Decode\n );\n ccsCredential = {\n credential: `${clientInfo.uid}${Separators.CLIENT_INFO_SEPARATOR}${clientInfo.utid}`,\n type: CcsCredentialType.HOME_ACCOUNT_ID,\n };\n } catch (e) {\n this.logger.verbose(\n \"Could not parse client info for CCS Header: \" + e\n );\n }\n }\n const headers: Record = this.createTokenRequestHeaders(\n ccsCredential || request.ccsCredential\n );\n\n const thumbprint = getRequestThumbprint(\n this.config.authOptions.clientId,\n request\n );\n\n return invokeAsync(\n this.executePostToTokenEndpoint.bind(this),\n PerformanceEvents.AuthorizationCodeClientExecutePostToTokenEndpoint,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(\n endpoint,\n requestBody,\n headers,\n thumbprint,\n request.correlationId,\n PerformanceEvents.AuthorizationCodeClientExecutePostToTokenEndpoint\n );\n }\n\n /**\n * Generates a map for all the params to be sent to the service\n * @param request\n */\n private async createTokenRequestBody(\n request: CommonAuthorizationCodeRequest\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.AuthClientCreateTokenRequestBody,\n request.correlationId\n );\n\n const parameters = new Map();\n\n RequestParameterBuilder.addClientId(\n parameters,\n request.embeddedClientId ||\n request.tokenBodyParameters?.[AADServerParamKeys.CLIENT_ID] ||\n this.config.authOptions.clientId\n );\n\n /*\n * For hybrid spa flow, there will be a code but no verifier\n * In this scenario, don't include redirect uri as auth code will not be bound to redirect URI\n */\n if (!this.includeRedirectUri) {\n // Just validate\n if (!request.redirectUri) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.redirectUriEmpty\n );\n }\n } else {\n // Validate and include redirect uri\n RequestParameterBuilder.addRedirectUri(\n parameters,\n request.redirectUri\n );\n }\n\n // Add scope array, parameter builder will add default scopes and dedupe\n RequestParameterBuilder.addScopes(\n parameters,\n request.scopes,\n true,\n this.oidcDefaultScopes\n );\n\n // add code: user set, not validated\n RequestParameterBuilder.addAuthorizationCode(parameters, request.code);\n\n // Add library metadata\n RequestParameterBuilder.addLibraryInfo(\n parameters,\n this.config.libraryInfo\n );\n RequestParameterBuilder.addApplicationTelemetry(\n parameters,\n this.config.telemetry.application\n );\n RequestParameterBuilder.addThrottling(parameters);\n\n if (this.serverTelemetryManager && !isOidcProtocolMode(this.config)) {\n RequestParameterBuilder.addServerTelemetry(\n parameters,\n this.serverTelemetryManager\n );\n }\n\n // add code_verifier if passed\n if (request.codeVerifier) {\n RequestParameterBuilder.addCodeVerifier(\n parameters,\n request.codeVerifier\n );\n }\n\n if (this.config.clientCredentials.clientSecret) {\n RequestParameterBuilder.addClientSecret(\n parameters,\n this.config.clientCredentials.clientSecret\n );\n }\n\n if (this.config.clientCredentials.clientAssertion) {\n const clientAssertion: ClientAssertion =\n this.config.clientCredentials.clientAssertion;\n\n RequestParameterBuilder.addClientAssertion(\n parameters,\n await getClientAssertion(\n clientAssertion.assertion,\n this.config.authOptions.clientId,\n request.resourceRequestUri\n )\n );\n RequestParameterBuilder.addClientAssertionType(\n parameters,\n clientAssertion.assertionType\n );\n }\n\n RequestParameterBuilder.addGrantType(\n parameters,\n GrantType.AUTHORIZATION_CODE_GRANT\n );\n RequestParameterBuilder.addClientInfo(parameters);\n\n if (request.authenticationScheme === AuthenticationScheme.POP) {\n const popTokenGenerator = new PopTokenGenerator(\n this.cryptoUtils,\n this.performanceClient\n );\n\n let reqCnfData;\n if (!request.popKid) {\n const generatedReqCnfData = await invokeAsync(\n popTokenGenerator.generateCnf.bind(popTokenGenerator),\n PerformanceEvents.PopTokenGenerateCnf,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request, this.logger);\n reqCnfData = generatedReqCnfData.reqCnfString;\n } else {\n reqCnfData = this.cryptoUtils.encodeKid(request.popKid);\n }\n\n // SPA PoP requires full Base64Url encoded req_cnf string (unhashed)\n RequestParameterBuilder.addPopToken(parameters, reqCnfData);\n } else if (request.authenticationScheme === AuthenticationScheme.SSH) {\n if (request.sshJwk) {\n RequestParameterBuilder.addSshJwk(parameters, request.sshJwk);\n } else {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.missingSshJwk\n );\n }\n }\n\n if (\n !StringUtils.isEmptyObj(request.claims) ||\n (this.config.authOptions.clientCapabilities &&\n this.config.authOptions.clientCapabilities.length > 0)\n ) {\n RequestParameterBuilder.addClaims(\n parameters,\n request.claims,\n this.config.authOptions.clientCapabilities\n );\n }\n\n let ccsCred: CcsCredential | undefined = undefined;\n if (request.clientInfo) {\n try {\n const clientInfo = buildClientInfo(\n request.clientInfo,\n this.cryptoUtils.base64Decode\n );\n ccsCred = {\n credential: `${clientInfo.uid}${Separators.CLIENT_INFO_SEPARATOR}${clientInfo.utid}`,\n type: CcsCredentialType.HOME_ACCOUNT_ID,\n };\n } catch (e) {\n this.logger.verbose(\n \"Could not parse client info for CCS Header: \" + e\n );\n }\n } else {\n ccsCred = request.ccsCredential;\n }\n\n // Adds these as parameters in the request instead of headers to prevent CORS preflight request\n if (this.config.systemOptions.preventCorsPreflight && ccsCred) {\n switch (ccsCred.type) {\n case CcsCredentialType.HOME_ACCOUNT_ID:\n try {\n const clientInfo = buildClientInfoFromHomeAccountId(\n ccsCred.credential\n );\n RequestParameterBuilder.addCcsOid(\n parameters,\n clientInfo\n );\n } catch (e) {\n this.logger.verbose(\n \"Could not parse home account ID for CCS Header: \" +\n e\n );\n }\n break;\n case CcsCredentialType.UPN:\n RequestParameterBuilder.addCcsUpn(\n parameters,\n ccsCred.credential\n );\n break;\n }\n }\n\n if (request.embeddedClientId) {\n RequestParameterBuilder.addBrokerParameters(\n parameters,\n this.config.authOptions.clientId,\n this.config.authOptions.redirectUri\n );\n }\n\n if (request.tokenBodyParameters) {\n RequestParameterBuilder.addExtraQueryParameters(\n parameters,\n request.tokenBodyParameters\n );\n }\n\n // Add hybrid spa parameters if not already provided\n if (\n request.enableSpaAuthorizationCode &&\n (!request.tokenBodyParameters ||\n !request.tokenBodyParameters[\n AADServerParamKeys.RETURN_SPA_CODE\n ])\n ) {\n RequestParameterBuilder.addExtraQueryParameters(parameters, {\n [AADServerParamKeys.RETURN_SPA_CODE]: \"1\",\n });\n }\n\n RequestParameterBuilder.instrumentBrokerParams(\n parameters,\n request.correlationId,\n this.performanceClient\n );\n return UrlUtils.mapToQueryString(parameters);\n }\n\n /**\n * This API validates the `EndSessionRequest` and creates a URL\n * @param request\n */\n private createLogoutUrlQueryString(\n request: CommonEndSessionRequest\n ): string {\n const parameters = new Map();\n\n if (request.postLogoutRedirectUri) {\n RequestParameterBuilder.addPostLogoutRedirectUri(\n parameters,\n request.postLogoutRedirectUri\n );\n }\n\n if (request.correlationId) {\n RequestParameterBuilder.addCorrelationId(\n parameters,\n request.correlationId\n );\n }\n\n if (request.idTokenHint) {\n RequestParameterBuilder.addIdTokenHint(\n parameters,\n request.idTokenHint\n );\n }\n\n if (request.state) {\n RequestParameterBuilder.addState(parameters, request.state);\n }\n\n if (request.logoutHint) {\n RequestParameterBuilder.addLogoutHint(\n parameters,\n request.logoutHint\n );\n }\n\n if (request.extraQueryParameters) {\n RequestParameterBuilder.addExtraQueryParameters(\n parameters,\n request.extraQueryParameters\n );\n }\n\n if (this.config.authOptions.instanceAware) {\n RequestParameterBuilder.addInstanceAware(parameters);\n }\n\n return UrlUtils.mapToQueryString(\n parameters,\n this.config.authOptions.encodeExtraQueryParams,\n request.extraQueryParameters\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ClientConfiguration,\n isOidcProtocolMode,\n} from \"../config/ClientConfiguration.js\";\nimport { BaseClient } from \"./BaseClient.js\";\nimport { CommonRefreshTokenRequest } from \"../request/CommonRefreshTokenRequest.js\";\nimport { Authority } from \"../authority/Authority.js\";\nimport { ServerAuthorizationTokenResponse } from \"../response/ServerAuthorizationTokenResponse.js\";\nimport * as RequestParameterBuilder from \"../request/RequestParameterBuilder.js\";\nimport * as UrlUtils from \"../utils/UrlUtils.js\";\nimport {\n GrantType,\n AuthenticationScheme,\n Errors,\n HeaderNames,\n} from \"../utils/Constants.js\";\nimport * as AADServerParamKeys from \"../constants/AADServerParamKeys.js\";\nimport { ResponseHandler } from \"../response/ResponseHandler.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { PopTokenGenerator } from \"../crypto/PopTokenGenerator.js\";\nimport { StringUtils } from \"../utils/StringUtils.js\";\nimport { NetworkResponse } from \"../network/NetworkResponse.js\";\nimport { CommonSilentFlowRequest } from \"../request/CommonSilentFlowRequest.js\";\nimport {\n createClientConfigurationError,\n ClientConfigurationErrorCodes,\n} from \"../error/ClientConfigurationError.js\";\nimport {\n createClientAuthError,\n ClientAuthErrorCodes,\n} from \"../error/ClientAuthError.js\";\nimport { ServerError } from \"../error/ServerError.js\";\nimport * as TimeUtils from \"../utils/TimeUtils.js\";\nimport { UrlString } from \"../url/UrlString.js\";\nimport { CcsCredentialType } from \"../account/CcsCredential.js\";\nimport { buildClientInfoFromHomeAccountId } from \"../account/ClientInfo.js\";\nimport {\n InteractionRequiredAuthError,\n InteractionRequiredAuthErrorCodes,\n createInteractionRequiredAuthError,\n} from \"../error/InteractionRequiredAuthError.js\";\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\nimport { invoke, invokeAsync } from \"../utils/FunctionWrappers.js\";\nimport { ClientAssertion } from \"../account/ClientCredentials.js\";\nimport { getClientAssertion } from \"../utils/ClientAssertionUtils.js\";\nimport { getRequestThumbprint } from \"../network/RequestThumbprint.js\";\n\nconst DEFAULT_REFRESH_TOKEN_EXPIRATION_OFFSET_SECONDS = 300; // 5 Minutes\n\n/**\n * OAuth2.0 refresh token client\n * @internal\n */\nexport class RefreshTokenClient extends BaseClient {\n constructor(\n configuration: ClientConfiguration,\n performanceClient?: IPerformanceClient\n ) {\n super(configuration, performanceClient);\n }\n public async acquireToken(\n request: CommonRefreshTokenRequest\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.RefreshTokenClientAcquireToken,\n request.correlationId\n );\n\n const reqTimestamp = TimeUtils.nowSeconds();\n const response = await invokeAsync(\n this.executeTokenRequest.bind(this),\n PerformanceEvents.RefreshTokenClientExecuteTokenRequest,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request, this.authority);\n\n // Retrieve requestId from response headers\n const requestId = response.headers?.[HeaderNames.X_MS_REQUEST_ID];\n const responseHandler = new ResponseHandler(\n this.config.authOptions.clientId,\n this.cacheManager,\n this.cryptoUtils,\n this.logger,\n this.config.serializableCache,\n this.config.persistencePlugin\n );\n responseHandler.validateTokenResponse(response.body);\n\n return invokeAsync(\n responseHandler.handleServerTokenResponse.bind(responseHandler),\n PerformanceEvents.HandleServerTokenResponse,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(\n response.body,\n this.authority,\n reqTimestamp,\n request,\n undefined,\n undefined,\n true,\n request.forceCache,\n requestId\n );\n }\n\n /**\n * Gets cached refresh token and attaches to request, then calls acquireToken API\n * @param request\n */\n public async acquireTokenByRefreshToken(\n request: CommonSilentFlowRequest\n ): Promise {\n // Cannot renew token if no request object is given.\n if (!request) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.tokenRequestEmpty\n );\n }\n\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.RefreshTokenClientAcquireTokenByRefreshToken,\n request.correlationId\n );\n\n // We currently do not support silent flow for account === null use cases; This will be revisited for confidential flow usecases\n if (!request.account) {\n throw createClientAuthError(\n ClientAuthErrorCodes.noAccountInSilentRequest\n );\n }\n\n // try checking if FOCI is enabled for the given application\n const isFOCI = this.cacheManager.isAppMetadataFOCI(\n request.account.environment\n );\n\n // if the app is part of the family, retrive a Family refresh token if present and make a refreshTokenRequest\n if (isFOCI) {\n try {\n return await invokeAsync(\n this.acquireTokenWithCachedRefreshToken.bind(this),\n PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request, true);\n } catch (e) {\n const noFamilyRTInCache =\n e instanceof InteractionRequiredAuthError &&\n e.errorCode ===\n InteractionRequiredAuthErrorCodes.noTokensFound;\n const clientMismatchErrorWithFamilyRT =\n e instanceof ServerError &&\n e.errorCode === Errors.INVALID_GRANT_ERROR &&\n e.subError === Errors.CLIENT_MISMATCH_ERROR;\n\n // if family Refresh Token (FRT) cache acquisition fails or if client_mismatch error is seen with FRT, reattempt with application Refresh Token (ART)\n if (noFamilyRTInCache || clientMismatchErrorWithFamilyRT) {\n return invokeAsync(\n this.acquireTokenWithCachedRefreshToken.bind(this),\n PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request, false);\n // throw in all other cases\n } else {\n throw e;\n }\n }\n }\n // fall back to application refresh token acquisition\n return invokeAsync(\n this.acquireTokenWithCachedRefreshToken.bind(this),\n PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request, false);\n }\n\n /**\n * makes a network call to acquire tokens by exchanging RefreshToken available in userCache; throws if refresh token is not cached\n * @param request\n */\n private async acquireTokenWithCachedRefreshToken(\n request: CommonSilentFlowRequest,\n foci: boolean\n ) {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken,\n request.correlationId\n );\n\n // fetches family RT or application RT based on FOCI value\n const refreshToken = invoke(\n this.cacheManager.getRefreshToken.bind(this.cacheManager),\n PerformanceEvents.CacheManagerGetRefreshToken,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(\n request.account,\n foci,\n request.correlationId,\n undefined,\n this.performanceClient\n );\n\n if (!refreshToken) {\n throw createInteractionRequiredAuthError(\n InteractionRequiredAuthErrorCodes.noTokensFound\n );\n }\n\n if (\n refreshToken.expiresOn &&\n TimeUtils.isTokenExpired(\n refreshToken.expiresOn,\n request.refreshTokenExpirationOffsetSeconds ||\n DEFAULT_REFRESH_TOKEN_EXPIRATION_OFFSET_SECONDS\n )\n ) {\n this.performanceClient?.addFields(\n { rtExpiresOnMs: Number(refreshToken.expiresOn) },\n request.correlationId\n );\n throw createInteractionRequiredAuthError(\n InteractionRequiredAuthErrorCodes.refreshTokenExpired\n );\n }\n // attach cached RT size to the current measurement\n\n const refreshTokenRequest: CommonRefreshTokenRequest = {\n ...request,\n refreshToken: refreshToken.secret,\n authenticationScheme:\n request.authenticationScheme || AuthenticationScheme.BEARER,\n ccsCredential: {\n credential: request.account.homeAccountId,\n type: CcsCredentialType.HOME_ACCOUNT_ID,\n },\n };\n\n try {\n return await invokeAsync(\n this.acquireToken.bind(this),\n PerformanceEvents.RefreshTokenClientAcquireToken,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(refreshTokenRequest);\n } catch (e) {\n if (e instanceof InteractionRequiredAuthError) {\n this.performanceClient?.addFields(\n { rtExpiresOnMs: Number(refreshToken.expiresOn) },\n request.correlationId\n );\n\n if (e.subError === InteractionRequiredAuthErrorCodes.badToken) {\n // Remove bad refresh token from cache\n this.logger.verbose(\n \"acquireTokenWithRefreshToken: bad refresh token, removing from cache\"\n );\n const badRefreshTokenKey =\n this.cacheManager.generateCredentialKey(refreshToken);\n this.cacheManager.removeRefreshToken(\n badRefreshTokenKey,\n request.correlationId\n );\n }\n }\n\n throw e;\n }\n }\n\n /**\n * Constructs the network message and makes a NW call to the underlying secure token service\n * @param request\n * @param authority\n */\n private async executeTokenRequest(\n request: CommonRefreshTokenRequest,\n authority: Authority\n ): Promise> {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.RefreshTokenClientExecuteTokenRequest,\n request.correlationId\n );\n\n const queryParametersString = this.createTokenQueryParameters(request);\n const endpoint = UrlString.appendQueryString(\n authority.tokenEndpoint,\n queryParametersString\n );\n\n const requestBody = await invokeAsync(\n this.createTokenRequestBody.bind(this),\n PerformanceEvents.RefreshTokenClientCreateTokenRequestBody,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request);\n const headers: Record = this.createTokenRequestHeaders(\n request.ccsCredential\n );\n\n const thumbprint = getRequestThumbprint(\n this.config.authOptions.clientId,\n request\n );\n\n return invokeAsync(\n this.executePostToTokenEndpoint.bind(this),\n PerformanceEvents.RefreshTokenClientExecutePostToTokenEndpoint,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(\n endpoint,\n requestBody,\n headers,\n thumbprint,\n request.correlationId,\n PerformanceEvents.RefreshTokenClientExecutePostToTokenEndpoint\n );\n }\n\n /**\n * Helper function to create the token request body\n * @param request\n */\n private async createTokenRequestBody(\n request: CommonRefreshTokenRequest\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.RefreshTokenClientCreateTokenRequestBody,\n request.correlationId\n );\n\n const parameters = new Map();\n\n RequestParameterBuilder.addClientId(\n parameters,\n request.embeddedClientId ||\n request.tokenBodyParameters?.[AADServerParamKeys.CLIENT_ID] ||\n this.config.authOptions.clientId\n );\n\n if (request.redirectUri) {\n RequestParameterBuilder.addRedirectUri(\n parameters,\n request.redirectUri\n );\n }\n\n RequestParameterBuilder.addScopes(\n parameters,\n request.scopes,\n true,\n this.config.authOptions.authority.options.OIDCOptions?.defaultScopes\n );\n\n RequestParameterBuilder.addGrantType(\n parameters,\n GrantType.REFRESH_TOKEN_GRANT\n );\n\n RequestParameterBuilder.addClientInfo(parameters);\n\n RequestParameterBuilder.addLibraryInfo(\n parameters,\n this.config.libraryInfo\n );\n RequestParameterBuilder.addApplicationTelemetry(\n parameters,\n this.config.telemetry.application\n );\n RequestParameterBuilder.addThrottling(parameters);\n\n if (this.serverTelemetryManager && !isOidcProtocolMode(this.config)) {\n RequestParameterBuilder.addServerTelemetry(\n parameters,\n this.serverTelemetryManager\n );\n }\n\n RequestParameterBuilder.addRefreshToken(\n parameters,\n request.refreshToken\n );\n\n if (this.config.clientCredentials.clientSecret) {\n RequestParameterBuilder.addClientSecret(\n parameters,\n this.config.clientCredentials.clientSecret\n );\n }\n\n if (this.config.clientCredentials.clientAssertion) {\n const clientAssertion: ClientAssertion =\n this.config.clientCredentials.clientAssertion;\n\n RequestParameterBuilder.addClientAssertion(\n parameters,\n await getClientAssertion(\n clientAssertion.assertion,\n this.config.authOptions.clientId,\n request.resourceRequestUri\n )\n );\n RequestParameterBuilder.addClientAssertionType(\n parameters,\n clientAssertion.assertionType\n );\n }\n\n if (request.authenticationScheme === AuthenticationScheme.POP) {\n const popTokenGenerator = new PopTokenGenerator(\n this.cryptoUtils,\n this.performanceClient\n );\n\n let reqCnfData;\n if (!request.popKid) {\n const generatedReqCnfData = await invokeAsync(\n popTokenGenerator.generateCnf.bind(popTokenGenerator),\n PerformanceEvents.PopTokenGenerateCnf,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request, this.logger);\n\n reqCnfData = generatedReqCnfData.reqCnfString;\n } else {\n reqCnfData = this.cryptoUtils.encodeKid(request.popKid);\n }\n\n // SPA PoP requires full Base64Url encoded req_cnf string (unhashed)\n RequestParameterBuilder.addPopToken(parameters, reqCnfData);\n } else if (request.authenticationScheme === AuthenticationScheme.SSH) {\n if (request.sshJwk) {\n RequestParameterBuilder.addSshJwk(parameters, request.sshJwk);\n } else {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.missingSshJwk\n );\n }\n }\n\n if (\n !StringUtils.isEmptyObj(request.claims) ||\n (this.config.authOptions.clientCapabilities &&\n this.config.authOptions.clientCapabilities.length > 0)\n ) {\n RequestParameterBuilder.addClaims(\n parameters,\n request.claims,\n this.config.authOptions.clientCapabilities\n );\n }\n\n if (\n this.config.systemOptions.preventCorsPreflight &&\n request.ccsCredential\n ) {\n switch (request.ccsCredential.type) {\n case CcsCredentialType.HOME_ACCOUNT_ID:\n try {\n const clientInfo = buildClientInfoFromHomeAccountId(\n request.ccsCredential.credential\n );\n RequestParameterBuilder.addCcsOid(\n parameters,\n clientInfo\n );\n } catch (e) {\n this.logger.verbose(\n \"Could not parse home account ID for CCS Header: \" +\n e\n );\n }\n break;\n case CcsCredentialType.UPN:\n RequestParameterBuilder.addCcsUpn(\n parameters,\n request.ccsCredential.credential\n );\n break;\n }\n }\n\n if (request.embeddedClientId) {\n RequestParameterBuilder.addBrokerParameters(\n parameters,\n this.config.authOptions.clientId,\n this.config.authOptions.redirectUri\n );\n }\n\n if (request.tokenBodyParameters) {\n RequestParameterBuilder.addExtraQueryParameters(\n parameters,\n request.tokenBodyParameters\n );\n }\n\n RequestParameterBuilder.instrumentBrokerParams(\n parameters,\n request.correlationId,\n this.performanceClient\n );\n return UrlUtils.mapToQueryString(parameters);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { BaseClient } from \"./BaseClient.js\";\nimport { ClientConfiguration } from \"../config/ClientConfiguration.js\";\nimport { CommonSilentFlowRequest } from \"../request/CommonSilentFlowRequest.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport * as TimeUtils from \"../utils/TimeUtils.js\";\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n} from \"../error/ClientAuthError.js\";\nimport { ResponseHandler } from \"../response/ResponseHandler.js\";\nimport { CacheRecord } from \"../cache/entities/CacheRecord.js\";\nimport { CacheOutcome } from \"../utils/Constants.js\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\nimport { StringUtils } from \"../utils/StringUtils.js\";\nimport { checkMaxAge, extractTokenClaims } from \"../account/AuthToken.js\";\nimport { TokenClaims } from \"../account/TokenClaims.js\";\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\nimport { getTenantFromAuthorityString } from \"../authority/Authority.js\";\n\n/** @internal */\nexport class SilentFlowClient extends BaseClient {\n constructor(\n configuration: ClientConfiguration,\n performanceClient?: IPerformanceClient\n ) {\n super(configuration, performanceClient);\n }\n\n /**\n * Retrieves token from cache or throws an error if it must be refreshed.\n * @param request\n */\n async acquireCachedToken(\n request: CommonSilentFlowRequest\n ): Promise<[AuthenticationResult, CacheOutcome]> {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.SilentFlowClientAcquireCachedToken,\n request.correlationId\n );\n let lastCacheOutcome: CacheOutcome = CacheOutcome.NOT_APPLICABLE;\n\n if (\n request.forceRefresh ||\n (!this.config.cacheOptions.claimsBasedCachingEnabled &&\n !StringUtils.isEmptyObj(request.claims))\n ) {\n // Must refresh due to present force_refresh flag.\n this.setCacheOutcome(\n CacheOutcome.FORCE_REFRESH_OR_CLAIMS,\n request.correlationId\n );\n throw createClientAuthError(\n ClientAuthErrorCodes.tokenRefreshRequired\n );\n }\n\n // We currently do not support silent flow for account === null use cases; This will be revisited for confidential flow usecases\n if (!request.account) {\n throw createClientAuthError(\n ClientAuthErrorCodes.noAccountInSilentRequest\n );\n }\n\n const requestTenantId =\n request.account.tenantId ||\n getTenantFromAuthorityString(request.authority);\n const tokenKeys = this.cacheManager.getTokenKeys();\n const cachedAccessToken = this.cacheManager.getAccessToken(\n request.account,\n request,\n tokenKeys,\n requestTenantId\n );\n\n if (!cachedAccessToken) {\n // must refresh due to non-existent access_token\n this.setCacheOutcome(\n CacheOutcome.NO_CACHED_ACCESS_TOKEN,\n request.correlationId\n );\n throw createClientAuthError(\n ClientAuthErrorCodes.tokenRefreshRequired\n );\n } else if (\n TimeUtils.wasClockTurnedBack(cachedAccessToken.cachedAt) ||\n TimeUtils.isTokenExpired(\n cachedAccessToken.expiresOn,\n this.config.systemOptions.tokenRenewalOffsetSeconds\n )\n ) {\n // must refresh due to the expires_in value\n this.setCacheOutcome(\n CacheOutcome.CACHED_ACCESS_TOKEN_EXPIRED,\n request.correlationId\n );\n throw createClientAuthError(\n ClientAuthErrorCodes.tokenRefreshRequired\n );\n } else if (\n cachedAccessToken.refreshOn &&\n TimeUtils.isTokenExpired(cachedAccessToken.refreshOn, 0)\n ) {\n // must refresh (in the background) due to the refresh_in value\n lastCacheOutcome = CacheOutcome.PROACTIVELY_REFRESHED;\n\n // don't throw ClientAuthError.createRefreshRequiredError(), return cached token instead\n }\n\n const environment =\n request.authority || this.authority.getPreferredCache();\n const cacheRecord: CacheRecord = {\n account: this.cacheManager.getAccount(\n this.cacheManager.generateAccountKey(request.account),\n request.correlationId\n ),\n accessToken: cachedAccessToken,\n idToken: this.cacheManager.getIdToken(\n request.account,\n request.correlationId,\n tokenKeys,\n requestTenantId,\n this.performanceClient\n ),\n refreshToken: null,\n appMetadata:\n this.cacheManager.readAppMetadataFromCache(environment),\n };\n\n this.setCacheOutcome(lastCacheOutcome, request.correlationId);\n\n if (this.config.serverTelemetryManager) {\n this.config.serverTelemetryManager.incrementCacheHits();\n }\n\n return [\n await invokeAsync(\n this.generateResultFromCacheRecord.bind(this),\n PerformanceEvents.SilentFlowClientGenerateResultFromCacheRecord,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(cacheRecord, request),\n lastCacheOutcome,\n ];\n }\n\n private setCacheOutcome(\n cacheOutcome: CacheOutcome,\n correlationId: string\n ): void {\n this.serverTelemetryManager?.setCacheOutcome(cacheOutcome);\n this.performanceClient?.addFields(\n {\n cacheOutcome: cacheOutcome,\n },\n correlationId\n );\n if (cacheOutcome !== CacheOutcome.NOT_APPLICABLE) {\n this.logger.info(\n `Token refresh is required due to cache outcome: ${cacheOutcome}`\n );\n }\n }\n\n /**\n * Helper function to build response object from the CacheRecord\n * @param cacheRecord\n */\n private async generateResultFromCacheRecord(\n cacheRecord: CacheRecord,\n request: CommonSilentFlowRequest\n ): Promise {\n this.performanceClient?.addQueueMeasurement(\n PerformanceEvents.SilentFlowClientGenerateResultFromCacheRecord,\n request.correlationId\n );\n let idTokenClaims: TokenClaims | undefined;\n if (cacheRecord.idToken) {\n idTokenClaims = extractTokenClaims(\n cacheRecord.idToken.secret,\n this.config.cryptoInterface.base64Decode\n );\n }\n\n // token max_age check\n if (request.maxAge || request.maxAge === 0) {\n const authTime = idTokenClaims?.auth_time;\n if (!authTime) {\n throw createClientAuthError(\n ClientAuthErrorCodes.authTimeNotFound\n );\n }\n\n checkMaxAge(authTime, request.maxAge);\n }\n\n return ResponseHandler.generateAuthenticationResult(\n this.cryptoUtils,\n this.authority,\n cacheRecord,\n true,\n request,\n idTokenClaims\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n} from \"../error/ClientAuthError.js\";\nimport { NetworkResponse } from \"./NetworkResponse.js\";\n\n/**\n * Options allowed by network request APIs.\n */\nexport type NetworkRequestOptions = {\n headers?: Record;\n body?: string;\n};\n\n/**\n * Client network interface to send backend requests.\n * @interface\n */\nexport interface INetworkModule {\n /**\n * Interface function for async network \"GET\" requests. Based on the Fetch standard: https://fetch.spec.whatwg.org/\n * @param url\n * @param requestParams\n * @param enableCaching\n */\n sendGetRequestAsync(\n url: string,\n options?: NetworkRequestOptions,\n timeout?: number\n ): Promise>;\n\n /**\n * Interface function for async network \"POST\" requests. Based on the Fetch standard: https://fetch.spec.whatwg.org/\n * @param url\n * @param requestParams\n * @param enableCaching\n */\n sendPostRequestAsync(\n url: string,\n options?: NetworkRequestOptions\n ): Promise>;\n}\n\nexport const StubbedNetworkModule: INetworkModule = {\n sendGetRequestAsync: () => {\n return Promise.reject(\n createClientAuthError(ClientAuthErrorCodes.methodNotImplemented)\n );\n },\n sendPostRequestAsync: () => {\n return Promise.reject(\n createClientAuthError(ClientAuthErrorCodes.methodNotImplemented)\n );\n },\n};\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { CommonAuthorizationUrlRequest } from \"../request/CommonAuthorizationUrlRequest.js\";\nimport * as RequestParameterBuilder from \"../request/RequestParameterBuilder.js\";\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\nimport * as AADServerParamKeys from \"../constants/AADServerParamKeys.js\";\nimport { AuthOptions } from \"../config/ClientConfiguration.js\";\nimport { PromptValue } from \"../utils/Constants.js\";\nimport { AccountInfo } from \"../account/AccountInfo.js\";\nimport { Logger } from \"../logger/Logger.js\";\nimport { buildClientInfoFromHomeAccountId } from \"../account/ClientInfo.js\";\nimport { Authority } from \"../authority/Authority.js\";\nimport { mapToQueryString } from \"../utils/UrlUtils.js\";\nimport { UrlString } from \"../url/UrlString.js\";\nimport { AuthorizationCodePayload } from \"../response/AuthorizationCodePayload.js\";\nimport { AuthorizeResponse } from \"../response/AuthorizeResponse.js\";\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n} from \"../error/ClientAuthError.js\";\nimport {\n InteractionRequiredAuthError,\n isInteractionRequiredError,\n} from \"../error/InteractionRequiredAuthError.js\";\nimport { ServerError } from \"../error/ServerError.js\";\nimport { StringDict } from \"../utils/MsalTypes.js\";\n\n/**\n * Returns map of parameters that are applicable to all calls to /authorize whether using PKCE or EAR\n * @param config\n * @param request\n * @param logger\n * @param performanceClient\n * @returns\n */\nexport function getStandardAuthorizeRequestParameters(\n authOptions: AuthOptions,\n request: CommonAuthorizationUrlRequest,\n logger: Logger,\n performanceClient?: IPerformanceClient\n): Map {\n // generate the correlationId if not set by the user and add\n const correlationId = request.correlationId;\n\n const parameters = new Map();\n\n RequestParameterBuilder.addClientId(\n parameters,\n request.embeddedClientId ||\n request.extraQueryParameters?.[AADServerParamKeys.CLIENT_ID] ||\n authOptions.clientId\n );\n\n const requestScopes = [\n ...(request.scopes || []),\n ...(request.extraScopesToConsent || []),\n ];\n RequestParameterBuilder.addScopes(\n parameters,\n requestScopes,\n true,\n authOptions.authority.options.OIDCOptions?.defaultScopes\n );\n\n RequestParameterBuilder.addRedirectUri(parameters, request.redirectUri);\n\n RequestParameterBuilder.addCorrelationId(parameters, correlationId);\n\n // add response_mode. If not passed in it defaults to query.\n RequestParameterBuilder.addResponseMode(parameters, request.responseMode);\n\n // add client_info=1\n RequestParameterBuilder.addClientInfo(parameters);\n\n if (request.prompt) {\n RequestParameterBuilder.addPrompt(parameters, request.prompt);\n performanceClient?.addFields({ prompt: request.prompt }, correlationId);\n }\n\n if (request.domainHint) {\n RequestParameterBuilder.addDomainHint(parameters, request.domainHint);\n performanceClient?.addFields(\n { domainHintFromRequest: true },\n correlationId\n );\n }\n\n // Add sid or loginHint with preference for login_hint claim (in request) -> sid -> loginHint (upn/email) -> username of AccountInfo object\n if (request.prompt !== PromptValue.SELECT_ACCOUNT) {\n // AAD will throw if prompt=select_account is passed with an account hint\n if (request.sid && request.prompt === PromptValue.NONE) {\n // SessionID is only used in silent calls\n logger.verbose(\n \"createAuthCodeUrlQueryString: Prompt is none, adding sid from request\"\n );\n RequestParameterBuilder.addSid(parameters, request.sid);\n performanceClient?.addFields(\n { sidFromRequest: true },\n correlationId\n );\n } else if (request.account) {\n const accountSid = extractAccountSid(request.account);\n let accountLoginHintClaim = extractLoginHint(request.account);\n\n if (accountLoginHintClaim && request.domainHint) {\n logger.warning(\n `AuthorizationCodeClient.createAuthCodeUrlQueryString: \"domainHint\" param is set, skipping opaque \"login_hint\" claim. Please consider not passing domainHint`\n );\n accountLoginHintClaim = null;\n }\n\n // If login_hint claim is present, use it over sid/username\n if (accountLoginHintClaim) {\n logger.verbose(\n \"createAuthCodeUrlQueryString: login_hint claim present on account\"\n );\n RequestParameterBuilder.addLoginHint(\n parameters,\n accountLoginHintClaim\n );\n performanceClient?.addFields(\n { loginHintFromClaim: true },\n correlationId\n );\n try {\n const clientInfo = buildClientInfoFromHomeAccountId(\n request.account.homeAccountId\n );\n RequestParameterBuilder.addCcsOid(parameters, clientInfo);\n } catch (e) {\n logger.verbose(\n \"createAuthCodeUrlQueryString: Could not parse home account ID for CCS Header\"\n );\n }\n } else if (accountSid && request.prompt === PromptValue.NONE) {\n /*\n * If account and loginHint are provided, we will check account first for sid before adding loginHint\n * SessionId is only used in silent calls\n */\n logger.verbose(\n \"createAuthCodeUrlQueryString: Prompt is none, adding sid from account\"\n );\n RequestParameterBuilder.addSid(parameters, accountSid);\n performanceClient?.addFields(\n { sidFromClaim: true },\n correlationId\n );\n try {\n const clientInfo = buildClientInfoFromHomeAccountId(\n request.account.homeAccountId\n );\n RequestParameterBuilder.addCcsOid(parameters, clientInfo);\n } catch (e) {\n logger.verbose(\n \"createAuthCodeUrlQueryString: Could not parse home account ID for CCS Header\"\n );\n }\n } else if (request.loginHint) {\n logger.verbose(\n \"createAuthCodeUrlQueryString: Adding login_hint from request\"\n );\n RequestParameterBuilder.addLoginHint(\n parameters,\n request.loginHint\n );\n RequestParameterBuilder.addCcsUpn(\n parameters,\n request.loginHint\n );\n performanceClient?.addFields(\n { loginHintFromRequest: true },\n correlationId\n );\n } else if (request.account.username) {\n // Fallback to account username if provided\n logger.verbose(\n \"createAuthCodeUrlQueryString: Adding login_hint from account\"\n );\n RequestParameterBuilder.addLoginHint(\n parameters,\n request.account.username\n );\n performanceClient?.addFields(\n { loginHintFromUpn: true },\n correlationId\n );\n try {\n const clientInfo = buildClientInfoFromHomeAccountId(\n request.account.homeAccountId\n );\n RequestParameterBuilder.addCcsOid(parameters, clientInfo);\n } catch (e) {\n logger.verbose(\n \"createAuthCodeUrlQueryString: Could not parse home account ID for CCS Header\"\n );\n }\n }\n } else if (request.loginHint) {\n logger.verbose(\n \"createAuthCodeUrlQueryString: No account, adding login_hint from request\"\n );\n RequestParameterBuilder.addLoginHint(parameters, request.loginHint);\n RequestParameterBuilder.addCcsUpn(parameters, request.loginHint);\n performanceClient?.addFields(\n { loginHintFromRequest: true },\n correlationId\n );\n }\n } else {\n logger.verbose(\n \"createAuthCodeUrlQueryString: Prompt is select_account, ignoring account hints\"\n );\n }\n\n if (request.nonce) {\n RequestParameterBuilder.addNonce(parameters, request.nonce);\n }\n\n if (request.state) {\n RequestParameterBuilder.addState(parameters, request.state);\n }\n\n if (\n request.claims ||\n (authOptions.clientCapabilities &&\n authOptions.clientCapabilities.length > 0)\n ) {\n RequestParameterBuilder.addClaims(\n parameters,\n request.claims,\n authOptions.clientCapabilities\n );\n }\n\n if (request.embeddedClientId) {\n RequestParameterBuilder.addBrokerParameters(\n parameters,\n authOptions.clientId,\n authOptions.redirectUri\n );\n }\n\n // If extraQueryParameters includes instance_aware its value will be added when extraQueryParameters are added\n if (\n authOptions.instanceAware &&\n (!request.extraQueryParameters ||\n !Object.keys(request.extraQueryParameters).includes(\n AADServerParamKeys.INSTANCE_AWARE\n ))\n ) {\n RequestParameterBuilder.addInstanceAware(parameters);\n }\n\n return parameters;\n}\n\n/**\n * Returns authorize endpoint with given request parameters in the query string\n * @param authority\n * @param requestParameters\n * @returns\n */\nexport function getAuthorizeUrl(\n authority: Authority,\n requestParameters: Map,\n encodeParams?: boolean,\n extraQueryParameters?: StringDict | undefined\n): string {\n const queryString = mapToQueryString(\n requestParameters,\n encodeParams,\n extraQueryParameters\n );\n return UrlString.appendQueryString(\n authority.authorizationEndpoint,\n queryString\n );\n}\n\n/**\n * Handles the hash fragment response from public client code request. Returns a code response used by\n * the client to exchange for a token in acquireToken.\n * @param serverParams\n * @param cachedState\n */\nexport function getAuthorizationCodePayload(\n serverParams: AuthorizeResponse,\n cachedState: string\n): AuthorizationCodePayload {\n // Get code response\n validateAuthorizationResponse(serverParams, cachedState);\n\n // throw when there is no auth code in the response\n if (!serverParams.code) {\n throw createClientAuthError(\n ClientAuthErrorCodes.authorizationCodeMissingFromServerResponse\n );\n }\n\n return serverParams as AuthorizationCodePayload;\n}\n\n/**\n * Function which validates server authorization code response.\n * @param serverResponseHash\n * @param requestState\n */\nexport function validateAuthorizationResponse(\n serverResponse: AuthorizeResponse,\n requestState: string\n): void {\n if (!serverResponse.state || !requestState) {\n throw serverResponse.state\n ? createClientAuthError(\n ClientAuthErrorCodes.stateNotFound,\n \"Cached State\"\n )\n : createClientAuthError(\n ClientAuthErrorCodes.stateNotFound,\n \"Server State\"\n );\n }\n\n let decodedServerResponseState: string;\n let decodedRequestState: string;\n\n try {\n decodedServerResponseState = decodeURIComponent(serverResponse.state);\n } catch (e) {\n throw createClientAuthError(\n ClientAuthErrorCodes.invalidState,\n serverResponse.state\n );\n }\n\n try {\n decodedRequestState = decodeURIComponent(requestState);\n } catch (e) {\n throw createClientAuthError(\n ClientAuthErrorCodes.invalidState,\n serverResponse.state\n );\n }\n\n if (decodedServerResponseState !== decodedRequestState) {\n throw createClientAuthError(ClientAuthErrorCodes.stateMismatch);\n }\n\n // Check for error\n if (\n serverResponse.error ||\n serverResponse.error_description ||\n serverResponse.suberror\n ) {\n const serverErrorNo = parseServerErrorNo(serverResponse);\n if (\n isInteractionRequiredError(\n serverResponse.error,\n serverResponse.error_description,\n serverResponse.suberror\n )\n ) {\n throw new InteractionRequiredAuthError(\n serverResponse.error || \"\",\n serverResponse.error_description,\n serverResponse.suberror,\n serverResponse.timestamp || \"\",\n serverResponse.trace_id || \"\",\n serverResponse.correlation_id || \"\",\n serverResponse.claims || \"\",\n serverErrorNo\n );\n }\n\n throw new ServerError(\n serverResponse.error || \"\",\n serverResponse.error_description,\n serverResponse.suberror,\n serverErrorNo\n );\n }\n}\n\n/**\n * Get server error No from the error_uri\n * @param serverResponse\n * @returns\n */\nfunction parseServerErrorNo(\n serverResponse: AuthorizeResponse\n): string | undefined {\n const errorCodePrefix = \"code=\";\n const errorCodePrefixIndex =\n serverResponse.error_uri?.lastIndexOf(errorCodePrefix);\n return errorCodePrefixIndex && errorCodePrefixIndex >= 0\n ? serverResponse.error_uri?.substring(\n errorCodePrefixIndex + errorCodePrefix.length\n )\n : undefined;\n}\n\n/**\n * Helper to get sid from account. Returns null if idTokenClaims are not present or sid is not present.\n * @param account\n */\nfunction extractAccountSid(account: AccountInfo): string | null {\n return account.idTokenClaims?.sid || null;\n}\n\nfunction extractLoginHint(account: AccountInfo): string | null {\n return account.loginHint || account.idTokenClaims?.login_hint || null;\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n createClientConfigurationError,\n ClientConfigurationErrorCodes,\n} from \"../error/ClientConfigurationError.js\";\nimport { Constants, HeaderNames } from \"../utils/Constants.js\";\n\ntype WWWAuthenticateChallenges = {\n nonce?: string;\n};\n\ntype AuthenticationInfoChallenges = {\n nextnonce?: string;\n};\n\n/**\n * This is a helper class that parses supported HTTP response authentication headers to extract and return\n * header challenge values that can be used outside the basic authorization flows.\n */\nexport class AuthenticationHeaderParser {\n private headers: Record;\n\n constructor(headers: Record) {\n this.headers = headers;\n }\n\n /**\n * This method parses the SHR nonce value out of either the Authentication-Info or WWW-Authenticate authentication headers.\n * @returns\n */\n getShrNonce(): string {\n // Attempt to parse nonce from Authentiacation-Info\n const authenticationInfo = this.headers[HeaderNames.AuthenticationInfo];\n if (authenticationInfo) {\n const authenticationInfoChallenges =\n this.parseChallenges(\n authenticationInfo\n );\n if (authenticationInfoChallenges.nextnonce) {\n return authenticationInfoChallenges.nextnonce;\n }\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.invalidAuthenticationHeader\n );\n }\n\n // Attempt to parse nonce from WWW-Authenticate\n const wwwAuthenticate = this.headers[HeaderNames.WWWAuthenticate];\n if (wwwAuthenticate) {\n const wwwAuthenticateChallenges =\n this.parseChallenges(\n wwwAuthenticate\n );\n if (wwwAuthenticateChallenges.nonce) {\n return wwwAuthenticateChallenges.nonce;\n }\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.invalidAuthenticationHeader\n );\n }\n\n // If neither header is present, throw missing headers error\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.missingNonceAuthenticationHeader\n );\n }\n\n /**\n * Parses an HTTP header's challenge set into a key/value map.\n * @param header\n * @returns\n */\n private parseChallenges(header: string): T {\n const schemeSeparator = header.indexOf(\" \");\n const challenges = header.substr(schemeSeparator + 1).split(\",\");\n const challengeMap = {} as T;\n\n challenges.forEach((challenge: string) => {\n const [key, value] = challenge.split(\"=\");\n // Remove escaped quotation marks (', \") from challenge string to keep only the challenge value\n challengeMap[key] = unescape(\n value.replace(/['\"]+/g, Constants.EMPTY_STRING)\n );\n });\n\n return challengeMap;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n SERVER_TELEM_CONSTANTS,\n Separators,\n CacheOutcome,\n Constants,\n RegionDiscoverySources,\n RegionDiscoveryOutcomes,\n} from \"../../utils/Constants.js\";\nimport { CacheManager } from \"../../cache/CacheManager.js\";\nimport { AuthError } from \"../../error/AuthError.js\";\nimport { ServerTelemetryRequest } from \"./ServerTelemetryRequest.js\";\nimport { ServerTelemetryEntity } from \"../../cache/entities/ServerTelemetryEntity.js\";\nimport { RegionDiscoveryMetadata } from \"../../authority/RegionDiscoveryMetadata.js\";\n\nconst skuGroupSeparator = \",\";\nconst skuValueSeparator = \"|\";\n\ntype SkuParams = {\n libraryName?: string;\n libraryVersion?: string;\n extensionName?: string;\n extensionVersion?: string;\n skus?: string;\n};\n\nfunction makeExtraSkuString(params: SkuParams): string {\n const {\n skus,\n libraryName,\n libraryVersion,\n extensionName,\n extensionVersion,\n } = params;\n const skuMap: Map = new Map([\n [0, [libraryName, libraryVersion]],\n [2, [extensionName, extensionVersion]],\n ]);\n let skuArr: string[] = [];\n\n if (skus?.length) {\n skuArr = skus.split(skuGroupSeparator);\n\n // Ignore invalid input sku param\n if (skuArr.length < 4) {\n return skus;\n }\n } else {\n skuArr = Array.from({ length: 4 }, () => skuValueSeparator);\n }\n\n skuMap.forEach((value, key) => {\n if (value.length === 2 && value[0]?.length && value[1]?.length) {\n setSku({\n skuArr,\n index: key,\n skuName: value[0],\n skuVersion: value[1],\n });\n }\n });\n\n return skuArr.join(skuGroupSeparator);\n}\n\nfunction setSku(params: {\n skuArr: string[];\n index: number;\n skuName: string;\n skuVersion: string;\n}): void {\n const { skuArr, index, skuName, skuVersion } = params;\n if (index >= skuArr.length) {\n return;\n }\n skuArr[index] = [skuName, skuVersion].join(skuValueSeparator);\n}\n\n/** @internal */\nexport class ServerTelemetryManager {\n private cacheManager: CacheManager;\n private apiId: number;\n private correlationId: string;\n private telemetryCacheKey: string;\n private wrapperSKU: String;\n private wrapperVer: String;\n private regionUsed: string | undefined;\n private regionSource: RegionDiscoverySources | undefined;\n private regionOutcome: RegionDiscoveryOutcomes | undefined;\n private cacheOutcome: CacheOutcome = CacheOutcome.NOT_APPLICABLE;\n\n constructor(\n telemetryRequest: ServerTelemetryRequest,\n cacheManager: CacheManager\n ) {\n this.cacheManager = cacheManager;\n this.apiId = telemetryRequest.apiId;\n this.correlationId = telemetryRequest.correlationId;\n this.wrapperSKU = telemetryRequest.wrapperSKU || Constants.EMPTY_STRING;\n this.wrapperVer = telemetryRequest.wrapperVer || Constants.EMPTY_STRING;\n\n this.telemetryCacheKey =\n SERVER_TELEM_CONSTANTS.CACHE_KEY +\n Separators.CACHE_KEY_SEPARATOR +\n telemetryRequest.clientId;\n }\n\n /**\n * API to add MSER Telemetry to request\n */\n generateCurrentRequestHeaderValue(): string {\n const request = `${this.apiId}${SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR}${this.cacheOutcome}`;\n const platformFieldsArr = [this.wrapperSKU, this.wrapperVer];\n const nativeBrokerErrorCode = this.getNativeBrokerErrorCode();\n if (nativeBrokerErrorCode?.length) {\n platformFieldsArr.push(`broker_error=${nativeBrokerErrorCode}`);\n }\n const platformFields = platformFieldsArr.join(\n SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR\n );\n const regionDiscoveryFields = this.getRegionDiscoveryFields();\n const requestWithRegionDiscoveryFields = [\n request,\n regionDiscoveryFields,\n ].join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR);\n\n return [\n SERVER_TELEM_CONSTANTS.SCHEMA_VERSION,\n requestWithRegionDiscoveryFields,\n platformFields,\n ].join(SERVER_TELEM_CONSTANTS.CATEGORY_SEPARATOR);\n }\n\n /**\n * API to add MSER Telemetry for the last failed request\n */\n generateLastRequestHeaderValue(): string {\n const lastRequests = this.getLastRequests();\n\n const maxErrors = ServerTelemetryManager.maxErrorsToSend(lastRequests);\n const failedRequests = lastRequests.failedRequests\n .slice(0, 2 * maxErrors)\n .join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR);\n const errors = lastRequests.errors\n .slice(0, maxErrors)\n .join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR);\n const errorCount = lastRequests.errors.length;\n\n // Indicate whether this header contains all data or partial data\n const overflow =\n maxErrors < errorCount\n ? SERVER_TELEM_CONSTANTS.OVERFLOW_TRUE\n : SERVER_TELEM_CONSTANTS.OVERFLOW_FALSE;\n const platformFields = [errorCount, overflow].join(\n SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR\n );\n\n return [\n SERVER_TELEM_CONSTANTS.SCHEMA_VERSION,\n lastRequests.cacheHits,\n failedRequests,\n errors,\n platformFields,\n ].join(SERVER_TELEM_CONSTANTS.CATEGORY_SEPARATOR);\n }\n\n /**\n * API to cache token failures for MSER data capture\n * @param error\n */\n cacheFailedRequest(error: unknown): void {\n const lastRequests = this.getLastRequests();\n if (\n lastRequests.errors.length >=\n SERVER_TELEM_CONSTANTS.MAX_CACHED_ERRORS\n ) {\n // Remove a cached error to make room, first in first out\n lastRequests.failedRequests.shift(); // apiId\n lastRequests.failedRequests.shift(); // correlationId\n lastRequests.errors.shift();\n }\n\n lastRequests.failedRequests.push(this.apiId, this.correlationId);\n\n if (error instanceof Error && !!error && error.toString()) {\n if (error instanceof AuthError) {\n if (error.subError) {\n lastRequests.errors.push(error.subError);\n } else if (error.errorCode) {\n lastRequests.errors.push(error.errorCode);\n } else {\n lastRequests.errors.push(error.toString());\n }\n } else {\n lastRequests.errors.push(error.toString());\n }\n } else {\n lastRequests.errors.push(SERVER_TELEM_CONSTANTS.UNKNOWN_ERROR);\n }\n\n this.cacheManager.setServerTelemetry(\n this.telemetryCacheKey,\n lastRequests,\n this.correlationId\n );\n\n return;\n }\n\n /**\n * Update server telemetry cache entry by incrementing cache hit counter\n */\n incrementCacheHits(): number {\n const lastRequests = this.getLastRequests();\n lastRequests.cacheHits += 1;\n\n this.cacheManager.setServerTelemetry(\n this.telemetryCacheKey,\n lastRequests,\n this.correlationId\n );\n return lastRequests.cacheHits;\n }\n\n /**\n * Get the server telemetry entity from cache or initialize a new one\n */\n getLastRequests(): ServerTelemetryEntity {\n const initialValue: ServerTelemetryEntity = {\n failedRequests: [],\n errors: [],\n cacheHits: 0,\n };\n const lastRequests = this.cacheManager.getServerTelemetry(\n this.telemetryCacheKey\n ) as ServerTelemetryEntity;\n\n return lastRequests || initialValue;\n }\n\n /**\n * Remove server telemetry cache entry\n */\n clearTelemetryCache(): void {\n const lastRequests = this.getLastRequests();\n const numErrorsFlushed =\n ServerTelemetryManager.maxErrorsToSend(lastRequests);\n const errorCount = lastRequests.errors.length;\n if (numErrorsFlushed === errorCount) {\n // All errors were sent on last request, clear Telemetry cache\n this.cacheManager.removeItem(\n this.telemetryCacheKey,\n this.correlationId\n );\n } else {\n // Partial data was flushed to server, construct a new telemetry cache item with errors that were not flushed\n const serverTelemEntity: ServerTelemetryEntity = {\n failedRequests: lastRequests.failedRequests.slice(\n numErrorsFlushed * 2\n ), // failedRequests contains 2 items for each error\n errors: lastRequests.errors.slice(numErrorsFlushed),\n cacheHits: 0,\n };\n\n this.cacheManager.setServerTelemetry(\n this.telemetryCacheKey,\n serverTelemEntity,\n this.correlationId\n );\n }\n }\n\n /**\n * Returns the maximum number of errors that can be flushed to the server in the next network request\n * @param serverTelemetryEntity\n */\n static maxErrorsToSend(\n serverTelemetryEntity: ServerTelemetryEntity\n ): number {\n let i;\n let maxErrors = 0;\n let dataSize = 0;\n const errorCount = serverTelemetryEntity.errors.length;\n for (i = 0; i < errorCount; i++) {\n // failedRequests parameter contains pairs of apiId and correlationId, multiply index by 2 to preserve pairs\n const apiId =\n serverTelemetryEntity.failedRequests[2 * i] ||\n Constants.EMPTY_STRING;\n const correlationId =\n serverTelemetryEntity.failedRequests[2 * i + 1] ||\n Constants.EMPTY_STRING;\n const errorCode =\n serverTelemetryEntity.errors[i] || Constants.EMPTY_STRING;\n\n // Count number of characters that would be added to header, each character is 1 byte. Add 3 at the end to account for separators\n dataSize +=\n apiId.toString().length +\n correlationId.toString().length +\n errorCode.length +\n 3;\n\n if (dataSize < SERVER_TELEM_CONSTANTS.MAX_LAST_HEADER_BYTES) {\n // Adding this entry to the header would still keep header size below the limit\n maxErrors += 1;\n } else {\n break;\n }\n }\n\n return maxErrors;\n }\n\n /**\n * Get the region discovery fields\n *\n * @returns string\n */\n getRegionDiscoveryFields(): string {\n const regionDiscoveryFields: string[] = [];\n\n regionDiscoveryFields.push(this.regionUsed || Constants.EMPTY_STRING);\n regionDiscoveryFields.push(this.regionSource || Constants.EMPTY_STRING);\n regionDiscoveryFields.push(\n this.regionOutcome || Constants.EMPTY_STRING\n );\n\n return regionDiscoveryFields.join(\",\");\n }\n\n /**\n * Update the region discovery metadata\n *\n * @param regionDiscoveryMetadata\n * @returns void\n */\n updateRegionDiscoveryMetadata(\n regionDiscoveryMetadata: RegionDiscoveryMetadata\n ): void {\n this.regionUsed = regionDiscoveryMetadata.region_used;\n this.regionSource = regionDiscoveryMetadata.region_source;\n this.regionOutcome = regionDiscoveryMetadata.region_outcome;\n }\n\n /**\n * Set cache outcome\n */\n setCacheOutcome(cacheOutcome: CacheOutcome): void {\n this.cacheOutcome = cacheOutcome;\n }\n\n setNativeBrokerErrorCode(errorCode: string): void {\n const lastRequests = this.getLastRequests();\n lastRequests.nativeBrokerErrorCode = errorCode;\n this.cacheManager.setServerTelemetry(\n this.telemetryCacheKey,\n lastRequests,\n this.correlationId\n );\n }\n\n getNativeBrokerErrorCode(): string | undefined {\n return this.getLastRequests().nativeBrokerErrorCode;\n }\n\n clearNativeBrokerErrorCode(): void {\n const lastRequests = this.getLastRequests();\n delete lastRequests.nativeBrokerErrorCode;\n this.cacheManager.setServerTelemetry(\n this.telemetryCacheKey,\n lastRequests,\n this.correlationId\n );\n }\n\n static makeExtraSkuString(params: SkuParams): string {\n return makeExtraSkuString(params);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const missingKidError = \"missing_kid_error\";\nexport const missingAlgError = \"missing_alg_error\";\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthError } from \"./AuthError.js\";\nimport * as JoseHeaderErrorCodes from \"./JoseHeaderErrorCodes.js\";\nexport { JoseHeaderErrorCodes };\n\nexport const JoseHeaderErrorMessages = {\n [JoseHeaderErrorCodes.missingKidError]:\n \"The JOSE Header for the requested JWT, JWS or JWK object requires a keyId to be configured as the 'kid' header claim. No 'kid' value was provided.\",\n [JoseHeaderErrorCodes.missingAlgError]:\n \"The JOSE Header for the requested JWT, JWS or JWK object requires an algorithm to be specified as the 'alg' header claim. No 'alg' value was provided.\",\n};\n\n/**\n * Error thrown when there is an error in the client code running on the browser.\n */\nexport class JoseHeaderError extends AuthError {\n constructor(errorCode: string, errorMessage?: string) {\n super(errorCode, errorMessage);\n this.name = \"JoseHeaderError\";\n\n Object.setPrototypeOf(this, JoseHeaderError.prototype);\n }\n}\n\n/** Returns JoseHeaderError object */\nexport function createJoseHeaderError(code: string): JoseHeaderError {\n return new JoseHeaderError(code, JoseHeaderErrorMessages[code]);\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n JoseHeaderErrorCodes,\n createJoseHeaderError,\n} from \"../error/JoseHeaderError.js\";\nimport { JsonWebTokenTypes } from \"../utils/Constants.js\";\n\nexport type JoseHeaderOptions = {\n typ?: JsonWebTokenTypes;\n alg?: string;\n kid?: string;\n};\n\n/** @internal */\nexport class JoseHeader {\n public typ?: JsonWebTokenTypes;\n public alg?: string;\n public kid?: string;\n\n constructor(options: JoseHeaderOptions) {\n this.typ = options.typ;\n this.alg = options.alg;\n this.kid = options.kid;\n }\n\n /**\n * Builds SignedHttpRequest formatted JOSE Header from the\n * JOSE Header options provided or previously set on the object and returns\n * the stringified header object.\n * Throws if keyId or algorithm aren't provided since they are required for Access Token Binding.\n * @param shrHeaderOptions\n * @returns\n */\n static getShrHeaderString(shrHeaderOptions: JoseHeaderOptions): string {\n // KeyID is required on the SHR header\n if (!shrHeaderOptions.kid) {\n throw createJoseHeaderError(JoseHeaderErrorCodes.missingKidError);\n }\n\n // Alg is required on the SHR header\n if (!shrHeaderOptions.alg) {\n throw createJoseHeaderError(JoseHeaderErrorCodes.missingAlgError);\n }\n\n const shrHeader = new JoseHeader({\n // Access Token PoP headers must have type pop, but the type header can be overriden for special cases\n typ: shrHeaderOptions.typ || JsonWebTokenTypes.Pop,\n kid: shrHeaderOptions.kid,\n alg: shrHeaderOptions.alg,\n });\n\n return JSON.stringify(shrHeader);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ApplicationTelemetry } from \"../../config/ClientConfiguration.js\";\nimport { Logger } from \"../../logger/Logger.js\";\nimport {\n InProgressPerformanceEvent,\n IPerformanceClient,\n PerformanceCallbackFunction,\n QueueMeasurement,\n} from \"./IPerformanceClient.js\";\nimport {\n IntFields,\n PerformanceEvent,\n PerformanceEventAbbreviations,\n PerformanceEventContext,\n PerformanceEvents,\n PerformanceEventStackedContext,\n PerformanceEventStatus,\n} from \"./PerformanceEvent.js\";\nimport { IPerformanceMeasurement } from \"./IPerformanceMeasurement.js\";\nimport { StubPerformanceMeasurement } from \"./StubPerformanceClient.js\";\nimport { AuthError } from \"../../error/AuthError.js\";\nimport { CacheError } from \"../../error/CacheError.js\";\nimport { ServerError } from \"../../error/ServerError.js\";\nimport { InteractionRequiredAuthError } from \"../../error/InteractionRequiredAuthError.js\";\n\nexport interface PreQueueEvent {\n name: PerformanceEvents;\n time: number;\n}\n\n/**\n * Starts context by adding payload to the stack\n * @param event {PerformanceEvent}\n * @param abbreviations {Map} event name abbreviations\n * @param stack {?PerformanceEventStackedContext[]} stack\n */\nexport function startContext(\n event: PerformanceEvent,\n abbreviations: Map,\n stack?: PerformanceEventStackedContext[]\n): void {\n if (!stack) {\n return;\n }\n\n stack.push({\n name: abbreviations.get(event.name) || event.name,\n });\n}\n\n/**\n * Ends context by removing payload from the stack and returning parent or self, if stack is empty, payload\n *\n * @param event {PerformanceEvent}\n * @param abbreviations {Map} event name abbreviations\n * @param stack {?PerformanceEventStackedContext[]} stack\n * @param error {?unknown} error\n */\nexport function endContext(\n event: PerformanceEvent,\n abbreviations: Map,\n stack?: PerformanceEventStackedContext[],\n error?: unknown\n): PerformanceEventContext | undefined {\n if (!stack?.length) {\n return;\n }\n\n const peek = (stack: PerformanceEventStackedContext[]) => {\n return stack.length ? stack[stack.length - 1] : undefined;\n };\n\n const abbrEventName = abbreviations.get(event.name) || event.name;\n const top = peek(stack);\n if (top?.name !== abbrEventName) {\n return;\n }\n\n const current = stack?.pop();\n if (!current) {\n return;\n }\n\n const errorCode =\n error instanceof AuthError\n ? error.errorCode\n : error instanceof Error\n ? error.name\n : undefined;\n const subErr = error instanceof AuthError ? error.subError : undefined;\n\n if (errorCode && current.childErr !== errorCode) {\n current.err = errorCode;\n if (subErr) {\n current.subErr = subErr;\n }\n }\n\n delete current.name;\n delete current.childErr;\n\n const context: PerformanceEventContext = {\n ...current,\n dur: event.durationMs,\n };\n\n if (!event.success) {\n context.fail = 1;\n }\n\n const parent = peek(stack);\n if (!parent) {\n return { [abbrEventName]: context };\n }\n\n if (errorCode) {\n parent.childErr = errorCode;\n }\n\n let childName: string;\n if (!parent[abbrEventName]) {\n childName = abbrEventName;\n } else {\n const siblings = Object.keys(parent).filter((key) =>\n key.startsWith(abbrEventName)\n ).length;\n childName = `${abbrEventName}_${siblings + 1}`;\n }\n parent[childName] = context;\n return parent;\n}\n\n/**\n * Adds error name and stack trace to the telemetry event\n * @param error {Error}\n * @param logger {Logger}\n * @param event {PerformanceEvent}\n * @param stackMaxSize {number} max error stack size to capture\n */\nexport function addError(\n error: unknown,\n logger: Logger,\n event: PerformanceEvent,\n stackMaxSize: number = 5\n): void {\n if (!(error instanceof Error)) {\n logger.trace(\n \"PerformanceClient.addErrorStack: Input error is not instance of Error\",\n event.correlationId\n );\n return;\n } else if (error instanceof AuthError) {\n event.errorCode = error.errorCode;\n event.subErrorCode = error.subError;\n if (\n error instanceof ServerError ||\n error instanceof InteractionRequiredAuthError\n ) {\n event.serverErrorNo = error.errorNo;\n }\n return;\n } else if (error instanceof CacheError) {\n event.errorCode = error.errorCode;\n return;\n } else if (event.errorStack?.length) {\n logger.trace(\n \"PerformanceClient.addErrorStack: Stack already exist\",\n event.correlationId\n );\n return;\n } else if (!error.stack?.length) {\n logger.trace(\n \"PerformanceClient.addErrorStack: Input stack is empty\",\n event.correlationId\n );\n return;\n }\n\n if (error.stack) {\n event.errorStack = compactStack(error.stack, stackMaxSize);\n }\n event.errorName = error.name;\n}\n\n/**\n * Compacts error stack into array by fetching N first entries\n * @param stack {string} error stack\n * @param stackMaxSize {number} max error stack size to capture\n * @returns {string[]}\n */\nexport function compactStack(stack: string, stackMaxSize: number): string[] {\n if (stackMaxSize < 0) {\n return [];\n }\n\n const stackArr = stack.split(\"\\n\") || [];\n\n const res = [];\n\n // Check for a handful of known, common runtime errors and log them (with redaction where applicable).\n const firstLine = stackArr[0];\n if (\n firstLine.startsWith(\"TypeError: Cannot read property\") ||\n firstLine.startsWith(\"TypeError: Cannot read properties of\") ||\n firstLine.startsWith(\"TypeError: Cannot set property\") ||\n firstLine.startsWith(\"TypeError: Cannot set properties of\") ||\n firstLine.endsWith(\"is not a function\")\n ) {\n // These types of errors are not at risk of leaking PII. They will indicate unavailable APIs\n res.push(compactStackLine(firstLine));\n } else if (\n firstLine.startsWith(\"SyntaxError\") ||\n firstLine.startsWith(\"TypeError\")\n ) {\n // Prevent unintentional leaking of arbitrary info by redacting contents between both single and double quotes\n res.push(\n compactStackLine(\n // Example: SyntaxError: Unexpected token 'e', \"test\" is not valid JSON -> SyntaxError: Unexpected token , is not valid JSON\n firstLine.replace(/['].*[']|[\"].*[\"]/g, \"\")\n )\n );\n }\n\n // Get top N stack lines\n for (let ix = 1; ix < stackArr.length; ix++) {\n if (res.length >= stackMaxSize) {\n break;\n }\n const line = stackArr[ix];\n res.push(compactStackLine(line));\n }\n return res;\n}\n\n/**\n * Compacts error stack line by shortening file path\n * Example: https://localhost/msal-common/src/authority/Authority.js:100:1 -> Authority.js:100:1\n * @param line {string} stack line\n * @returns {string}\n */\nexport function compactStackLine(line: string): string {\n const filePathIx = line.lastIndexOf(\" \") + 1;\n if (filePathIx < 1) {\n return line;\n }\n const filePath = line.substring(filePathIx);\n\n let fileNameIx = filePath.lastIndexOf(\"/\");\n fileNameIx = fileNameIx < 0 ? filePath.lastIndexOf(\"\\\\\") : fileNameIx;\n\n if (fileNameIx >= 0) {\n return (\n line.substring(0, filePathIx) +\n \"(\" +\n filePath.substring(fileNameIx + 1) +\n (filePath.charAt(filePath.length - 1) === \")\" ? \"\" : \")\")\n ).trimStart();\n }\n\n return line.trimStart();\n}\n\nexport abstract class PerformanceClient implements IPerformanceClient {\n protected authority: string;\n protected libraryName: string;\n protected libraryVersion: string;\n protected applicationTelemetry: ApplicationTelemetry;\n protected clientId: string;\n protected logger: Logger;\n protected callbacks: Map;\n\n /**\n * Multiple events with the same correlation id.\n * @protected\n * @type {Map}\n */\n protected eventsByCorrelationId: Map;\n\n /**\n * Map of pre-queue times by correlation Id\n *\n * @protected\n * @type {Map}\n */\n protected preQueueTimeByCorrelationId: Map;\n\n /**\n * Map of queue measurements by correlation Id\n *\n * @protected\n * @type {Map>}\n */\n protected queueMeasurements: Map>;\n\n protected intFields: Set;\n\n /**\n * Map of stacked events by correlation id.\n *\n * @protected\n */\n protected eventStack: Map;\n\n /**\n * Event name abbreviations\n *\n * @protected\n */\n protected abbreviations: Map;\n\n /**\n * Creates an instance of PerformanceClient,\n * an abstract class containing core performance telemetry logic.\n *\n * @constructor\n * @param {string} clientId Client ID of the application\n * @param {string} authority Authority used by the application\n * @param {Logger} logger Logger used by the application\n * @param {string} libraryName Name of the library\n * @param {string} libraryVersion Version of the library\n * @param {ApplicationTelemetry} applicationTelemetry application name and version\n * @param {Set} intFields integer fields to be truncated\n * @param {Map} abbreviations event name abbreviations\n */\n constructor(\n clientId: string,\n authority: string,\n logger: Logger,\n libraryName: string,\n libraryVersion: string,\n applicationTelemetry: ApplicationTelemetry,\n intFields?: Set,\n abbreviations?: Map\n ) {\n this.authority = authority;\n this.libraryName = libraryName;\n this.libraryVersion = libraryVersion;\n this.applicationTelemetry = applicationTelemetry;\n this.clientId = clientId;\n this.logger = logger;\n this.callbacks = new Map();\n this.eventsByCorrelationId = new Map();\n this.eventStack = new Map();\n this.queueMeasurements = new Map();\n this.preQueueTimeByCorrelationId = new Map();\n this.intFields = intFields || new Set();\n for (const item of IntFields) {\n this.intFields.add(item);\n }\n this.abbreviations = abbreviations || new Map();\n for (const [key, value] of PerformanceEventAbbreviations) {\n this.abbreviations.set(key, value);\n }\n }\n\n /**\n * Generates and returns a unique id, typically a guid.\n *\n * @abstract\n * @returns {string}\n */\n abstract generateId(): string;\n\n /**\n * Starts and returns an platform-specific implementation of IPerformanceMeasurement.\n * Note: this function can be changed to abstract at the next major version bump.\n *\n * @param {string} measureName\n * @param {string} correlationId\n * @returns {IPerformanceMeasurement}\n * @deprecated This method will be removed in the next major version\n */\n startPerformanceMeasurement(\n measureName: string, // eslint-disable-line @typescript-eslint/no-unused-vars\n correlationId: string // eslint-disable-line @typescript-eslint/no-unused-vars\n ): IPerformanceMeasurement {\n return {} as IPerformanceMeasurement;\n }\n\n /**\n * Sets pre-queue time by correlation Id\n *\n * @abstract\n * @param {PerformanceEvents} eventName\n * @param {string} correlationId\n * @returns\n */\n abstract setPreQueueTime(\n eventName: PerformanceEvents,\n correlationId?: string\n ): void;\n\n /**\n * Gets map of pre-queue times by correlation Id\n *\n * @param {PerformanceEvents} eventName\n * @param {string} correlationId\n * @returns {number}\n */\n getPreQueueTime(eventName: string, correlationId: string): number | void {\n const preQueueEvent: PreQueueEvent | undefined =\n this.preQueueTimeByCorrelationId.get(correlationId);\n\n if (!preQueueEvent) {\n this.logger.trace(\n `PerformanceClient.getPreQueueTime: no pre-queue times found for correlationId: ${correlationId}, unable to add queue measurement`\n );\n return;\n } else if (preQueueEvent.name !== eventName) {\n this.logger.trace(\n `PerformanceClient.getPreQueueTime: no pre-queue time found for ${eventName}, unable to add queue measurement`\n );\n return;\n }\n\n return preQueueEvent.time;\n }\n\n /**\n * Calculates the difference between current time and time when function was queued.\n * Note: It is possible to have 0 as the queue time if the current time and the queued time was the same.\n *\n * @param {number} preQueueTime\n * @param {number} currentTime\n * @returns {number}\n */\n calculateQueuedTime(preQueueTime: number, currentTime: number): number {\n if (preQueueTime < 1) {\n this.logger.trace(\n `PerformanceClient: preQueueTime should be a positive integer and not ${preQueueTime}`\n );\n return 0;\n }\n\n if (currentTime < 1) {\n this.logger.trace(\n `PerformanceClient: currentTime should be a positive integer and not ${currentTime}`\n );\n return 0;\n }\n\n if (currentTime < preQueueTime) {\n this.logger.trace(\n \"PerformanceClient: currentTime is less than preQueueTime, check how time is being retrieved\"\n );\n return 0;\n }\n\n return currentTime - preQueueTime;\n }\n\n /**\n * Adds queue measurement time to QueueMeasurements array for given correlation ID.\n *\n * @param {PerformanceEvents} eventName\n * @param {?string} correlationId\n * @param {?number} queueTime\n * @param {?boolean} manuallyCompleted - indicator for manually completed queue measurements\n * @returns\n */\n addQueueMeasurement(\n eventName: string,\n correlationId?: string,\n queueTime?: number,\n manuallyCompleted?: boolean\n ): void {\n if (!correlationId) {\n this.logger.trace(\n `PerformanceClient.addQueueMeasurement: correlationId not provided for ${eventName}, cannot add queue measurement`\n );\n return;\n }\n\n if (queueTime === 0) {\n // Possible for there to be no queue time after calculation\n this.logger.trace(\n `PerformanceClient.addQueueMeasurement: queue time provided for ${eventName} is ${queueTime}`\n );\n } else if (!queueTime) {\n this.logger.trace(\n `PerformanceClient.addQueueMeasurement: no queue time provided for ${eventName}`\n );\n return;\n }\n\n const queueMeasurement: QueueMeasurement = {\n eventName,\n // Always default queue time to 0 for manually completed (improperly instrumented)\n queueTime: manuallyCompleted ? 0 : queueTime,\n manuallyCompleted,\n };\n\n // Adds to existing correlation Id if present in queueMeasurements\n const existingMeasurements = this.queueMeasurements.get(correlationId);\n if (existingMeasurements) {\n existingMeasurements.push(queueMeasurement);\n this.queueMeasurements.set(correlationId, existingMeasurements);\n } else {\n // Sets new correlation Id if not present in queueMeasurements\n this.logger.trace(\n `PerformanceClient.addQueueMeasurement: adding correlationId ${correlationId} to queue measurements`\n );\n const measurementArray = [queueMeasurement];\n this.queueMeasurements.set(correlationId, measurementArray);\n }\n // Delete processed pre-queue event.\n this.preQueueTimeByCorrelationId.delete(correlationId);\n }\n\n /**\n * Starts measuring performance for a given operation. Returns a function that should be used to end the measurement.\n *\n * @param {PerformanceEvents} measureName\n * @param {?string} [correlationId]\n * @returns {InProgressPerformanceEvent}\n */\n startMeasurement(\n measureName: string,\n correlationId?: string\n ): InProgressPerformanceEvent {\n // Generate a placeholder correlation if the request does not provide one\n const eventCorrelationId = correlationId || this.generateId();\n if (!correlationId) {\n this.logger.info(\n `PerformanceClient: No correlation id provided for ${measureName}, generating`,\n eventCorrelationId\n );\n }\n\n this.logger.trace(\n `PerformanceClient: Performance measurement started for ${measureName}`,\n eventCorrelationId\n );\n\n const inProgressEvent: PerformanceEvent = {\n eventId: this.generateId(),\n status: PerformanceEventStatus.InProgress,\n authority: this.authority,\n libraryName: this.libraryName,\n libraryVersion: this.libraryVersion,\n clientId: this.clientId,\n name: measureName,\n startTimeMs: Date.now(),\n correlationId: eventCorrelationId,\n appName: this.applicationTelemetry?.appName,\n appVersion: this.applicationTelemetry?.appVersion,\n };\n\n // Store in progress events so they can be discarded if not ended properly\n this.cacheEventByCorrelationId(inProgressEvent);\n startContext(\n inProgressEvent,\n this.abbreviations,\n this.eventStack.get(eventCorrelationId)\n );\n\n // Return the event and functions the caller can use to properly end/flush the measurement\n return {\n end: (\n event?: Partial,\n error?: unknown\n ): PerformanceEvent | null => {\n return this.endMeasurement(\n {\n // Initial set of event properties\n ...inProgressEvent,\n // Properties set when event ends\n ...event,\n },\n error\n );\n },\n discard: () => {\n return this.discardMeasurements(inProgressEvent.correlationId);\n },\n add: (fields: { [key: string]: {} | undefined }) => {\n return this.addFields(fields, inProgressEvent.correlationId);\n },\n increment: (fields: { [key: string]: number | undefined }) => {\n return this.incrementFields(\n fields,\n inProgressEvent.correlationId\n );\n },\n event: inProgressEvent,\n measurement: new StubPerformanceMeasurement(),\n };\n }\n\n /**\n * Stops measuring the performance for an operation. Should only be called directly by PerformanceClient classes,\n * as consumers should instead use the function returned by startMeasurement.\n * Adds a new field named as \"[event name]DurationMs\" for sub-measurements, completes and emits an event\n * otherwise.\n *\n * @param {PerformanceEvent} event\n * @param {unknown} error\n * @returns {(PerformanceEvent | null)}\n */\n endMeasurement(\n event: PerformanceEvent,\n error?: unknown\n ): PerformanceEvent | null {\n const rootEvent: PerformanceEvent | undefined =\n this.eventsByCorrelationId.get(event.correlationId);\n if (!rootEvent) {\n this.logger.trace(\n `PerformanceClient: Measurement not found for ${event.eventId}`,\n event.correlationId\n );\n return null;\n }\n\n const isRoot = event.eventId === rootEvent.eventId;\n let queueInfo = {\n totalQueueTime: 0,\n totalQueueCount: 0,\n manuallyCompletedCount: 0,\n };\n\n event.durationMs = Math.round(\n event.durationMs || this.getDurationMs(event.startTimeMs)\n );\n\n const context = JSON.stringify(\n endContext(\n event,\n this.abbreviations,\n this.eventStack.get(rootEvent.correlationId),\n error\n )\n );\n\n if (isRoot) {\n queueInfo = this.getQueueInfo(event.correlationId);\n this.discardMeasurements(rootEvent.correlationId);\n } else {\n rootEvent.incompleteSubMeasurements?.delete(event.eventId);\n }\n\n this.logger.trace(\n `PerformanceClient: Performance measurement ended for ${event.name}: ${event.durationMs} ms`,\n event.correlationId\n );\n\n if (error) {\n addError(error, this.logger, rootEvent);\n }\n\n // Add sub-measurement attribute to root event.\n if (!isRoot) {\n rootEvent[event.name + \"DurationMs\"] = Math.floor(event.durationMs);\n return { ...rootEvent };\n }\n\n if (\n isRoot &&\n !error &&\n (rootEvent.errorCode || rootEvent.subErrorCode)\n ) {\n this.logger.trace(\n `PerformanceClient: Remove error and sub-error codes for root event ${event.name} as intermediate error was successfully handled`,\n event.correlationId\n );\n rootEvent.errorCode = undefined;\n rootEvent.subErrorCode = undefined;\n }\n\n let finalEvent: PerformanceEvent = { ...rootEvent, ...event };\n let incompleteSubsCount: number = 0;\n // Incomplete sub-measurements are discarded. They are likely an instrumentation bug that should be fixed.\n finalEvent.incompleteSubMeasurements?.forEach((subMeasurement) => {\n this.logger.trace(\n `PerformanceClient: Incomplete submeasurement ${subMeasurement.name} found for ${event.name}`,\n finalEvent.correlationId\n );\n incompleteSubsCount++;\n });\n finalEvent.incompleteSubMeasurements = undefined;\n\n finalEvent = {\n ...finalEvent,\n queuedTimeMs: queueInfo.totalQueueTime,\n queuedCount: queueInfo.totalQueueCount,\n queuedManuallyCompletedCount: queueInfo.manuallyCompletedCount,\n status: PerformanceEventStatus.Completed,\n incompleteSubsCount,\n context,\n };\n this.truncateIntegralFields(finalEvent);\n this.emitEvents([finalEvent], event.correlationId);\n\n return finalEvent;\n }\n\n /**\n * Saves extra information to be emitted when the measurements are flushed\n * @param fields\n * @param correlationId\n */\n addFields(\n fields: { [key: string]: {} | undefined },\n correlationId: string\n ): void {\n this.logger.trace(\"PerformanceClient: Updating static fields\");\n const event = this.eventsByCorrelationId.get(correlationId);\n if (event) {\n this.eventsByCorrelationId.set(correlationId, {\n ...event,\n ...fields,\n });\n } else {\n this.logger.trace(\n \"PerformanceClient: Event not found for\",\n correlationId\n );\n }\n }\n\n /**\n * Increment counters to be emitted when the measurements are flushed\n * @param fields {string[]}\n * @param correlationId {string} correlation identifier\n */\n incrementFields(\n fields: { [key: string]: number | undefined },\n correlationId: string\n ): void {\n this.logger.trace(\"PerformanceClient: Updating counters\");\n const event = this.eventsByCorrelationId.get(correlationId);\n if (event) {\n for (const counter in fields) {\n if (!event.hasOwnProperty(counter)) {\n event[counter] = 0;\n } else if (isNaN(Number(event[counter]))) {\n return;\n }\n event[counter] += fields[counter];\n }\n } else {\n this.logger.trace(\n \"PerformanceClient: Event not found for\",\n correlationId\n );\n }\n }\n\n /**\n * Upserts event into event cache.\n * First key is the correlation id, second key is the event id.\n * Allows for events to be grouped by correlation id,\n * and to easily allow for properties on them to be updated.\n *\n * @private\n * @param {PerformanceEvent} event\n */\n protected cacheEventByCorrelationId(event: PerformanceEvent): void {\n const rootEvent = this.eventsByCorrelationId.get(event.correlationId);\n if (rootEvent) {\n this.logger.trace(\n `PerformanceClient: Performance measurement for ${event.name} added/updated`,\n event.correlationId\n );\n rootEvent.incompleteSubMeasurements =\n rootEvent.incompleteSubMeasurements || new Map();\n rootEvent.incompleteSubMeasurements.set(event.eventId, {\n name: event.name,\n startTimeMs: event.startTimeMs,\n });\n } else {\n this.logger.trace(\n `PerformanceClient: Performance measurement for ${event.name} started`,\n event.correlationId\n );\n this.eventsByCorrelationId.set(event.correlationId, { ...event });\n this.eventStack.set(event.correlationId, []);\n }\n }\n\n private getQueueInfo(correlationId: string): {\n totalQueueTime: number;\n totalQueueCount: number;\n manuallyCompletedCount: number;\n } {\n const queueMeasurementForCorrelationId =\n this.queueMeasurements.get(correlationId);\n if (!queueMeasurementForCorrelationId) {\n this.logger.trace(\n `PerformanceClient: no queue measurements found for for correlationId: ${correlationId}`\n );\n }\n\n let totalQueueTime = 0;\n let totalQueueCount = 0;\n let manuallyCompletedCount = 0;\n queueMeasurementForCorrelationId?.forEach((measurement) => {\n totalQueueTime += measurement.queueTime;\n totalQueueCount++;\n manuallyCompletedCount += measurement.manuallyCompleted ? 1 : 0;\n });\n\n return {\n totalQueueTime,\n totalQueueCount,\n manuallyCompletedCount,\n };\n }\n\n /**\n * Removes measurements and aux data for a given correlation id.\n *\n * @param {string} correlationId\n */\n discardMeasurements(correlationId: string): void {\n this.logger.trace(\n \"PerformanceClient: Performance measurements discarded\",\n correlationId\n );\n this.eventsByCorrelationId.delete(correlationId);\n\n this.logger.trace(\n \"PerformanceClient: QueueMeasurements discarded\",\n correlationId\n );\n this.queueMeasurements.delete(correlationId);\n\n this.logger.trace(\n \"PerformanceClient: Pre-queue times discarded\",\n correlationId\n );\n this.preQueueTimeByCorrelationId.delete(correlationId);\n\n this.logger.trace(\n \"PerformanceClient: Event stack discarded\",\n correlationId\n );\n this.eventStack.delete(correlationId);\n }\n\n /**\n * Registers a callback function to receive performance events.\n *\n * @param {PerformanceCallbackFunction} callback\n * @returns {string}\n */\n addPerformanceCallback(callback: PerformanceCallbackFunction): string {\n for (const [id, cb] of this.callbacks) {\n if (cb.toString() === callback.toString()) {\n this.logger.warning(\n `PerformanceClient: Performance callback is already registered with id: ${id}`\n );\n return id;\n }\n }\n\n const callbackId = this.generateId();\n this.callbacks.set(callbackId, callback);\n this.logger.verbose(\n `PerformanceClient: Performance callback registered with id: ${callbackId}`\n );\n\n return callbackId;\n }\n\n /**\n * Removes a callback registered with addPerformanceCallback.\n *\n * @param {string} callbackId\n * @returns {boolean}\n */\n removePerformanceCallback(callbackId: string): boolean {\n const result = this.callbacks.delete(callbackId);\n\n if (result) {\n this.logger.verbose(\n `PerformanceClient: Performance callback ${callbackId} removed.`\n );\n } else {\n this.logger.verbose(\n `PerformanceClient: Performance callback ${callbackId} not removed.`\n );\n }\n\n return result;\n }\n\n /**\n * Emits events to all registered callbacks.\n *\n * @param {PerformanceEvent[]} events\n * @param {?string} [correlationId]\n */\n emitEvents(events: PerformanceEvent[], correlationId: string): void {\n this.logger.verbose(\n \"PerformanceClient: Emitting performance events\",\n correlationId\n );\n\n this.callbacks.forEach(\n (callback: PerformanceCallbackFunction, callbackId: string) => {\n this.logger.trace(\n `PerformanceClient: Emitting event to callback ${callbackId}`,\n correlationId\n );\n callback.apply(null, [events]);\n }\n );\n }\n\n /**\n * Enforce truncation of integral fields in performance event.\n * @param {PerformanceEvent} event performance event to update.\n */\n private truncateIntegralFields(event: PerformanceEvent): void {\n this.intFields.forEach((key) => {\n if (key in event && typeof event[key] === \"number\") {\n event[key] = Math.floor(event[key]);\n }\n });\n }\n\n /**\n * Returns event duration in milliseconds\n * @param startTimeMs {number}\n * @returns {number}\n */\n private getDurationMs(startTimeMs: number): number {\n const durationMs = Date.now() - startTimeMs;\n // Handle clock skew\n return durationMs < 0 ? durationMs : 0;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const pkceNotCreated = \"pkce_not_created\";\nexport const earJwkEmpty = \"ear_jwk_empty\";\nexport const earJweEmpty = \"ear_jwe_empty\";\nexport const cryptoNonExistent = \"crypto_nonexistent\";\nexport const emptyNavigateUri = \"empty_navigate_uri\";\nexport const hashEmptyError = \"hash_empty_error\";\nexport const noStateInHash = \"no_state_in_hash\";\nexport const hashDoesNotContainKnownProperties =\n \"hash_does_not_contain_known_properties\";\nexport const unableToParseState = \"unable_to_parse_state\";\nexport const stateInteractionTypeMismatch = \"state_interaction_type_mismatch\";\nexport const interactionInProgress = \"interaction_in_progress\";\nexport const popupWindowError = \"popup_window_error\";\nexport const emptyWindowError = \"empty_window_error\";\nexport const userCancelled = \"user_cancelled\";\nexport const monitorPopupTimeout = \"monitor_popup_timeout\";\nexport const monitorWindowTimeout = \"monitor_window_timeout\";\nexport const redirectInIframe = \"redirect_in_iframe\";\nexport const blockIframeReload = \"block_iframe_reload\";\nexport const blockNestedPopups = \"block_nested_popups\";\nexport const iframeClosedPrematurely = \"iframe_closed_prematurely\";\nexport const silentLogoutUnsupported = \"silent_logout_unsupported\";\nexport const noAccountError = \"no_account_error\";\nexport const silentPromptValueError = \"silent_prompt_value_error\";\nexport const noTokenRequestCacheError = \"no_token_request_cache_error\";\nexport const unableToParseTokenRequestCacheError =\n \"unable_to_parse_token_request_cache_error\";\nexport const authRequestNotSetError = \"auth_request_not_set_error\";\nexport const invalidCacheType = \"invalid_cache_type\";\nexport const nonBrowserEnvironment = \"non_browser_environment\";\nexport const databaseNotOpen = \"database_not_open\";\nexport const noNetworkConnectivity = \"no_network_connectivity\";\nexport const postRequestFailed = \"post_request_failed\";\nexport const getRequestFailed = \"get_request_failed\";\nexport const failedToParseResponse = \"failed_to_parse_response\";\nexport const unableToLoadToken = \"unable_to_load_token\";\nexport const cryptoKeyNotFound = \"crypto_key_not_found\";\nexport const authCodeRequired = \"auth_code_required\";\nexport const authCodeOrNativeAccountIdRequired =\n \"auth_code_or_nativeAccountId_required\";\nexport const spaCodeAndNativeAccountIdPresent =\n \"spa_code_and_nativeAccountId_present\";\nexport const databaseUnavailable = \"database_unavailable\";\nexport const unableToAcquireTokenFromNativePlatform =\n \"unable_to_acquire_token_from_native_platform\";\nexport const nativeHandshakeTimeout = \"native_handshake_timeout\";\nexport const nativeExtensionNotInstalled = \"native_extension_not_installed\";\nexport const nativeConnectionNotEstablished =\n \"native_connection_not_established\";\nexport const uninitializedPublicClientApplication =\n \"uninitialized_public_client_application\";\nexport const nativePromptNotSupported = \"native_prompt_not_supported\";\nexport const invalidBase64String = \"invalid_base64_string\";\nexport const invalidPopTokenRequest = \"invalid_pop_token_request\";\nexport const failedToBuildHeaders = \"failed_to_build_headers\";\nexport const failedToParseHeaders = \"failed_to_parse_headers\";\nexport const failedToDecryptEarResponse = \"failed_to_decrypt_ear_response\";\nexport const timedOut = \"timed_out\";\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthError } from \"@azure/msal-common/browser\";\nimport * as BrowserAuthErrorCodes from \"./BrowserAuthErrorCodes.js\";\nexport { BrowserAuthErrorCodes }; // Allow importing as \"BrowserAuthErrorCodes\"\n\nconst ErrorLink = \"For more visit: aka.ms/msaljs/browser-errors\";\n\n/**\n * BrowserAuthErrorMessage class containing string constants used by error codes and messages.\n */\nexport const BrowserAuthErrorMessages = {\n [BrowserAuthErrorCodes.pkceNotCreated]:\n \"The PKCE code challenge and verifier could not be generated.\",\n [BrowserAuthErrorCodes.earJwkEmpty]:\n \"No EAR encryption key provided. This is unexpected.\",\n [BrowserAuthErrorCodes.earJweEmpty]:\n \"Server response does not contain ear_jwe property. This is unexpected.\",\n [BrowserAuthErrorCodes.cryptoNonExistent]:\n \"The crypto object or function is not available.\",\n [BrowserAuthErrorCodes.emptyNavigateUri]:\n \"Navigation URI is empty. Please check stack trace for more info.\",\n [BrowserAuthErrorCodes.hashEmptyError]: `Hash value cannot be processed because it is empty. Please verify that your redirectUri is not clearing the hash. ${ErrorLink}`,\n [BrowserAuthErrorCodes.noStateInHash]:\n \"Hash does not contain state. Please verify that the request originated from msal.\",\n [BrowserAuthErrorCodes.hashDoesNotContainKnownProperties]: `Hash does not contain known properites. Please verify that your redirectUri is not changing the hash. ${ErrorLink}`,\n [BrowserAuthErrorCodes.unableToParseState]:\n \"Unable to parse state. Please verify that the request originated from msal.\",\n [BrowserAuthErrorCodes.stateInteractionTypeMismatch]:\n \"Hash contains state but the interaction type does not match the caller.\",\n [BrowserAuthErrorCodes.interactionInProgress]: `Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API. ${ErrorLink}`,\n [BrowserAuthErrorCodes.popupWindowError]:\n \"Error opening popup window. This can happen if you are using IE or if popups are blocked in the browser.\",\n [BrowserAuthErrorCodes.emptyWindowError]:\n \"window.open returned null or undefined window object.\",\n [BrowserAuthErrorCodes.userCancelled]: \"User cancelled the flow.\",\n [BrowserAuthErrorCodes.monitorPopupTimeout]: `Token acquisition in popup failed due to timeout. ${ErrorLink}`,\n [BrowserAuthErrorCodes.monitorWindowTimeout]: `Token acquisition in iframe failed due to timeout. ${ErrorLink}`,\n [BrowserAuthErrorCodes.redirectInIframe]:\n \"Redirects are not supported for iframed or brokered applications. Please ensure you are using MSAL.js in a top frame of the window if using the redirect APIs, or use the popup APIs.\",\n [BrowserAuthErrorCodes.blockIframeReload]: `Request was blocked inside an iframe because MSAL detected an authentication response. ${ErrorLink}`,\n [BrowserAuthErrorCodes.blockNestedPopups]:\n \"Request was blocked inside a popup because MSAL detected it was running in a popup.\",\n [BrowserAuthErrorCodes.iframeClosedPrematurely]:\n \"The iframe being monitored was closed prematurely.\",\n [BrowserAuthErrorCodes.silentLogoutUnsupported]:\n \"Silent logout not supported. Please call logoutRedirect or logoutPopup instead.\",\n [BrowserAuthErrorCodes.noAccountError]:\n \"No account object provided to acquireTokenSilent and no active account has been set. Please call setActiveAccount or provide an account on the request.\",\n [BrowserAuthErrorCodes.silentPromptValueError]:\n \"The value given for the prompt value is not valid for silent requests - must be set to 'none' or 'no_session'.\",\n [BrowserAuthErrorCodes.noTokenRequestCacheError]:\n \"No token request found in cache.\",\n [BrowserAuthErrorCodes.unableToParseTokenRequestCacheError]:\n \"The cached token request could not be parsed.\",\n [BrowserAuthErrorCodes.authRequestNotSetError]:\n \"Auth Request not set. Please ensure initiateAuthRequest was called from the InteractionHandler\",\n [BrowserAuthErrorCodes.invalidCacheType]: \"Invalid cache type\",\n [BrowserAuthErrorCodes.nonBrowserEnvironment]:\n \"Login and token requests are not supported in non-browser environments.\",\n [BrowserAuthErrorCodes.databaseNotOpen]: \"Database is not open!\",\n [BrowserAuthErrorCodes.noNetworkConnectivity]:\n \"No network connectivity. Check your internet connection.\",\n [BrowserAuthErrorCodes.postRequestFailed]:\n \"Network request failed: If the browser threw a CORS error, check that the redirectUri is registered in the Azure App Portal as type 'SPA'\",\n [BrowserAuthErrorCodes.getRequestFailed]:\n \"Network request failed. Please check the network trace to determine root cause.\",\n [BrowserAuthErrorCodes.failedToParseResponse]:\n \"Failed to parse network response. Check network trace.\",\n [BrowserAuthErrorCodes.unableToLoadToken]: \"Error loading token to cache.\",\n [BrowserAuthErrorCodes.cryptoKeyNotFound]:\n \"Cryptographic Key or Keypair not found in browser storage.\",\n [BrowserAuthErrorCodes.authCodeRequired]:\n \"An authorization code must be provided (as the `code` property on the request) to this flow.\",\n [BrowserAuthErrorCodes.authCodeOrNativeAccountIdRequired]:\n \"An authorization code or nativeAccountId must be provided to this flow.\",\n [BrowserAuthErrorCodes.spaCodeAndNativeAccountIdPresent]:\n \"Request cannot contain both spa code and native account id.\",\n [BrowserAuthErrorCodes.databaseUnavailable]:\n \"IndexedDB, which is required for persistent cryptographic key storage, is unavailable. This may be caused by browser privacy features which block persistent storage in third-party contexts.\",\n [BrowserAuthErrorCodes.unableToAcquireTokenFromNativePlatform]: `Unable to acquire token from native platform. ${ErrorLink}`,\n [BrowserAuthErrorCodes.nativeHandshakeTimeout]:\n \"Timed out while attempting to establish connection to browser extension\",\n [BrowserAuthErrorCodes.nativeExtensionNotInstalled]:\n \"Native extension is not installed. If you think this is a mistake call the initialize function.\",\n [BrowserAuthErrorCodes.nativeConnectionNotEstablished]: `Connection to native platform has not been established. Please install a compatible browser extension and run initialize(). ${ErrorLink}`,\n [BrowserAuthErrorCodes.uninitializedPublicClientApplication]: `You must call and await the initialize function before attempting to call any other MSAL API. ${ErrorLink}`,\n [BrowserAuthErrorCodes.nativePromptNotSupported]:\n \"The provided prompt is not supported by the native platform. This request should be routed to the web based flow.\",\n [BrowserAuthErrorCodes.invalidBase64String]:\n \"Invalid base64 encoded string.\",\n [BrowserAuthErrorCodes.invalidPopTokenRequest]:\n \"Invalid PoP token request. The request should not have both a popKid value and signPopToken set to true.\",\n [BrowserAuthErrorCodes.failedToBuildHeaders]:\n \"Failed to build request headers object.\",\n [BrowserAuthErrorCodes.failedToParseHeaders]:\n \"Failed to parse response headers\",\n [BrowserAuthErrorCodes.failedToDecryptEarResponse]:\n \"Failed to decrypt ear response\",\n [BrowserAuthErrorCodes.timedOut]: \"The request timed out.\",\n};\n\n/**\n * BrowserAuthErrorMessage class containing string constants used by error codes and messages.\n * @deprecated Use exported BrowserAuthErrorCodes instead.\n * In your app you can do :\n * ```\n * import { BrowserAuthErrorCodes } from \"@azure/msal-browser\";\n * ```\n */\nexport const BrowserAuthErrorMessage = {\n pkceNotGenerated: {\n code: BrowserAuthErrorCodes.pkceNotCreated,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.pkceNotCreated],\n },\n cryptoDoesNotExist: {\n code: BrowserAuthErrorCodes.cryptoNonExistent,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.cryptoNonExistent],\n },\n emptyNavigateUriError: {\n code: BrowserAuthErrorCodes.emptyNavigateUri,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.emptyNavigateUri],\n },\n hashEmptyError: {\n code: BrowserAuthErrorCodes.hashEmptyError,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.hashEmptyError],\n },\n hashDoesNotContainStateError: {\n code: BrowserAuthErrorCodes.noStateInHash,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.noStateInHash],\n },\n hashDoesNotContainKnownPropertiesError: {\n code: BrowserAuthErrorCodes.hashDoesNotContainKnownProperties,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.hashDoesNotContainKnownProperties\n ],\n },\n unableToParseStateError: {\n code: BrowserAuthErrorCodes.unableToParseState,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.unableToParseState\n ],\n },\n stateInteractionTypeMismatchError: {\n code: BrowserAuthErrorCodes.stateInteractionTypeMismatch,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.stateInteractionTypeMismatch\n ],\n },\n interactionInProgress: {\n code: BrowserAuthErrorCodes.interactionInProgress,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.interactionInProgress\n ],\n },\n popupWindowError: {\n code: BrowserAuthErrorCodes.popupWindowError,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.popupWindowError],\n },\n emptyWindowError: {\n code: BrowserAuthErrorCodes.emptyWindowError,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.emptyWindowError],\n },\n userCancelledError: {\n code: BrowserAuthErrorCodes.userCancelled,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.userCancelled],\n },\n monitorPopupTimeoutError: {\n code: BrowserAuthErrorCodes.monitorPopupTimeout,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.monitorPopupTimeout\n ],\n },\n monitorIframeTimeoutError: {\n code: BrowserAuthErrorCodes.monitorWindowTimeout,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.monitorWindowTimeout\n ],\n },\n redirectInIframeError: {\n code: BrowserAuthErrorCodes.redirectInIframe,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.redirectInIframe],\n },\n blockTokenRequestsInHiddenIframeError: {\n code: BrowserAuthErrorCodes.blockIframeReload,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.blockIframeReload],\n },\n blockAcquireTokenInPopupsError: {\n code: BrowserAuthErrorCodes.blockNestedPopups,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.blockNestedPopups],\n },\n iframeClosedPrematurelyError: {\n code: BrowserAuthErrorCodes.iframeClosedPrematurely,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.iframeClosedPrematurely\n ],\n },\n silentLogoutUnsupportedError: {\n code: BrowserAuthErrorCodes.silentLogoutUnsupported,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.silentLogoutUnsupported\n ],\n },\n noAccountError: {\n code: BrowserAuthErrorCodes.noAccountError,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.noAccountError],\n },\n silentPromptValueError: {\n code: BrowserAuthErrorCodes.silentPromptValueError,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.silentPromptValueError\n ],\n },\n noTokenRequestCacheError: {\n code: BrowserAuthErrorCodes.noTokenRequestCacheError,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.noTokenRequestCacheError\n ],\n },\n unableToParseTokenRequestCacheError: {\n code: BrowserAuthErrorCodes.unableToParseTokenRequestCacheError,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.unableToParseTokenRequestCacheError\n ],\n },\n authRequestNotSet: {\n code: BrowserAuthErrorCodes.authRequestNotSetError,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.authRequestNotSetError\n ],\n },\n invalidCacheType: {\n code: BrowserAuthErrorCodes.invalidCacheType,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.invalidCacheType],\n },\n notInBrowserEnvironment: {\n code: BrowserAuthErrorCodes.nonBrowserEnvironment,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.nonBrowserEnvironment\n ],\n },\n databaseNotOpen: {\n code: BrowserAuthErrorCodes.databaseNotOpen,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.databaseNotOpen],\n },\n noNetworkConnectivity: {\n code: BrowserAuthErrorCodes.noNetworkConnectivity,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.noNetworkConnectivity\n ],\n },\n postRequestFailed: {\n code: BrowserAuthErrorCodes.postRequestFailed,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.postRequestFailed],\n },\n getRequestFailed: {\n code: BrowserAuthErrorCodes.getRequestFailed,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.getRequestFailed],\n },\n failedToParseNetworkResponse: {\n code: BrowserAuthErrorCodes.failedToParseResponse,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.failedToParseResponse\n ],\n },\n unableToLoadTokenError: {\n code: BrowserAuthErrorCodes.unableToLoadToken,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.unableToLoadToken],\n },\n signingKeyNotFoundInStorage: {\n code: BrowserAuthErrorCodes.cryptoKeyNotFound,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.cryptoKeyNotFound],\n },\n authCodeRequired: {\n code: BrowserAuthErrorCodes.authCodeRequired,\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.authCodeRequired],\n },\n authCodeOrNativeAccountRequired: {\n code: BrowserAuthErrorCodes.authCodeOrNativeAccountIdRequired,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.authCodeOrNativeAccountIdRequired\n ],\n },\n spaCodeAndNativeAccountPresent: {\n code: BrowserAuthErrorCodes.spaCodeAndNativeAccountIdPresent,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.spaCodeAndNativeAccountIdPresent\n ],\n },\n databaseUnavailable: {\n code: BrowserAuthErrorCodes.databaseUnavailable,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.databaseUnavailable\n ],\n },\n unableToAcquireTokenFromNativePlatform: {\n code: BrowserAuthErrorCodes.unableToAcquireTokenFromNativePlatform,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.unableToAcquireTokenFromNativePlatform\n ],\n },\n nativeHandshakeTimeout: {\n code: BrowserAuthErrorCodes.nativeHandshakeTimeout,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.nativeHandshakeTimeout\n ],\n },\n nativeExtensionNotInstalled: {\n code: BrowserAuthErrorCodes.nativeExtensionNotInstalled,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.nativeExtensionNotInstalled\n ],\n },\n nativeConnectionNotEstablished: {\n code: BrowserAuthErrorCodes.nativeConnectionNotEstablished,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.nativeConnectionNotEstablished\n ],\n },\n uninitializedPublicClientApplication: {\n code: BrowserAuthErrorCodes.uninitializedPublicClientApplication,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.uninitializedPublicClientApplication\n ],\n },\n nativePromptNotSupported: {\n code: BrowserAuthErrorCodes.nativePromptNotSupported,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.nativePromptNotSupported\n ],\n },\n invalidBase64StringError: {\n code: BrowserAuthErrorCodes.invalidBase64String,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.invalidBase64String\n ],\n },\n invalidPopTokenRequest: {\n code: BrowserAuthErrorCodes.invalidPopTokenRequest,\n desc: BrowserAuthErrorMessages[\n BrowserAuthErrorCodes.invalidPopTokenRequest\n ],\n },\n};\n\n/**\n * Browser library error class thrown by the MSAL.js library for SPAs\n */\nexport class BrowserAuthError extends AuthError {\n constructor(errorCode: string, subError?: string) {\n super(errorCode, BrowserAuthErrorMessages[errorCode], subError);\n\n Object.setPrototypeOf(this, BrowserAuthError.prototype);\n this.name = \"BrowserAuthError\";\n }\n}\n\nexport function createBrowserAuthError(\n errorCode: string,\n subError?: string\n): BrowserAuthError {\n return new BrowserAuthError(errorCode, subError);\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { OIDC_DEFAULT_SCOPES } from \"@azure/msal-common/browser\";\nimport { PopupRequest } from \"../request/PopupRequest.js\";\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\n\n/**\n * Constants\n */\nexport const BrowserConstants = {\n /**\n * Interaction in progress cache value\n */\n INTERACTION_IN_PROGRESS_VALUE: \"interaction_in_progress\",\n /**\n * Invalid grant error code\n */\n INVALID_GRANT_ERROR: \"invalid_grant\",\n /**\n * Default popup window width\n */\n POPUP_WIDTH: 483,\n /**\n * Default popup window height\n */\n POPUP_HEIGHT: 600,\n /**\n * Name of the popup window starts with\n */\n POPUP_NAME_PREFIX: \"msal\",\n /**\n * Default popup monitor poll interval in milliseconds\n */\n DEFAULT_POLL_INTERVAL_MS: 30,\n /**\n * Msal-browser SKU\n */\n MSAL_SKU: \"msal.js.browser\",\n};\n\nexport const PlatformAuthConstants = {\n CHANNEL_ID: \"53ee284d-920a-4b59-9d30-a60315b26836\",\n PREFERRED_EXTENSION_ID: \"ppnbnpeolgkicgegkbkbjmhlideopiji\",\n MATS_TELEMETRY: \"MATS\",\n MICROSOFT_ENTRA_BROKERID: \"MicrosoftEntra\",\n DOM_API_NAME: \"DOM API\",\n PLATFORM_DOM_APIS: \"get-token-and-sign-out\",\n PLATFORM_DOM_PROVIDER: \"PlatformAuthDOMHandler\",\n PLATFORM_EXTENSION_PROVIDER: \"PlatformAuthExtensionHandler\",\n};\n\nexport const NativeExtensionMethod = {\n HandshakeRequest: \"Handshake\",\n HandshakeResponse: \"HandshakeResponse\",\n GetToken: \"GetToken\",\n Response: \"Response\",\n} as const;\nexport type NativeExtensionMethod =\n (typeof NativeExtensionMethod)[keyof typeof NativeExtensionMethod];\n\nexport const BrowserCacheLocation = {\n LocalStorage: \"localStorage\",\n SessionStorage: \"sessionStorage\",\n MemoryStorage: \"memoryStorage\",\n} as const;\nexport type BrowserCacheLocation =\n (typeof BrowserCacheLocation)[keyof typeof BrowserCacheLocation];\n\n/**\n * HTTP Request types supported by MSAL.\n */\nexport const HTTP_REQUEST_TYPE = {\n GET: \"GET\",\n POST: \"POST\",\n} as const;\nexport type HTTP_REQUEST_TYPE =\n (typeof HTTP_REQUEST_TYPE)[keyof typeof HTTP_REQUEST_TYPE];\n\nexport const INTERACTION_TYPE = {\n SIGNIN: \"signin\",\n SIGNOUT: \"signout\",\n} as const;\nexport type INTERACTION_TYPE =\n (typeof INTERACTION_TYPE)[keyof typeof INTERACTION_TYPE];\n\n/**\n * Temporary cache keys for MSAL, deleted after any request.\n */\nexport const TemporaryCacheKeys = {\n ORIGIN_URI: \"request.origin\",\n URL_HASH: \"urlHash\",\n REQUEST_PARAMS: \"request.params\",\n VERIFIER: \"code.verifier\",\n INTERACTION_STATUS_KEY: \"interaction.status\",\n NATIVE_REQUEST: \"request.native\",\n} as const;\nexport type TemporaryCacheKeys =\n (typeof TemporaryCacheKeys)[keyof typeof TemporaryCacheKeys];\n\n/**\n * Cache keys stored in-memory\n */\nexport const InMemoryCacheKeys = {\n WRAPPER_SKU: \"wrapper.sku\",\n WRAPPER_VER: \"wrapper.version\",\n} as const;\nexport type InMemoryCacheKeys =\n (typeof InMemoryCacheKeys)[keyof typeof InMemoryCacheKeys];\n\n/**\n * API Codes for Telemetry purposes.\n * Before adding a new code you must claim it in the MSAL Telemetry tracker as these number spaces are shared across all MSALs\n * 0-99 Silent Flow\n * 800-899 Auth Code Flow\n */\nexport const ApiId = {\n acquireTokenRedirect: 861,\n acquireTokenPopup: 862,\n ssoSilent: 863,\n acquireTokenSilent_authCode: 864,\n handleRedirectPromise: 865,\n acquireTokenByCode: 866,\n acquireTokenSilent_silentFlow: 61,\n logout: 961,\n logoutPopup: 962,\n} as const;\nexport type ApiId = (typeof ApiId)[keyof typeof ApiId];\n\n/*\n * Interaction type of the API - used for state and telemetry\n */\nexport enum InteractionType {\n Redirect = \"redirect\",\n Popup = \"popup\",\n Silent = \"silent\",\n None = \"none\",\n}\n\n/**\n * Types of interaction currently in progress.\n * Used in events in wrapper libraries to invoke functions when certain interaction is in progress or all interactions are complete.\n */\nexport const InteractionStatus = {\n /**\n * Initial status before interaction occurs\n */\n Startup: \"startup\",\n /**\n * Status set when all login calls occuring\n */\n Login: \"login\",\n /**\n * Status set when logout call occuring\n */\n Logout: \"logout\",\n /**\n * Status set for acquireToken calls\n */\n AcquireToken: \"acquireToken\",\n /**\n * Status set for ssoSilent calls\n */\n SsoSilent: \"ssoSilent\",\n /**\n * Status set when handleRedirect in progress\n */\n HandleRedirect: \"handleRedirect\",\n /**\n * Status set when interaction is complete\n */\n None: \"none\",\n} as const;\nexport type InteractionStatus =\n (typeof InteractionStatus)[keyof typeof InteractionStatus];\n\nexport const DEFAULT_REQUEST: RedirectRequest | PopupRequest = {\n scopes: OIDC_DEFAULT_SCOPES,\n};\n\n/**\n * JWK Key Format string (Type MUST be defined for window crypto APIs)\n */\nexport const KEY_FORMAT_JWK = \"jwk\";\n\n// Supported wrapper SKUs\nexport const WrapperSKU = {\n React: \"@azure/msal-react\",\n Angular: \"@azure/msal-angular\",\n} as const;\nexport type WrapperSKU = (typeof WrapperSKU)[keyof typeof WrapperSKU];\n\n// DatabaseStorage Constants\nexport const DB_NAME = \"msal.db\";\nexport const DB_VERSION = 1;\nexport const DB_TABLE_NAME = `${DB_NAME}.keys`;\n\nexport const CacheLookupPolicy = {\n /*\n * acquireTokenSilent will attempt to retrieve an access token from the cache. If the access token is expired\n * or cannot be found the refresh token will be used to acquire a new one. Finally, if the refresh token\n * is expired acquireTokenSilent will attempt to acquire new access and refresh tokens.\n */\n Default: 0, // 0 is falsy, is equivalent to not passing in a CacheLookupPolicy\n /*\n * acquireTokenSilent will only look for access tokens in the cache. It will not attempt to renew access or\n * refresh tokens.\n */\n AccessToken: 1,\n /*\n * acquireTokenSilent will attempt to retrieve an access token from the cache. If the access token is expired or\n * cannot be found, the refresh token will be used to acquire a new one. If the refresh token is expired, it\n * will not be renewed and acquireTokenSilent will fail.\n */\n AccessTokenAndRefreshToken: 2,\n /*\n * acquireTokenSilent will not attempt to retrieve access tokens from the cache and will instead attempt to\n * exchange the cached refresh token for a new access token. If the refresh token is expired, it will not be\n * renewed and acquireTokenSilent will fail.\n */\n RefreshToken: 3,\n /*\n * acquireTokenSilent will not look in the cache for the access token. It will go directly to network with the\n * cached refresh token. If the refresh token is expired an attempt will be made to renew it. This is equivalent to\n * setting \"forceRefresh: true\".\n */\n RefreshTokenAndNetwork: 4,\n /*\n * acquireTokenSilent will attempt to renew both access and refresh tokens. It will not look in the cache. This will\n * always fail if 3rd party cookies are blocked by the browser.\n */\n Skip: 5,\n} as const;\nexport type CacheLookupPolicy =\n (typeof CacheLookupPolicy)[keyof typeof CacheLookupPolicy];\n\nexport const iFrameRenewalPolicies: CacheLookupPolicy[] = [\n CacheLookupPolicy.Default,\n CacheLookupPolicy.Skip,\n CacheLookupPolicy.RefreshTokenAndNetwork,\n];\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Class which exposes APIs to encode plaintext to base64 encoded string. See here for implementation details:\n * https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_JavaScript's_UTF-16_%3E_UTF-8_%3E_base64\n */\n\n/**\n * Returns URL Safe b64 encoded string from a plaintext string.\n * @param input\n */\nexport function urlEncode(input: string): string {\n return encodeURIComponent(\n base64Encode(input)\n .replace(/=/g, \"\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n );\n}\n\n/**\n * Returns URL Safe b64 encoded string from an int8Array.\n * @param inputArr\n */\nexport function urlEncodeArr(inputArr: Uint8Array): string {\n return base64EncArr(inputArr)\n .replace(/=/g, \"\")\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\");\n}\n\n/**\n * Returns b64 encoded string from plaintext string.\n * @param input\n */\nexport function base64Encode(input: string): string {\n return base64EncArr(new TextEncoder().encode(input));\n}\n\n/**\n * Base64 encode byte array\n * @param aBytes\n */\nfunction base64EncArr(aBytes: Uint8Array): string {\n const binString = Array.from(aBytes, (x) => String.fromCodePoint(x)).join(\n \"\"\n );\n return btoa(binString);\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n BrowserAuthErrorCodes,\n createBrowserAuthError,\n} from \"../error/BrowserAuthError.js\";\n\n/**\n * Class which exposes APIs to decode base64 strings to plaintext. See here for implementation details:\n * https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem\n */\n\n/**\n * Returns a URL-safe plaintext decoded string from b64 encoded input.\n * @param input\n */\nexport function base64Decode(input: string): string {\n return new TextDecoder().decode(base64DecToArr(input));\n}\n\n/**\n * Decodes base64 into Uint8Array\n * @param base64String\n */\nexport function base64DecToArr(base64String: string): Uint8Array {\n let encodedString = base64String.replace(/-/g, \"+\").replace(/_/g, \"/\");\n switch (encodedString.length % 4) {\n case 0:\n break;\n case 2:\n encodedString += \"==\";\n break;\n case 3:\n encodedString += \"=\";\n break;\n default:\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.invalidBase64String\n );\n }\n const binString = atob(encodedString);\n return Uint8Array.from(binString, (m) => m.codePointAt(0) || 0);\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport {\n IPerformanceClient,\n PerformanceEvents,\n} from \"@azure/msal-common/browser\";\nimport { KEY_FORMAT_JWK } from \"../utils/BrowserConstants.js\";\nimport { base64Encode, urlEncodeArr } from \"../encode/Base64Encode.js\";\nimport { base64Decode, base64DecToArr } from \"../encode/Base64Decode.js\";\n\n/**\n * This file defines functions used by the browser library to perform cryptography operations such as\n * hashing and encoding. It also has helper functions to validate the availability of specific APIs.\n */\n\n/**\n * See here for more info on RsaHashedKeyGenParams: https://developer.mozilla.org/en-US/docs/Web/API/RsaHashedKeyGenParams\n */\n// Algorithms\nconst PKCS1_V15_KEYGEN_ALG = \"RSASSA-PKCS1-v1_5\";\nconst AES_GCM = \"AES-GCM\";\nconst HKDF = \"HKDF\";\n// SHA-256 hashing algorithm\nconst S256_HASH_ALG = \"SHA-256\";\n// MOD length for PoP tokens\nconst MODULUS_LENGTH = 2048;\n// Public Exponent\nconst PUBLIC_EXPONENT: Uint8Array = new Uint8Array([0x01, 0x00, 0x01]);\n// UUID hex digits\nconst UUID_CHARS = \"0123456789abcdef\";\n// Array to store UINT32 random value\nconst UINT32_ARR = new Uint32Array(1);\n\n// Key Format\nconst RAW = \"raw\";\n// Key Usages\nconst ENCRYPT = \"encrypt\";\nconst DECRYPT = \"decrypt\";\nconst DERIVE_KEY = \"deriveKey\";\n\n// Suberror\nconst SUBTLE_SUBERROR = \"crypto_subtle_undefined\";\n\nconst keygenAlgorithmOptions: RsaHashedKeyGenParams = {\n name: PKCS1_V15_KEYGEN_ALG,\n hash: S256_HASH_ALG,\n modulusLength: MODULUS_LENGTH,\n publicExponent: PUBLIC_EXPONENT,\n};\n\n/**\n * Check whether browser crypto is available.\n */\nexport function validateCryptoAvailable(\n skipValidateSubtleCrypto: boolean\n): void {\n if (!window) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.nonBrowserEnvironment\n );\n }\n if (!window.crypto) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.cryptoNonExistent);\n }\n if (!skipValidateSubtleCrypto && !window.crypto.subtle) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.cryptoNonExistent,\n SUBTLE_SUBERROR\n );\n }\n}\n\n/**\n * Returns a sha-256 hash of the given dataString as an ArrayBuffer.\n * @param dataString {string} data string\n * @param performanceClient {?IPerformanceClient}\n * @param correlationId {?string} correlation id\n */\nexport async function sha256Digest(\n dataString: string,\n performanceClient?: IPerformanceClient,\n correlationId?: string\n): Promise {\n performanceClient?.addQueueMeasurement(\n PerformanceEvents.Sha256Digest,\n correlationId\n );\n const encoder = new TextEncoder();\n const data = encoder.encode(dataString);\n return window.crypto.subtle.digest(\n S256_HASH_ALG,\n data\n ) as Promise;\n}\n\n/**\n * Populates buffer with cryptographically random values.\n * @param dataBuffer\n */\nexport function getRandomValues(dataBuffer: Uint8Array): Uint8Array {\n return window.crypto.getRandomValues(dataBuffer);\n}\n\n/**\n * Returns random Uint32 value.\n * @returns {number}\n */\nfunction getRandomUint32(): number {\n window.crypto.getRandomValues(UINT32_ARR);\n return UINT32_ARR[0];\n}\n\n/**\n * Creates a UUID v7 from the current timestamp.\n * Implementation relies on the system clock to guarantee increasing order of generated identifiers.\n * @returns {number}\n */\nexport function createNewGuid(): string {\n const currentTimestamp = Date.now();\n const baseRand = getRandomUint32() * 0x400 + (getRandomUint32() & 0x3ff);\n\n // Result byte array\n const bytes = new Uint8Array(16);\n // A 12-bit `rand_a` field value\n const randA = Math.trunc(baseRand / 2 ** 30);\n // The higher 30 bits of 62-bit `rand_b` field value\n const randBHi = baseRand & (2 ** 30 - 1);\n // The lower 32 bits of 62-bit `rand_b` field value\n const randBLo = getRandomUint32();\n\n bytes[0] = currentTimestamp / 2 ** 40;\n bytes[1] = currentTimestamp / 2 ** 32;\n bytes[2] = currentTimestamp / 2 ** 24;\n bytes[3] = currentTimestamp / 2 ** 16;\n bytes[4] = currentTimestamp / 2 ** 8;\n bytes[5] = currentTimestamp;\n bytes[6] = 0x70 | (randA >>> 8);\n bytes[7] = randA;\n bytes[8] = 0x80 | (randBHi >>> 24);\n bytes[9] = randBHi >>> 16;\n bytes[10] = randBHi >>> 8;\n bytes[11] = randBHi;\n bytes[12] = randBLo >>> 24;\n bytes[13] = randBLo >>> 16;\n bytes[14] = randBLo >>> 8;\n bytes[15] = randBLo;\n\n let text = \"\";\n for (let i = 0; i < bytes.length; i++) {\n text += UUID_CHARS.charAt(bytes[i] >>> 4);\n text += UUID_CHARS.charAt(bytes[i] & 0xf);\n if (i === 3 || i === 5 || i === 7 || i === 9) {\n text += \"-\";\n }\n }\n return text;\n}\n\n/**\n * Generates a keypair based on current keygen algorithm config.\n * @param extractable\n * @param usages\n */\nexport async function generateKeyPair(\n extractable: boolean,\n usages: Array\n): Promise {\n return window.crypto.subtle.generateKey(\n keygenAlgorithmOptions,\n extractable,\n usages\n ) as Promise;\n}\n\n/**\n * Export key as Json Web Key (JWK)\n * @param key\n */\nexport async function exportJwk(key: CryptoKey): Promise {\n return window.crypto.subtle.exportKey(\n KEY_FORMAT_JWK,\n key\n ) as Promise;\n}\n\n/**\n * Imports key as Json Web Key (JWK), can set extractable and usages.\n * @param key\n * @param extractable\n * @param usages\n */\nexport async function importJwk(\n key: JsonWebKey,\n extractable: boolean,\n usages: Array\n): Promise {\n return window.crypto.subtle.importKey(\n KEY_FORMAT_JWK,\n key,\n keygenAlgorithmOptions,\n extractable,\n usages\n ) as Promise;\n}\n\n/**\n * Signs given data with given key\n * @param key\n * @param data\n */\nexport async function sign(\n key: CryptoKey,\n data: ArrayBuffer\n): Promise {\n return window.crypto.subtle.sign(\n keygenAlgorithmOptions,\n key,\n data\n ) as Promise;\n}\n\n/**\n * Generates Base64 encoded jwk used in the Encrypted Authorize Response (EAR) flow\n */\nexport async function generateEarKey(): Promise {\n const key = await generateBaseKey();\n const keyStr = urlEncodeArr(new Uint8Array(key));\n\n const jwk = {\n alg: \"dir\",\n kty: \"oct\",\n k: keyStr,\n };\n\n return base64Encode(JSON.stringify(jwk));\n}\n\n/**\n * Parses earJwk for encryption key and returns CryptoKey object\n * @param earJwk\n * @returns\n */\nexport async function importEarKey(earJwk: string): Promise {\n const b64DecodedJwk = base64Decode(earJwk);\n const jwkJson = JSON.parse(b64DecodedJwk);\n const rawKey = jwkJson.k;\n const keyBuffer = base64DecToArr(rawKey);\n\n return window.crypto.subtle.importKey(RAW, keyBuffer, AES_GCM, false, [\n DECRYPT,\n ]);\n}\n\n/**\n * Decrypt ear_jwe response returned in the Encrypted Authorize Response (EAR) flow\n * @param earJwk\n * @param earJwe\n * @returns\n */\nexport async function decryptEarResponse(\n earJwk: string,\n earJwe: string\n): Promise {\n const earJweParts = earJwe.split(\".\");\n if (earJweParts.length !== 5) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.failedToDecryptEarResponse,\n \"jwe_length\"\n );\n }\n\n const key = await importEarKey(earJwk).catch(() => {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.failedToDecryptEarResponse,\n \"import_key\"\n );\n });\n\n try {\n const header = new TextEncoder().encode(earJweParts[0]);\n const iv = base64DecToArr(earJweParts[2]);\n const ciphertext = base64DecToArr(earJweParts[3]);\n const tag = base64DecToArr(earJweParts[4]);\n const tagLengthBits = tag.byteLength * 8;\n\n // Concat ciphertext and tag\n const encryptedData = new Uint8Array(ciphertext.length + tag.length);\n encryptedData.set(ciphertext);\n encryptedData.set(tag, ciphertext.length);\n\n const decryptedData = await window.crypto.subtle.decrypt(\n {\n name: AES_GCM,\n iv: iv,\n tagLength: tagLengthBits,\n additionalData: header,\n },\n key,\n encryptedData\n );\n\n return new TextDecoder().decode(decryptedData);\n } catch (e) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.failedToDecryptEarResponse,\n \"decrypt\"\n );\n }\n}\n\n/**\n * Generates symmetric base encryption key. This may be stored as all encryption/decryption keys will be derived from this one.\n */\nexport async function generateBaseKey(): Promise {\n const key = await window.crypto.subtle.generateKey(\n {\n name: AES_GCM,\n length: 256,\n },\n true,\n [ENCRYPT, DECRYPT]\n );\n return window.crypto.subtle.exportKey(RAW, key);\n}\n\n/**\n * Returns the raw key to be passed into the key derivation function\n * @param baseKey\n * @returns\n */\nexport async function generateHKDF(baseKey: ArrayBuffer): Promise {\n return window.crypto.subtle.importKey(RAW, baseKey, HKDF, false, [\n DERIVE_KEY,\n ]);\n}\n\n/**\n * Given a base key and a nonce generates a derived key to be used in encryption and decryption.\n * Note: every time we encrypt a new key is derived\n * @param baseKey\n * @param nonce\n * @returns\n */\nasync function deriveKey(\n baseKey: CryptoKey,\n nonce: ArrayBuffer,\n context: string\n): Promise {\n return window.crypto.subtle.deriveKey(\n {\n name: HKDF,\n salt: nonce,\n hash: S256_HASH_ALG,\n info: new TextEncoder().encode(context),\n },\n baseKey,\n { name: AES_GCM, length: 256 },\n false,\n [ENCRYPT, DECRYPT]\n );\n}\n\n/**\n * Encrypt the given data given a base key. Returns encrypted data and a nonce that must be provided during decryption\n * @param key\n * @param rawData\n */\nexport async function encrypt(\n baseKey: CryptoKey,\n rawData: string,\n context: string\n): Promise<{ data: string; nonce: string }> {\n const encodedData = new TextEncoder().encode(rawData);\n // The nonce must never be reused with a given key.\n const nonce = window.crypto.getRandomValues(new Uint8Array(16));\n const derivedKey = await deriveKey(baseKey, nonce, context);\n const encryptedData = await window.crypto.subtle.encrypt(\n {\n name: AES_GCM,\n iv: new Uint8Array(12), // New key is derived for every encrypt so we don't need a new nonce\n },\n derivedKey,\n encodedData\n );\n\n return {\n data: urlEncodeArr(new Uint8Array(encryptedData)),\n nonce: urlEncodeArr(nonce),\n };\n}\n\n/**\n * Decrypt data with the given key and nonce\n * @param key\n * @param nonce\n * @param encryptedData\n * @returns\n */\nexport async function decrypt(\n baseKey: CryptoKey,\n nonce: string,\n context: string,\n encryptedData: string\n): Promise {\n const encodedData = base64DecToArr(encryptedData);\n const derivedKey = await deriveKey(baseKey, base64DecToArr(nonce), context);\n const decryptedData = await window.crypto.subtle.decrypt(\n {\n name: AES_GCM,\n iv: new Uint8Array(12), // New key is derived for every encrypt so we don't need a new nonce\n },\n derivedKey,\n encodedData\n );\n\n return new TextDecoder().decode(decryptedData);\n}\n\n/**\n * Returns the SHA-256 hash of an input string\n * @param plainText\n */\nexport async function hashString(plainText: string): Promise {\n const hashBuffer: ArrayBuffer = await sha256Digest(plainText);\n const hashBytes = new Uint8Array(hashBuffer);\n return urlEncodeArr(hashBytes);\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const storageNotSupported = \"storage_not_supported\";\nexport const stubbedPublicClientApplicationCalled =\n \"stubbed_public_client_application_called\";\nexport const inMemRedirectUnavailable = \"in_mem_redirect_unavailable\";\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthError } from \"@azure/msal-common/browser\";\nimport * as BrowserConfigurationAuthErrorCodes from \"./BrowserConfigurationAuthErrorCodes.js\";\nexport { BrowserConfigurationAuthErrorCodes };\n\nexport const BrowserConfigurationAuthErrorMessages = {\n [BrowserConfigurationAuthErrorCodes.storageNotSupported]:\n \"Given storage configuration option was not supported.\",\n [BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled]:\n \"Stub instance of Public Client Application was called. If using msal-react, please ensure context is not used without a provider. For more visit: aka.ms/msaljs/browser-errors\",\n [BrowserConfigurationAuthErrorCodes.inMemRedirectUnavailable]:\n \"Redirect cannot be supported. In-memory storage was selected and storeAuthStateInCookie=false, which would cause the library to be unable to handle the incoming hash. If you would like to use the redirect API, please use session/localStorage or set storeAuthStateInCookie=true.\",\n};\n\n/**\n * BrowserAuthErrorMessage class containing string constants used by error codes and messages.\n * @deprecated Use BrowserAuthErrorCodes instead\n */\nexport const BrowserConfigurationAuthErrorMessage = {\n storageNotSupportedError: {\n code: BrowserConfigurationAuthErrorCodes.storageNotSupported,\n desc: BrowserConfigurationAuthErrorMessages[\n BrowserConfigurationAuthErrorCodes.storageNotSupported\n ],\n },\n stubPcaInstanceCalled: {\n code: BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled,\n desc: BrowserConfigurationAuthErrorMessages[\n BrowserConfigurationAuthErrorCodes\n .stubbedPublicClientApplicationCalled\n ],\n },\n inMemRedirectUnavailable: {\n code: BrowserConfigurationAuthErrorCodes.inMemRedirectUnavailable,\n desc: BrowserConfigurationAuthErrorMessages[\n BrowserConfigurationAuthErrorCodes.inMemRedirectUnavailable\n ],\n },\n};\n\n/**\n * Browser library error class thrown by the MSAL.js library for SPAs\n */\nexport class BrowserConfigurationAuthError extends AuthError {\n constructor(errorCode: string, errorMessage?: string) {\n super(errorCode, errorMessage);\n this.name = \"BrowserConfigurationAuthError\";\n\n Object.setPrototypeOf(this, BrowserConfigurationAuthError.prototype);\n }\n}\n\nexport function createBrowserConfigurationAuthError(\n errorCode: string\n): BrowserConfigurationAuthError {\n return new BrowserConfigurationAuthError(\n errorCode,\n BrowserConfigurationAuthErrorMessages[errorCode]\n );\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n UrlString,\n invoke,\n invokeAsync,\n RequestParameterBuilder,\n} from \"@azure/msal-common/browser\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport { BrowserConstants, BrowserCacheLocation } from \"./BrowserConstants.js\";\nimport * as BrowserCrypto from \"../crypto/BrowserCrypto.js\";\nimport {\n BrowserConfigurationAuthErrorCodes,\n createBrowserConfigurationAuthError,\n} from \"../error/BrowserConfigurationAuthError.js\";\nimport type { BrowserConfiguration } from \"../config/Configuration.js\";\n\n/**\n * Clears hash from window url.\n */\nexport function clearHash(contentWindow: Window): void {\n // Office.js sets history.replaceState to null\n contentWindow.location.hash = \"\";\n if (typeof contentWindow.history.replaceState === \"function\") {\n // Full removes \"#\" from url\n contentWindow.history.replaceState(\n null,\n \"\",\n `${contentWindow.location.origin}${contentWindow.location.pathname}${contentWindow.location.search}`\n );\n }\n}\n\n/**\n * Replaces current hash with hash from provided url\n */\nexport function replaceHash(url: string): void {\n const urlParts = url.split(\"#\");\n urlParts.shift(); // Remove part before the hash\n window.location.hash = urlParts.length > 0 ? urlParts.join(\"#\") : \"\";\n}\n\n/**\n * Returns boolean of whether the current window is in an iframe or not.\n */\nexport function isInIframe(): boolean {\n return window.parent !== window;\n}\n\n/**\n * Returns boolean of whether or not the current window is a popup opened by msal\n */\nexport function isInPopup(): boolean {\n return (\n typeof window !== \"undefined\" &&\n !!window.opener &&\n window.opener !== window &&\n typeof window.name === \"string\" &&\n window.name.indexOf(`${BrowserConstants.POPUP_NAME_PREFIX}.`) === 0\n );\n}\n\n// #endregion\n\n/**\n * Returns current window URL as redirect uri\n */\nexport function getCurrentUri(): string {\n return typeof window !== \"undefined\" && window.location\n ? window.location.href.split(\"?\")[0].split(\"#\")[0]\n : \"\";\n}\n\n/**\n * Gets the homepage url for the current window location.\n */\nexport function getHomepage(): string {\n const currentUrl = new UrlString(window.location.href);\n const urlComponents = currentUrl.getUrlComponents();\n return `${urlComponents.Protocol}//${urlComponents.HostNameAndPort}/`;\n}\n\n/**\n * Throws error if we have completed an auth and are\n * attempting another auth request inside an iframe.\n */\nexport function blockReloadInHiddenIframes(): void {\n const isResponseHash = UrlString.hashContainsKnownProperties(\n window.location.hash\n );\n // return an error if called from the hidden iframe created by the msal js silent calls\n if (isResponseHash && isInIframe()) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.blockIframeReload);\n }\n}\n\n/**\n * Block redirect operations in iframes unless explicitly allowed\n * @param interactionType Interaction type for the request\n * @param allowRedirectInIframe Config value to allow redirects when app is inside an iframe\n */\nexport function blockRedirectInIframe(allowRedirectInIframe: boolean): void {\n if (isInIframe() && !allowRedirectInIframe) {\n // If we are not in top frame, we shouldn't redirect. This is also handled by the service.\n throw createBrowserAuthError(BrowserAuthErrorCodes.redirectInIframe);\n }\n}\n\n/**\n * Block redirectUri loaded in popup from calling AcquireToken APIs\n */\nexport function blockAcquireTokenInPopups(): void {\n // Popups opened by msal popup APIs are given a name that starts with \"msal.\"\n if (isInPopup()) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.blockNestedPopups);\n }\n}\n\n/**\n * Throws error if token requests are made in non-browser environment\n * @param isBrowserEnvironment Flag indicating if environment is a browser.\n */\nexport function blockNonBrowserEnvironment(): void {\n if (typeof window === \"undefined\") {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.nonBrowserEnvironment\n );\n }\n}\n\n/**\n * Throws error if initialize hasn't been called\n * @param initialized\n */\nexport function blockAPICallsBeforeInitialize(initialized: boolean): void {\n if (!initialized) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.uninitializedPublicClientApplication\n );\n }\n}\n\n/**\n * Helper to validate app environment before making an auth request\n * @param initialized\n */\nexport function preflightCheck(initialized: boolean): void {\n // Block request if not in browser environment\n blockNonBrowserEnvironment();\n\n // Block auth requests inside a hidden iframe\n blockReloadInHiddenIframes();\n\n // Block redirectUri opened in a popup from calling MSAL APIs\n blockAcquireTokenInPopups();\n\n // Block token acquisition before initialize has been called\n blockAPICallsBeforeInitialize(initialized);\n}\n\n/**\n * Helper to validate app enviornment before making redirect request\n * @param initialized\n * @param config\n */\nexport function redirectPreflightCheck(\n initialized: boolean,\n config: BrowserConfiguration\n): void {\n preflightCheck(initialized);\n blockRedirectInIframe(config.system.allowRedirectInIframe);\n // Block redirects if memory storage is enabled but storeAuthStateInCookie is not\n if (\n config.cache.cacheLocation === BrowserCacheLocation.MemoryStorage &&\n !config.cache.storeAuthStateInCookie\n ) {\n throw createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.inMemRedirectUnavailable\n );\n }\n}\n\n/**\n * Adds a preconnect link element to the header which begins DNS resolution and SSL connection in anticipation of the /token request\n * @param loginDomain Authority domain, including https protocol e.g. https://login.microsoftonline.com\n * @returns\n */\nexport function preconnect(authority: string): void {\n const link = document.createElement(\"link\");\n link.rel = \"preconnect\";\n link.href = new URL(authority).origin;\n link.crossOrigin = \"anonymous\";\n document.head.appendChild(link);\n\n // The browser will close connection if not used within a few seconds, remove element from the header after 10s\n window.setTimeout(() => {\n try {\n document.head.removeChild(link);\n } catch {}\n }, 10000); // 10s Timeout\n}\n\n/**\n * Wrapper function that creates a UUID v7 from the current timestamp.\n * @returns {string}\n */\nexport function createGuid(): string {\n return BrowserCrypto.createNewGuid();\n}\n\nexport { invoke };\nexport { invokeAsync };\nexport const addClientCapabilitiesToClaims =\n RequestParameterBuilder.addClientCapabilitiesToClaims;\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n BrowserAuthErrorCodes,\n createBrowserAuthError,\n} from \"../error/BrowserAuthError.js\";\nimport { INavigationClient } from \"./INavigationClient.js\";\nimport { NavigationOptions } from \"./NavigationOptions.js\";\n\nexport class NavigationClient implements INavigationClient {\n /**\n * Navigates to other pages within the same web application\n * @param url\n * @param options\n */\n navigateInternal(\n url: string,\n options: NavigationOptions\n ): Promise {\n return NavigationClient.defaultNavigateWindow(url, options);\n }\n\n /**\n * Navigates to other pages outside the web application i.e. the Identity Provider\n * @param url\n * @param options\n */\n navigateExternal(\n url: string,\n options: NavigationOptions\n ): Promise {\n return NavigationClient.defaultNavigateWindow(url, options);\n }\n\n /**\n * Default navigation implementation invoked by the internal and external functions\n * @param url\n * @param options\n */\n private static defaultNavigateWindow(\n url: string,\n options: NavigationOptions\n ): Promise {\n if (options.noHistory) {\n window.location.replace(url); // CodeQL [SM03712] Application owner controls the URL. User can't change it.\n } else {\n window.location.assign(url); // CodeQL [SM03712] Application owner controls the URL. User can't change it.\n }\n\n return new Promise((resolve, reject) => {\n setTimeout(() => {\n reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.timedOut,\n \"failed_to_redirect\"\n )\n );\n }, options.timeout);\n });\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n INetworkModule,\n NetworkRequestOptions,\n NetworkResponse,\n createNetworkError,\n} from \"@azure/msal-common/browser\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport { HTTP_REQUEST_TYPE } from \"../utils/BrowserConstants.js\";\n\n/**\n * This class implements the Fetch API for GET and POST requests. See more here: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\n */\nexport class FetchClient implements INetworkModule {\n /**\n * Fetch Client for REST endpoints - Get request\n * @param url\n * @param headers\n * @param body\n */\n async sendGetRequestAsync(\n url: string,\n options?: NetworkRequestOptions\n ): Promise> {\n let response: Response;\n let responseHeaders: Record = {};\n let responseStatus = 0;\n const reqHeaders = getFetchHeaders(options);\n try {\n response = await fetch(url, {\n method: HTTP_REQUEST_TYPE.GET,\n headers: reqHeaders,\n });\n } catch (e) {\n throw createNetworkError(\n createBrowserAuthError(\n window.navigator.onLine\n ? BrowserAuthErrorCodes.getRequestFailed\n : BrowserAuthErrorCodes.noNetworkConnectivity\n ),\n undefined,\n undefined,\n e as Error\n );\n }\n\n responseHeaders = getHeaderDict(response.headers);\n try {\n responseStatus = response.status;\n return {\n headers: responseHeaders,\n body: (await response.json()) as T,\n status: responseStatus,\n };\n } catch (e) {\n throw createNetworkError(\n createBrowserAuthError(\n BrowserAuthErrorCodes.failedToParseResponse\n ),\n responseStatus,\n responseHeaders,\n e as Error\n );\n }\n }\n\n /**\n * Fetch Client for REST endpoints - Post request\n * @param url\n * @param headers\n * @param body\n */\n async sendPostRequestAsync(\n url: string,\n options?: NetworkRequestOptions\n ): Promise> {\n const reqBody = (options && options.body) || \"\";\n const reqHeaders = getFetchHeaders(options);\n\n let response: Response;\n let responseStatus = 0;\n let responseHeaders: Record = {};\n try {\n response = await fetch(url, {\n method: HTTP_REQUEST_TYPE.POST,\n headers: reqHeaders,\n body: reqBody,\n });\n } catch (e) {\n throw createNetworkError(\n createBrowserAuthError(\n window.navigator.onLine\n ? BrowserAuthErrorCodes.postRequestFailed\n : BrowserAuthErrorCodes.noNetworkConnectivity\n ),\n undefined,\n undefined,\n e as Error\n );\n }\n\n responseHeaders = getHeaderDict(response.headers);\n try {\n responseStatus = response.status;\n return {\n headers: responseHeaders,\n body: (await response.json()) as T,\n status: responseStatus,\n };\n } catch (e) {\n throw createNetworkError(\n createBrowserAuthError(\n BrowserAuthErrorCodes.failedToParseResponse\n ),\n responseStatus,\n responseHeaders,\n e as Error\n );\n }\n }\n}\n\n/**\n * Get Fetch API Headers object from string map\n * @param inputHeaders\n */\nfunction getFetchHeaders(options?: NetworkRequestOptions): Headers {\n try {\n const headers = new Headers();\n if (!(options && options.headers)) {\n return headers;\n }\n const optionsHeaders = options.headers;\n Object.entries(optionsHeaders).forEach(([key, value]) => {\n headers.append(key, value);\n });\n return headers;\n } catch (e) {\n throw createNetworkError(\n createBrowserAuthError(BrowserAuthErrorCodes.failedToBuildHeaders),\n undefined,\n undefined,\n e as Error\n );\n }\n}\n\n/**\n * Returns object representing response headers\n * @param headers\n * @returns\n */\nfunction getHeaderDict(headers: Headers): Record {\n try {\n const headerDict: Record = {};\n headers.forEach((value: string, key: string) => {\n headerDict[key] = value;\n });\n return headerDict;\n } catch (e) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.failedToParseHeaders\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n SystemOptions,\n LoggerOptions,\n INetworkModule,\n DEFAULT_SYSTEM_OPTIONS,\n Constants,\n ProtocolMode,\n OIDCOptions,\n ServerResponseType,\n LogLevel,\n StubbedNetworkModule,\n AzureCloudInstance,\n AzureCloudOptions,\n ApplicationTelemetry,\n createClientConfigurationError,\n ClientConfigurationErrorCodes,\n IPerformanceClient,\n StubPerformanceClient,\n Logger,\n} from \"@azure/msal-common/browser\";\nimport {\n BrowserCacheLocation,\n BrowserConstants,\n} from \"../utils/BrowserConstants.js\";\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\nimport { NavigationClient } from \"../navigation/NavigationClient.js\";\nimport { FetchClient } from \"../network/FetchClient.js\";\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\n\n// Default timeout for popup windows and iframes in milliseconds\nexport const DEFAULT_POPUP_TIMEOUT_MS = 60000;\nexport const DEFAULT_IFRAME_TIMEOUT_MS = 10000;\nexport const DEFAULT_REDIRECT_TIMEOUT_MS = 30000;\nexport const DEFAULT_NATIVE_BROKER_HANDSHAKE_TIMEOUT_MS = 2000;\n\n/**\n * Use this to configure the auth options in the Configuration object\n */\nexport type BrowserAuthOptions = {\n /**\n * Client ID of your app registered with our Application registration portal : https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredAppsPreview in Microsoft Identity Platform\n */\n clientId: string;\n /**\n * You can configure a specific authority, defaults to \" \" or \"https://login.microsoftonline.com/common\"\n */\n authority?: string;\n /**\n * An array of URIs that are known to be valid. Used in B2C scenarios.\n */\n knownAuthorities?: Array;\n /**\n * A string containing the cloud discovery response. Used in AAD scenarios.\n */\n cloudDiscoveryMetadata?: string;\n /**\n * A string containing the .well-known/openid-configuration endpoint response\n */\n authorityMetadata?: string;\n /**\n * The redirect URI where authentication responses can be received by your application. It must exactly match one of the redirect URIs registered in the Azure portal.\n */\n redirectUri?: string;\n /**\n * The redirect URI where the window navigates after a successful logout.\n */\n postLogoutRedirectUri?: string | null;\n /**\n * Boolean indicating whether to navigate to the original request URL after the auth server navigates to the redirect URL.\n */\n navigateToLoginRequestUrl?: boolean;\n /**\n * Array of capabilities which will be added to the claims.access_token.xms_cc request property on every network request.\n */\n clientCapabilities?: Array;\n /**\n * Enum that represents the protocol that msal follows. Used for configuring proper endpoints.\n */\n protocolMode?: ProtocolMode;\n /**\n * Enum that configures options for the OIDC protocol mode.\n */\n OIDCOptions?: OIDCOptions;\n /**\n * Enum that represents the Azure Cloud to use.\n */\n azureCloudOptions?: AzureCloudOptions;\n /**\n * Flag of whether to use the local metadata cache\n */\n skipAuthorityMetadataCache?: boolean;\n /**\n * App supports nested app auth or not; defaults to\n *\n * @deprecated This flag is deprecated and will be removed in the next major version. createNestablePublicClientApplication should be used instead.\n */\n supportsNestedAppAuth?: boolean;\n /**\n * Callback that will be passed the url that MSAL will navigate to in redirect flows. Returning false in the callback will stop navigation.\n */\n onRedirectNavigate?: (url: string) => boolean | void;\n /**\n * Flag of whether the STS will send back additional parameters to specify where the tokens should be retrieved from.\n */\n instanceAware?: boolean;\n /**\n * Flag of whether to encode query parameters\n * @deprecated This flag is deprecated and will be removed in the next major version where all extra query params will be encoded by default.\n */\n encodeExtraQueryParams?: boolean;\n};\n\n/** @internal */\nexport type InternalAuthOptions = Omit<\n Required,\n \"onRedirectNavigate\"\n> & {\n OIDCOptions: Required;\n onRedirectNavigate?: (url: string) => boolean | void;\n};\n\n/**\n * Use this to configure the below cache configuration options:\n */\nexport type CacheOptions = {\n /**\n * Used to specify the cacheLocation user wants to set. Valid values are \"localStorage\", \"sessionStorage\" and \"memoryStorage\".\n */\n cacheLocation?: BrowserCacheLocation | string;\n /**\n * Used to specify the number of days cache entries written by previous versions of MSAL.js should be retained in the browser. Defaults to 5 days.\n */\n cacheRetentionDays?: number;\n /**\n * Used to specify the temporaryCacheLocation user wants to set. Valid values are \"localStorage\", \"sessionStorage\" and \"memoryStorage\".\n * @deprecated This option is deprecated and will be removed in the next major version.\n */\n temporaryCacheLocation?: BrowserCacheLocation | string;\n /**\n * If set, MSAL stores the auth request state required for validation of the auth flows in the browser cookies. By default this flag is set to false.\n * @deprecated This option is deprecated and will be removed in the next major version.\n */\n storeAuthStateInCookie?: boolean;\n /**\n * If set, MSAL sets the \"Secure\" flag on cookies so they can only be sent over HTTPS. By default this flag is set to true.\n * @deprecated This option will be removed in the next major version and all cookies set will include the Secure attribute.\n */\n secureCookies?: boolean;\n /**\n * If set, MSAL will attempt to migrate cache entries from older versions on initialization. By default this flag is set to true if cacheLocation is localStorage, otherwise false.\n * @deprecated This option is deprecated and will be removed in the next major version.\n */\n cacheMigrationEnabled?: boolean;\n /**\n * Flag that determines whether access tokens are stored based on requested claims\n * @deprecated This option is deprecated and will be removed in the next major version.\n */\n claimsBasedCachingEnabled?: boolean;\n};\n\nexport type BrowserSystemOptions = SystemOptions & {\n /**\n * Used to initialize the Logger object (See ClientConfiguration.ts)\n */\n loggerOptions?: LoggerOptions;\n /**\n * Network interface implementation\n */\n networkClient?: INetworkModule;\n /**\n * Override the methods used to navigate to other webpages. Particularly useful if you are using a client-side router\n */\n navigationClient?: INavigationClient;\n /**\n * Sets the timeout for waiting for a response hash in a popup. Will take precedence over loadFrameTimeout if both are set.\n */\n windowHashTimeout?: number;\n /**\n * Sets the timeout for waiting for a response hash in an iframe. Will take precedence over loadFrameTimeout if both are set.\n */\n iframeHashTimeout?: number;\n /**\n * Sets the timeout for waiting for a response hash in an iframe or popup\n */\n loadFrameTimeout?: number;\n /**\n * Maximum time the library should wait for a frame to load\n * @deprecated This was previously needed for older browsers which are no longer supported by MSAL.js. This option will be removed in the next major version\n */\n navigateFrameWait?: number;\n /**\n * Time to wait for redirection to occur before resolving promise\n */\n redirectNavigationTimeout?: number;\n /**\n * Sets whether popups are opened asynchronously. By default, this flag is set to false. When set to false, blank popups are opened before anything else happens. When set to true, popups are opened when making the network request.\n */\n asyncPopups?: boolean;\n /**\n * Flag to enable redirect opertaions when the app is rendered in an iframe (to support scenarios such as embedded B2C login).\n */\n allowRedirectInIframe?: boolean;\n /**\n * Flag to enable native broker support (e.g. acquiring tokens from WAM on Windows, MacBroker on Mac)\n */\n allowPlatformBroker?: boolean;\n /**\n * Sets the timeout for waiting for the native broker handshake to resolve\n */\n nativeBrokerHandshakeTimeout?: number;\n /**\n * Sets the interval length in milliseconds for polling the location attribute in popup windows (default is 30ms)\n */\n pollIntervalMilliseconds?: number;\n};\n\n/**\n * Telemetry Options\n */\nexport type BrowserTelemetryOptions = {\n /**\n * Telemetry information sent on request\n * - appName: Unique string name of an application\n * - appVersion: Version of the application using MSAL\n */\n application?: ApplicationTelemetry;\n\n client?: IPerformanceClient;\n};\n\n/**\n * This object allows you to configure important elements of MSAL functionality and is passed into the constructor of PublicClientApplication\n */\nexport type Configuration = {\n /**\n * This is where you configure auth elements like clientID, authority used for authenticating against the Microsoft Identity Platform\n */\n auth: BrowserAuthOptions;\n /**\n * This is where you configure cache location and whether to store cache in cookies\n */\n cache?: CacheOptions;\n /**\n * This is where you can configure the network client, logger, token renewal offset\n */\n system?: BrowserSystemOptions;\n /**\n * This is where you can configure telemetry data and options\n */\n telemetry?: BrowserTelemetryOptions;\n};\n\n/** @internal */\nexport type BrowserConfiguration = {\n auth: InternalAuthOptions;\n cache: Required;\n system: Required;\n telemetry: Required;\n};\n\n/**\n * MSAL function that sets the default options when not explicitly configured from app developer\n *\n * @param auth\n * @param cache\n * @param system\n *\n * @returns Configuration object\n */\nexport function buildConfiguration(\n {\n auth: userInputAuth,\n cache: userInputCache,\n system: userInputSystem,\n telemetry: userInputTelemetry,\n }: Configuration,\n isBrowserEnvironment: boolean\n): BrowserConfiguration {\n // Default auth options for browser\n const DEFAULT_AUTH_OPTIONS: InternalAuthOptions = {\n clientId: Constants.EMPTY_STRING,\n authority: `${Constants.DEFAULT_AUTHORITY}`,\n knownAuthorities: [],\n cloudDiscoveryMetadata: Constants.EMPTY_STRING,\n authorityMetadata: Constants.EMPTY_STRING,\n redirectUri:\n typeof window !== \"undefined\" ? BrowserUtils.getCurrentUri() : \"\",\n postLogoutRedirectUri: Constants.EMPTY_STRING,\n navigateToLoginRequestUrl: true,\n clientCapabilities: [],\n protocolMode: ProtocolMode.AAD,\n OIDCOptions: {\n serverResponseType: ServerResponseType.FRAGMENT,\n defaultScopes: [\n Constants.OPENID_SCOPE,\n Constants.PROFILE_SCOPE,\n Constants.OFFLINE_ACCESS_SCOPE,\n ],\n },\n azureCloudOptions: {\n azureCloudInstance: AzureCloudInstance.None,\n tenant: Constants.EMPTY_STRING,\n },\n skipAuthorityMetadataCache: false,\n supportsNestedAppAuth: false,\n instanceAware: false,\n encodeExtraQueryParams: false,\n };\n\n // Default cache options for browser\n const DEFAULT_CACHE_OPTIONS: Required = {\n cacheLocation: BrowserCacheLocation.SessionStorage,\n cacheRetentionDays: 5,\n temporaryCacheLocation: BrowserCacheLocation.SessionStorage,\n storeAuthStateInCookie: false,\n secureCookies: false,\n // Default cache migration to true if cache location is localStorage since entries are preserved across tabs/windows. Migration has little to no benefit in sessionStorage and memoryStorage\n cacheMigrationEnabled:\n userInputCache &&\n userInputCache.cacheLocation === BrowserCacheLocation.LocalStorage\n ? true\n : false,\n claimsBasedCachingEnabled: false,\n };\n\n // Default logger options for browser\n const DEFAULT_LOGGER_OPTIONS: LoggerOptions = {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n loggerCallback: (): void => {\n // allow users to not set logger call back\n },\n logLevel: LogLevel.Info,\n piiLoggingEnabled: false,\n };\n\n // Default system options for browser\n const DEFAULT_BROWSER_SYSTEM_OPTIONS: Required = {\n ...DEFAULT_SYSTEM_OPTIONS,\n loggerOptions: DEFAULT_LOGGER_OPTIONS,\n networkClient: isBrowserEnvironment\n ? new FetchClient()\n : StubbedNetworkModule,\n navigationClient: new NavigationClient(),\n loadFrameTimeout: 0,\n // If loadFrameTimeout is provided, use that as default.\n windowHashTimeout:\n userInputSystem?.loadFrameTimeout || DEFAULT_POPUP_TIMEOUT_MS,\n iframeHashTimeout:\n userInputSystem?.loadFrameTimeout || DEFAULT_IFRAME_TIMEOUT_MS,\n navigateFrameWait: 0,\n redirectNavigationTimeout: DEFAULT_REDIRECT_TIMEOUT_MS,\n asyncPopups: false,\n allowRedirectInIframe: false,\n allowPlatformBroker: false,\n nativeBrokerHandshakeTimeout:\n userInputSystem?.nativeBrokerHandshakeTimeout ||\n DEFAULT_NATIVE_BROKER_HANDSHAKE_TIMEOUT_MS,\n pollIntervalMilliseconds: BrowserConstants.DEFAULT_POLL_INTERVAL_MS,\n };\n\n const providedSystemOptions: Required = {\n ...DEFAULT_BROWSER_SYSTEM_OPTIONS,\n ...userInputSystem,\n loggerOptions: userInputSystem?.loggerOptions || DEFAULT_LOGGER_OPTIONS,\n };\n\n const DEFAULT_TELEMETRY_OPTIONS: Required = {\n application: {\n appName: Constants.EMPTY_STRING,\n appVersion: Constants.EMPTY_STRING,\n },\n client: new StubPerformanceClient(),\n };\n\n // Throw an error if user has set OIDCOptions without being in OIDC protocol mode\n if (\n userInputAuth?.protocolMode !== ProtocolMode.OIDC &&\n userInputAuth?.OIDCOptions\n ) {\n const logger = new Logger(providedSystemOptions.loggerOptions);\n logger.warning(\n JSON.stringify(\n createClientConfigurationError(\n ClientConfigurationErrorCodes.cannotSetOIDCOptions\n )\n )\n );\n }\n\n // Throw an error if user has set allowPlatformBroker to true with OIDC protocol mode\n if (\n userInputAuth?.protocolMode &&\n userInputAuth.protocolMode === ProtocolMode.OIDC &&\n providedSystemOptions?.allowPlatformBroker\n ) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.cannotAllowPlatformBroker\n );\n }\n\n const overlayedConfig: BrowserConfiguration = {\n auth: {\n ...DEFAULT_AUTH_OPTIONS,\n ...userInputAuth,\n OIDCOptions: {\n ...DEFAULT_AUTH_OPTIONS.OIDCOptions,\n ...userInputAuth?.OIDCOptions,\n },\n },\n cache: { ...DEFAULT_CACHE_OPTIONS, ...userInputCache },\n system: providedSystemOptions,\n telemetry: { ...DEFAULT_TELEMETRY_OPTIONS, ...userInputTelemetry },\n };\n\n return overlayedConfig;\n}\n", "/* eslint-disable header/header */\nexport const name = \"@azure/msal-browser\";\nexport const version = \"4.22.1\";\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const PREFIX = \"msal\";\nconst BROWSER_PREFIX = \"browser\";\nexport const CACHE_KEY_SEPARATOR = \"-\";\nexport const CREDENTIAL_SCHEMA_VERSION = 1;\nexport const ACCOUNT_SCHEMA_VERSION = 1;\n\nexport const LOG_LEVEL_CACHE_KEY = `${PREFIX}.${BROWSER_PREFIX}.log.level`;\nexport const LOG_PII_CACHE_KEY = `${PREFIX}.${BROWSER_PREFIX}.log.pii`;\nexport const BROWSER_PERF_ENABLED_KEY = `${PREFIX}.${BROWSER_PREFIX}.performance.enabled`;\nexport const PLATFORM_AUTH_DOM_SUPPORT = `${PREFIX}.${BROWSER_PREFIX}.platform.auth.dom`;\nexport const VERSION_CACHE_KEY = `${PREFIX}.version`;\nexport const ACCOUNT_KEYS = \"account.keys\";\nexport const TOKEN_KEYS = \"token.keys\";\n\nexport function getAccountKeysCacheKey(\n schema: number = ACCOUNT_SCHEMA_VERSION\n): string {\n if (schema < 1) {\n return `${PREFIX}.${ACCOUNT_KEYS}`;\n }\n\n return `${PREFIX}.${schema}.${ACCOUNT_KEYS}`;\n}\n\nexport function getTokenKeysCacheKey(\n clientId: string,\n schema: number = CREDENTIAL_SCHEMA_VERSION\n): string {\n if (schema < 1) {\n return `${PREFIX}.${TOKEN_KEYS}.${clientId}`;\n }\n\n return `${PREFIX}.${schema}.${TOKEN_KEYS}.${clientId}`;\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Logger, LogLevel } from \"@azure/msal-common/browser\";\nimport {\n BrowserConfiguration,\n buildConfiguration,\n Configuration,\n} from \"../config/Configuration.js\";\nimport { version, name } from \"../packageMetadata.js\";\nimport { BrowserCacheLocation } from \"../utils/BrowserConstants.js\";\nimport { LOG_LEVEL_CACHE_KEY, LOG_PII_CACHE_KEY } from \"../cache/CacheKeys.js\";\n\n/**\n * Base class for operating context\n * Operating contexts are contexts in which MSAL.js is being run\n * More than one operating context may be available at a time\n * It's important from a logging and telemetry point of view for us to be able to identify the operating context.\n * For example: Some operating contexts will pre-cache tokens impacting performance telemetry\n */\nexport abstract class BaseOperatingContext {\n protected logger: Logger;\n protected config: BrowserConfiguration;\n protected available: boolean;\n protected browserEnvironment: boolean;\n\n protected static loggerCallback(level: LogLevel, message: string): void {\n switch (level) {\n case LogLevel.Error:\n // eslint-disable-next-line no-console\n console.error(message);\n return;\n case LogLevel.Info:\n // eslint-disable-next-line no-console\n console.info(message);\n return;\n case LogLevel.Verbose:\n // eslint-disable-next-line no-console\n console.debug(message);\n return;\n case LogLevel.Warning:\n // eslint-disable-next-line no-console\n console.warn(message);\n return;\n default:\n // eslint-disable-next-line no-console\n console.log(message);\n return;\n }\n }\n\n constructor(config: Configuration) {\n /*\n * If loaded in an environment where window is not available,\n * set internal flag to false so that further requests fail.\n * This is to support server-side rendering environments.\n */\n this.browserEnvironment = typeof window !== \"undefined\";\n this.config = buildConfiguration(config, this.browserEnvironment);\n\n let sessionStorage: Storage | undefined;\n try {\n sessionStorage = window[BrowserCacheLocation.SessionStorage];\n // Mute errors if it's a non-browser environment or cookies are blocked.\n } catch (e) {}\n\n const logLevelKey = sessionStorage?.getItem(LOG_LEVEL_CACHE_KEY);\n const piiLoggingKey = sessionStorage\n ?.getItem(LOG_PII_CACHE_KEY)\n ?.toLowerCase();\n\n const piiLoggingEnabled =\n piiLoggingKey === \"true\"\n ? true\n : piiLoggingKey === \"false\"\n ? false\n : undefined;\n const loggerOptions = { ...this.config.system.loggerOptions };\n\n const logLevel =\n logLevelKey && Object.keys(LogLevel).includes(logLevelKey)\n ? LogLevel[logLevelKey]\n : undefined;\n if (logLevel) {\n loggerOptions.loggerCallback = BaseOperatingContext.loggerCallback;\n loggerOptions.logLevel = logLevel;\n }\n if (piiLoggingEnabled !== undefined) {\n loggerOptions.piiLoggingEnabled = piiLoggingEnabled;\n }\n\n this.logger = new Logger(loggerOptions, name, version);\n this.available = false;\n }\n\n /**\n * returns the name of the module containing the API controller associated with this operating context\n */\n abstract getModuleName(): string;\n\n /**\n * returns the string identifier of this operating context\n */\n abstract getId(): string;\n\n /**\n * returns a boolean indicating whether this operating context is present\n */\n abstract initialize(): Promise;\n\n /**\n * Return the MSAL config\n * @returns BrowserConfiguration\n */\n getConfig(): BrowserConfiguration {\n return this.config;\n }\n\n /**\n * Returns the MSAL Logger\n * @returns Logger\n */\n getLogger(): Logger {\n return this.logger;\n }\n\n isAvailable(): boolean {\n return this.available;\n }\n\n isBrowserEnvironment(): boolean {\n return this.browserEnvironment;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const BridgeStatusCode = {\n UserInteractionRequired: \"USER_INTERACTION_REQUIRED\",\n UserCancel: \"USER_CANCEL\",\n NoNetwork: \"NO_NETWORK\",\n TransientError: \"TRANSIENT_ERROR\",\n PersistentError: \"PERSISTENT_ERROR\",\n Disabled: \"DISABLED\",\n AccountUnavailable: \"ACCOUNT_UNAVAILABLE\",\n NestedAppAuthUnavailable: \"NESTED_APP_AUTH_UNAVAILABLE\", // NAA is unavailable in the current context, can retry with standard browser based auth\n} as const;\nexport type BridgeStatusCode =\n (typeof BridgeStatusCode)[keyof typeof BridgeStatusCode];\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthBridge, AuthBridgeResponse } from \"./AuthBridge.js\";\nimport { AuthResult } from \"./AuthResult.js\";\nimport { BridgeCapabilities } from \"./BridgeCapabilities.js\";\nimport { AccountContext } from \"./BridgeAccountContext.js\";\nimport { BridgeError } from \"./BridgeError.js\";\nimport { BridgeRequest } from \"./BridgeRequest.js\";\nimport {\n BridgeRequestEnvelope,\n BridgeMethods,\n} from \"./BridgeRequestEnvelope.js\";\nimport { BridgeResponseEnvelope } from \"./BridgeResponseEnvelope.js\";\nimport { BridgeStatusCode } from \"./BridgeStatusCode.js\";\nimport { IBridgeProxy } from \"./IBridgeProxy.js\";\nimport { InitContext } from \"./InitContext.js\";\nimport { TokenRequest } from \"./TokenRequest.js\";\nimport * as BrowserCrypto from \"../crypto/BrowserCrypto.js\";\nimport { BrowserConstants } from \"../utils/BrowserConstants.js\";\nimport { version } from \"../packageMetadata.js\";\n\ndeclare global {\n interface Window {\n nestedAppAuthBridge: AuthBridge;\n }\n}\n\n/**\n * BridgeProxy\n * Provides a proxy for accessing a bridge to a host app and/or\n * platform broker\n */\nexport class BridgeProxy implements IBridgeProxy {\n static bridgeRequests: BridgeRequest[] = [];\n sdkName: string;\n sdkVersion: string;\n capabilities?: BridgeCapabilities;\n accountContext?: AccountContext;\n\n /**\n * initializeNestedAppAuthBridge - Initializes the bridge to the host app\n * @returns a promise that resolves to an InitializeBridgeResponse or rejects with an Error\n * @remarks This method will be called by the create factory method\n * @remarks If the bridge is not available, this method will throw an error\n */\n protected static async initializeNestedAppAuthBridge(): Promise {\n if (window === undefined) {\n throw new Error(\"window is undefined\");\n }\n if (window.nestedAppAuthBridge === undefined) {\n throw new Error(\"window.nestedAppAuthBridge is undefined\");\n }\n\n try {\n window.nestedAppAuthBridge.addEventListener(\n \"message\",\n (response: AuthBridgeResponse) => {\n const responsePayload =\n typeof response === \"string\" ? response : response.data;\n const responseEnvelope: BridgeResponseEnvelope =\n JSON.parse(responsePayload);\n const request = BridgeProxy.bridgeRequests.find(\n (element) =>\n element.requestId === responseEnvelope.requestId\n );\n if (request !== undefined) {\n BridgeProxy.bridgeRequests.splice(\n BridgeProxy.bridgeRequests.indexOf(request),\n 1\n );\n if (responseEnvelope.success) {\n request.resolve(responseEnvelope);\n } else {\n request.reject(responseEnvelope.error);\n }\n }\n }\n );\n\n const bridgeResponse = await new Promise(\n (resolve, reject) => {\n const message = BridgeProxy.buildRequest(\"GetInitContext\");\n\n const request: BridgeRequest = {\n requestId: message.requestId,\n method: message.method,\n resolve: resolve,\n reject: reject,\n };\n BridgeProxy.bridgeRequests.push(request);\n window.nestedAppAuthBridge.postMessage(\n JSON.stringify(message)\n );\n }\n );\n\n return BridgeProxy.validateBridgeResultOrThrow(\n bridgeResponse.initContext\n );\n } catch (error) {\n window.console.log(error);\n throw error;\n }\n }\n\n /**\n * getTokenInteractive - Attempts to get a token interactively from the bridge\n * @param request A token request\n * @returns a promise that resolves to an auth result or rejects with a BridgeError\n */\n public getTokenInteractive(request: TokenRequest): Promise {\n return this.getToken(\"GetTokenPopup\", request);\n }\n\n /**\n * getTokenSilent Attempts to get a token silently from the bridge\n * @param request A token request\n * @returns a promise that resolves to an auth result or rejects with a BridgeError\n */\n public getTokenSilent(request: TokenRequest): Promise {\n return this.getToken(\"GetToken\", request);\n }\n\n private async getToken(\n requestType: BridgeMethods,\n request: TokenRequest\n ): Promise {\n const result = await this.sendRequest(requestType, {\n tokenParams: request,\n });\n return {\n token: BridgeProxy.validateBridgeResultOrThrow(result.token),\n account: BridgeProxy.validateBridgeResultOrThrow(result.account),\n };\n }\n\n public getHostCapabilities(): BridgeCapabilities | null {\n return this.capabilities ?? null;\n }\n\n public getAccountContext(): AccountContext | null {\n return this.accountContext ? this.accountContext : null;\n }\n\n private static buildRequest(\n method: BridgeMethods,\n requestParams?: Partial\n ): BridgeRequestEnvelope {\n return {\n messageType: \"NestedAppAuthRequest\",\n method: method,\n requestId: BrowserCrypto.createNewGuid(),\n sendTime: Date.now(),\n clientLibrary: BrowserConstants.MSAL_SKU,\n clientLibraryVersion: version,\n ...requestParams,\n };\n }\n\n /**\n * A method used to send a request to the bridge\n * @param request A token request\n * @returns a promise that resolves to a response of provided type or rejects with a BridgeError\n */\n private sendRequest(\n method: BridgeMethods,\n requestParams?: Partial\n ): Promise {\n const message = BridgeProxy.buildRequest(method, requestParams);\n\n const promise = new Promise(\n (resolve, reject) => {\n const request: BridgeRequest = {\n requestId: message.requestId,\n method: message.method,\n resolve: resolve,\n reject: reject,\n };\n BridgeProxy.bridgeRequests.push(request);\n window.nestedAppAuthBridge.postMessage(JSON.stringify(message));\n }\n );\n\n return promise;\n }\n\n private static validateBridgeResultOrThrow(input: T | undefined): T {\n if (input === undefined) {\n const bridgeError: BridgeError = {\n status: BridgeStatusCode.NestedAppAuthUnavailable,\n };\n throw bridgeError;\n }\n return input;\n }\n\n /**\n * Private constructor for BridgeProxy\n * @param sdkName The name of the SDK being used to make requests on behalf of the app\n * @param sdkVersion The version of the SDK being used to make requests on behalf of the app\n * @param capabilities The capabilities of the bridge / SDK / platform broker\n */\n private constructor(\n sdkName: string,\n sdkVersion: string,\n accountContext?: AccountContext,\n capabilities?: BridgeCapabilities\n ) {\n this.sdkName = sdkName;\n this.sdkVersion = sdkVersion;\n this.accountContext = accountContext;\n this.capabilities = capabilities;\n }\n\n /**\n * Factory method for creating an implementation of IBridgeProxy\n * @returns A promise that resolves to a BridgeProxy implementation\n */\n public static async create(): Promise {\n const response = await BridgeProxy.initializeNestedAppAuthBridge();\n return new BridgeProxy(\n response.sdkName,\n response.sdkVersion,\n response.accountContext,\n response.capabilities\n );\n }\n}\n\nexport default BridgeProxy;\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { BaseOperatingContext } from \"./BaseOperatingContext.js\";\nimport { IBridgeProxy } from \"../naa/IBridgeProxy.js\";\nimport { BridgeProxy } from \"../naa/BridgeProxy.js\";\nimport { AccountContext } from \"../naa/BridgeAccountContext.js\";\n\ndeclare global {\n interface Window {\n __initializeNestedAppAuth?(): Promise;\n }\n}\n\nexport class NestedAppOperatingContext extends BaseOperatingContext {\n protected bridgeProxy: IBridgeProxy | undefined = undefined;\n protected accountContext: AccountContext | null = null;\n\n /*\n * TODO: Once we have determine the bundling code return here to specify the name of the bundle\n * containing the implementation for this operating context\n */\n static readonly MODULE_NAME: string = \"\";\n\n /**\n * Unique identifier for the operating context\n */\n static readonly ID: string = \"NestedAppOperatingContext\";\n\n /**\n * Return the module name. Intended for use with import() to enable dynamic import\n * of the implementation associated with this operating context\n * @returns\n */\n getModuleName(): string {\n return NestedAppOperatingContext.MODULE_NAME;\n }\n\n /**\n * Returns the unique identifier for this operating context\n * @returns string\n */\n getId(): string {\n return NestedAppOperatingContext.ID;\n }\n\n /**\n * Returns the current BridgeProxy\n * @returns IBridgeProxy | undefined\n */\n getBridgeProxy(): IBridgeProxy | undefined {\n return this.bridgeProxy;\n }\n\n /**\n * Checks whether the operating context is available.\n * Confirms that the code is running a browser rather. This is required.\n * @returns Promise indicating whether this operating context is currently available.\n */\n async initialize(): Promise {\n try {\n if (typeof window !== \"undefined\") {\n if (typeof window.__initializeNestedAppAuth === \"function\") {\n await window.__initializeNestedAppAuth();\n }\n\n const bridgeProxy: IBridgeProxy = await BridgeProxy.create();\n /*\n * Because we want single sign on we expect the host app to provide the account context\n * with a min set of params that can be used to identify the account\n * this.account = nestedApp.getAccountByFilter(bridgeProxy.getAccountContext());\n */\n this.accountContext = bridgeProxy.getAccountContext();\n this.bridgeProxy = bridgeProxy;\n this.available = bridgeProxy !== undefined;\n }\n } catch (ex) {\n this.logger.infoPii(\n `Could not initialize Nested App Auth bridge (${ex})`\n );\n }\n\n this.logger.info(`Nested App Auth Bridge available: ${this.available}`);\n return this.available;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { BaseOperatingContext } from \"./BaseOperatingContext.js\";\n\nexport class StandardOperatingContext extends BaseOperatingContext {\n /*\n * TODO: Once we have determine the bundling code return here to specify the name of the bundle\n * containing the implementation for this operating context\n */\n static readonly MODULE_NAME: string = \"\";\n\n /**\n * Unique identifier for the operating context\n */\n static readonly ID: string = \"StandardOperatingContext\";\n\n /**\n * Return the module name. Intended for use with import() to enable dynamic import\n * of the implementation associated with this operating context\n * @returns\n */\n getModuleName(): string {\n return StandardOperatingContext.MODULE_NAME;\n }\n\n /**\n * Returns the unique identifier for this operating context\n * @returns string\n */\n getId(): string {\n return StandardOperatingContext.ID;\n }\n\n /**\n * Checks whether the operating context is available.\n * Confirms that the code is running a browser rather. This is required.\n * @returns Promise indicating whether this operating context is currently available.\n */\n async initialize(): Promise {\n this.available = typeof window !== \"undefined\";\n return this.available;\n /*\n * NOTE: The standard context is available as long as there is a window. If/when we split out WAM from Browser\n * We can move the current contents of the initialize method to here and verify that the WAM extension is available\n */\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport {\n DB_NAME,\n DB_TABLE_NAME,\n DB_VERSION,\n} from \"../utils/BrowserConstants.js\";\nimport { IAsyncStorage } from \"./IAsyncStorage.js\";\n\ninterface IDBOpenDBRequestEvent extends Event {\n target: IDBOpenDBRequest & EventTarget;\n}\n\ninterface IDBOpenOnUpgradeNeededEvent extends IDBVersionChangeEvent {\n target: IDBOpenDBRequest & EventTarget;\n}\n\ninterface IDBRequestEvent extends Event {\n target: IDBRequest & EventTarget;\n}\n\n/**\n * Storage wrapper for IndexedDB storage in browsers: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API\n */\nexport class DatabaseStorage implements IAsyncStorage {\n private db: IDBDatabase | undefined;\n private dbName: string;\n private tableName: string;\n private version: number;\n private dbOpen: boolean;\n\n constructor() {\n this.dbName = DB_NAME;\n this.version = DB_VERSION;\n this.tableName = DB_TABLE_NAME;\n this.dbOpen = false;\n }\n\n /**\n * Opens IndexedDB instance.\n */\n async open(): Promise {\n return new Promise((resolve, reject) => {\n const openDB = window.indexedDB.open(this.dbName, this.version);\n openDB.addEventListener(\n \"upgradeneeded\",\n (e: IDBVersionChangeEvent) => {\n const event = e as IDBOpenOnUpgradeNeededEvent;\n event.target.result.createObjectStore(this.tableName);\n }\n );\n openDB.addEventListener(\"success\", (e: Event) => {\n const event = e as IDBOpenDBRequestEvent;\n this.db = event.target.result;\n this.dbOpen = true;\n resolve();\n });\n openDB.addEventListener(\"error\", () =>\n reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.databaseUnavailable\n )\n )\n );\n });\n }\n\n /**\n * Closes the connection to IndexedDB database when all pending transactions\n * complete.\n */\n closeConnection(): void {\n const db = this.db;\n if (db && this.dbOpen) {\n db.close();\n this.dbOpen = false;\n }\n }\n\n /**\n * Opens database if it's not already open\n */\n private async validateDbIsOpen(): Promise {\n if (!this.dbOpen) {\n return this.open();\n }\n }\n\n /**\n * Retrieves item from IndexedDB instance.\n * @param key\n */\n async getItem(key: string): Promise {\n await this.validateDbIsOpen();\n return new Promise((resolve, reject) => {\n // TODO: Add timeouts?\n if (!this.db) {\n return reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.databaseNotOpen\n )\n );\n }\n const transaction = this.db.transaction(\n [this.tableName],\n \"readonly\"\n );\n const objectStore = transaction.objectStore(this.tableName);\n const dbGet = objectStore.get(key);\n\n dbGet.addEventListener(\"success\", (e: Event) => {\n const event = e as IDBRequestEvent;\n this.closeConnection();\n resolve(event.target.result);\n });\n\n dbGet.addEventListener(\"error\", (e: Event) => {\n this.closeConnection();\n reject(e);\n });\n });\n }\n\n /**\n * Adds item to IndexedDB under given key\n * @param key\n * @param payload\n */\n async setItem(key: string, payload: T): Promise {\n await this.validateDbIsOpen();\n return new Promise((resolve: Function, reject: Function) => {\n // TODO: Add timeouts?\n if (!this.db) {\n return reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.databaseNotOpen\n )\n );\n }\n const transaction = this.db.transaction(\n [this.tableName],\n \"readwrite\"\n );\n\n const objectStore = transaction.objectStore(this.tableName);\n\n const dbPut = objectStore.put(payload, key);\n\n dbPut.addEventListener(\"success\", () => {\n this.closeConnection();\n resolve();\n });\n\n dbPut.addEventListener(\"error\", (e) => {\n this.closeConnection();\n reject(e);\n });\n });\n }\n\n /**\n * Removes item from IndexedDB under given key\n * @param key\n */\n async removeItem(key: string): Promise {\n await this.validateDbIsOpen();\n return new Promise((resolve: Function, reject: Function) => {\n if (!this.db) {\n return reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.databaseNotOpen\n )\n );\n }\n\n const transaction = this.db.transaction(\n [this.tableName],\n \"readwrite\"\n );\n const objectStore = transaction.objectStore(this.tableName);\n const dbDelete = objectStore.delete(key);\n\n dbDelete.addEventListener(\"success\", () => {\n this.closeConnection();\n resolve();\n });\n\n dbDelete.addEventListener(\"error\", (e) => {\n this.closeConnection();\n reject(e);\n });\n });\n }\n\n /**\n * Get all the keys from the storage object as an iterable array of strings.\n */\n async getKeys(): Promise {\n await this.validateDbIsOpen();\n return new Promise((resolve: Function, reject: Function) => {\n if (!this.db) {\n return reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.databaseNotOpen\n )\n );\n }\n\n const transaction = this.db.transaction(\n [this.tableName],\n \"readonly\"\n );\n const objectStore = transaction.objectStore(this.tableName);\n const dbGetKeys = objectStore.getAllKeys();\n\n dbGetKeys.addEventListener(\"success\", (e: Event) => {\n const event = e as IDBRequestEvent;\n this.closeConnection();\n resolve(event.target.result);\n });\n\n dbGetKeys.addEventListener(\"error\", (e: Event) => {\n this.closeConnection();\n reject(e);\n });\n });\n }\n\n /**\n *\n * Checks whether there is an object under the search key in the object store\n */\n async containsKey(key: string): Promise {\n await this.validateDbIsOpen();\n\n return new Promise((resolve: Function, reject: Function) => {\n if (!this.db) {\n return reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.databaseNotOpen\n )\n );\n }\n\n const transaction = this.db.transaction(\n [this.tableName],\n \"readonly\"\n );\n const objectStore = transaction.objectStore(this.tableName);\n const dbContainsKey = objectStore.count(key);\n\n dbContainsKey.addEventListener(\"success\", (e: Event) => {\n const event = e as IDBRequestEvent;\n this.closeConnection();\n resolve(event.target.result === 1);\n });\n\n dbContainsKey.addEventListener(\"error\", (e: Event) => {\n this.closeConnection();\n reject(e);\n });\n });\n }\n\n /**\n * Deletes the MSAL database. The database is deleted rather than cleared to make it possible\n * for client applications to downgrade to a previous MSAL version without worrying about forward compatibility issues\n * with IndexedDB database versions.\n */\n async deleteDatabase(): Promise {\n // Check if database being deleted exists\n\n if (this.db && this.dbOpen) {\n this.closeConnection();\n }\n\n return new Promise((resolve: Function, reject: Function) => {\n const deleteDbRequest = window.indexedDB.deleteDatabase(DB_NAME);\n const id = setTimeout(() => reject(false), 200); // Reject if events aren't raised within 200ms\n deleteDbRequest.addEventListener(\"success\", () => {\n clearTimeout(id);\n return resolve(true);\n });\n deleteDbRequest.addEventListener(\"blocked\", () => {\n clearTimeout(id);\n return resolve(true);\n });\n deleteDbRequest.addEventListener(\"error\", () => {\n clearTimeout(id);\n return reject(false);\n });\n });\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IWindowStorage } from \"./IWindowStorage.js\";\n\nexport class MemoryStorage implements IWindowStorage {\n private cache: Map;\n\n constructor() {\n this.cache = new Map();\n }\n\n async initialize(): Promise {\n // Memory storage does not require initialization\n }\n\n getItem(key: string): T | null {\n return this.cache.get(key) || null;\n }\n\n getUserData(key: string): T | null {\n return this.getItem(key);\n }\n\n setItem(key: string, value: T): void {\n this.cache.set(key, value);\n }\n\n async setUserData(key: string, value: T): Promise {\n this.setItem(key, value);\n }\n\n removeItem(key: string): void {\n this.cache.delete(key);\n }\n\n getKeys(): string[] {\n const cacheKeys: string[] = [];\n this.cache.forEach((value: T, key: string) => {\n cacheKeys.push(key);\n });\n return cacheKeys;\n }\n\n containsKey(key: string): boolean {\n return this.cache.has(key);\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n decryptData(): Promise {\n // Memory storage does not support encryption, so this method is a no-op\n return Promise.resolve(null);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Logger } from \"@azure/msal-common/browser\";\nimport {\n BrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport { DatabaseStorage } from \"./DatabaseStorage.js\";\nimport { IAsyncStorage } from \"./IAsyncStorage.js\";\nimport { MemoryStorage } from \"./MemoryStorage.js\";\n\n/**\n * This class allows MSAL to store artifacts asynchronously using the DatabaseStorage IndexedDB wrapper,\n * backed up with the more volatile MemoryStorage object for cases in which IndexedDB may be unavailable.\n */\nexport class AsyncMemoryStorage implements IAsyncStorage {\n private inMemoryCache: MemoryStorage;\n private indexedDBCache: DatabaseStorage;\n private logger: Logger;\n\n constructor(logger: Logger) {\n this.inMemoryCache = new MemoryStorage();\n this.indexedDBCache = new DatabaseStorage();\n this.logger = logger;\n }\n\n private handleDatabaseAccessError(error: unknown): void {\n if (\n error instanceof BrowserAuthError &&\n error.errorCode === BrowserAuthErrorCodes.databaseUnavailable\n ) {\n this.logger.error(\n \"Could not access persistent storage. This may be caused by browser privacy features which block persistent storage in third-party contexts.\"\n );\n } else {\n throw error;\n }\n }\n /**\n * Get the item matching the given key. Tries in-memory cache first, then in the asynchronous\n * storage object if item isn't found in-memory.\n * @param key\n */\n async getItem(key: string): Promise {\n const item = this.inMemoryCache.getItem(key);\n if (!item) {\n try {\n this.logger.verbose(\n \"Queried item not found in in-memory cache, now querying persistent storage.\"\n );\n return await this.indexedDBCache.getItem(key);\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n return item;\n }\n\n /**\n * Sets the item in the in-memory cache and then tries to set it in the asynchronous\n * storage object with the given key.\n * @param key\n * @param value\n */\n async setItem(key: string, value: T): Promise {\n this.inMemoryCache.setItem(key, value);\n try {\n await this.indexedDBCache.setItem(key, value);\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n\n /**\n * Removes the item matching the key from the in-memory cache, then tries to remove it from the asynchronous storage object.\n * @param key\n */\n async removeItem(key: string): Promise {\n this.inMemoryCache.removeItem(key);\n try {\n await this.indexedDBCache.removeItem(key);\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n\n /**\n * Get all the keys from the in-memory cache as an iterable array of strings. If no keys are found, query the keys in the\n * asynchronous storage object.\n */\n async getKeys(): Promise {\n const cacheKeys = this.inMemoryCache.getKeys();\n if (cacheKeys.length === 0) {\n try {\n this.logger.verbose(\n \"In-memory cache is empty, now querying persistent storage.\"\n );\n return await this.indexedDBCache.getKeys();\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n return cacheKeys;\n }\n\n /**\n * Returns true or false if the given key is present in the cache.\n * @param key\n */\n async containsKey(key: string): Promise {\n const containsKey = this.inMemoryCache.containsKey(key);\n if (!containsKey) {\n try {\n this.logger.verbose(\n \"Key not found in in-memory cache, now querying persistent storage.\"\n );\n return await this.indexedDBCache.containsKey(key);\n } catch (e) {\n this.handleDatabaseAccessError(e);\n }\n }\n return containsKey;\n }\n\n /**\n * Clears in-memory Map\n */\n clearInMemory(): void {\n // InMemory cache is a Map instance, clear is straightforward\n this.logger.verbose(`Deleting in-memory keystore`);\n this.inMemoryCache.clear();\n this.logger.verbose(`In-memory keystore deleted`);\n }\n\n /**\n * Tries to delete the IndexedDB database\n * @returns\n */\n async clearPersistent(): Promise {\n try {\n this.logger.verbose(\"Deleting persistent keystore\");\n const dbDeleted = await this.indexedDBCache.deleteDatabase();\n if (dbDeleted) {\n this.logger.verbose(\"Persistent keystore deleted\");\n }\n\n return dbDeleted;\n } catch (e) {\n this.handleDatabaseAccessError(e);\n return false;\n }\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n ICrypto,\n IPerformanceClient,\n JoseHeader,\n Logger,\n PerformanceEvents,\n ShrOptions,\n SignedHttpRequest,\n SignedHttpRequestParameters,\n} from \"@azure/msal-common/browser\";\nimport {\n base64Encode,\n urlEncode,\n urlEncodeArr,\n} from \"../encode/Base64Encode.js\";\nimport { base64Decode } from \"../encode/Base64Decode.js\";\nimport * as BrowserCrypto from \"./BrowserCrypto.js\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport { AsyncMemoryStorage } from \"../cache/AsyncMemoryStorage.js\";\n\nexport type CachedKeyPair = {\n publicKey: CryptoKey;\n privateKey: CryptoKey;\n requestMethod?: string;\n requestUri?: string;\n};\n\n/**\n * This class implements MSAL's crypto interface, which allows it to perform base64 encoding and decoding, generating cryptographically random GUIDs and\n * implementing Proof Key for Code Exchange specs for the OAuth Authorization Code Flow using PKCE (rfc here: https://tools.ietf.org/html/rfc7636).\n */\nexport class CryptoOps implements ICrypto {\n private logger: Logger;\n\n /**\n * CryptoOps can be used in contexts outside a PCA instance,\n * meaning there won't be a performance manager available.\n */\n private performanceClient: IPerformanceClient | undefined;\n\n private static POP_KEY_USAGES: Array = [\"sign\", \"verify\"];\n private static EXTRACTABLE: boolean = true;\n private cache: AsyncMemoryStorage;\n\n constructor(\n logger: Logger,\n performanceClient?: IPerformanceClient,\n skipValidateSubtleCrypto?: boolean\n ) {\n this.logger = logger;\n // Browser crypto needs to be validated first before any other classes can be set.\n BrowserCrypto.validateCryptoAvailable(\n skipValidateSubtleCrypto ?? false\n );\n this.cache = new AsyncMemoryStorage(this.logger);\n this.performanceClient = performanceClient;\n }\n\n /**\n * Creates a new random GUID - used to populate state and nonce.\n * @returns string (GUID)\n */\n createNewGuid(): string {\n return BrowserCrypto.createNewGuid();\n }\n\n /**\n * Encodes input string to base64.\n * @param input\n */\n base64Encode(input: string): string {\n return base64Encode(input);\n }\n\n /**\n * Decodes input string from base64.\n * @param input\n */\n base64Decode(input: string): string {\n return base64Decode(input);\n }\n\n /**\n * Encodes input string to base64 URL safe string.\n * @param input\n */\n base64UrlEncode(input: string): string {\n return urlEncode(input);\n }\n\n /**\n * Stringifies and base64Url encodes input public key\n * @param inputKid\n * @returns Base64Url encoded public key\n */\n encodeKid(inputKid: string): string {\n return this.base64UrlEncode(JSON.stringify({ kid: inputKid }));\n }\n\n /**\n * Generates a keypair, stores it and returns a thumbprint\n * @param request\n */\n async getPublicKeyThumbprint(\n request: SignedHttpRequestParameters\n ): Promise {\n const publicKeyThumbMeasurement =\n this.performanceClient?.startMeasurement(\n PerformanceEvents.CryptoOptsGetPublicKeyThumbprint,\n request.correlationId\n );\n\n // Generate Keypair\n const keyPair: CryptoKeyPair = await BrowserCrypto.generateKeyPair(\n CryptoOps.EXTRACTABLE,\n CryptoOps.POP_KEY_USAGES\n );\n\n // Generate Thumbprint for Public Key\n const publicKeyJwk: JsonWebKey = await BrowserCrypto.exportJwk(\n keyPair.publicKey\n );\n\n const pubKeyThumprintObj: JsonWebKey = {\n e: publicKeyJwk.e,\n kty: publicKeyJwk.kty,\n n: publicKeyJwk.n,\n };\n\n const publicJwkString: string =\n getSortedObjectString(pubKeyThumprintObj);\n const publicJwkHash = await this.hashString(publicJwkString);\n\n // Generate Thumbprint for Private Key\n const privateKeyJwk: JsonWebKey = await BrowserCrypto.exportJwk(\n keyPair.privateKey\n );\n // Re-import private key to make it unextractable\n const unextractablePrivateKey: CryptoKey =\n await BrowserCrypto.importJwk(privateKeyJwk, false, [\"sign\"]);\n\n // Store Keypair data in keystore\n await this.cache.setItem(publicJwkHash, {\n privateKey: unextractablePrivateKey,\n publicKey: keyPair.publicKey,\n requestMethod: request.resourceRequestMethod,\n requestUri: request.resourceRequestUri,\n });\n\n if (publicKeyThumbMeasurement) {\n publicKeyThumbMeasurement.end({\n success: true,\n });\n }\n\n return publicJwkHash;\n }\n\n /**\n * Removes cryptographic keypair from key store matching the keyId passed in\n * @param kid\n */\n async removeTokenBindingKey(kid: string): Promise {\n await this.cache.removeItem(kid);\n const keyFound = await this.cache.containsKey(kid);\n if (keyFound) {\n throw createClientAuthError(\n ClientAuthErrorCodes.bindingKeyNotRemoved\n );\n }\n }\n\n /**\n * Removes all cryptographic keys from IndexedDB storage\n */\n async clearKeystore(): Promise {\n // Delete in-memory keystores\n this.cache.clearInMemory();\n\n /**\n * There is only one database, so calling clearPersistent on asymmetric keystore takes care of\n * every persistent keystore\n */\n try {\n await this.cache.clearPersistent();\n return true;\n } catch (e) {\n if (e instanceof Error) {\n this.logger.error(\n `Clearing keystore failed with error: ${e.message}`\n );\n } else {\n this.logger.error(\n \"Clearing keystore failed with unknown error\"\n );\n }\n\n return false;\n }\n }\n\n /**\n * Signs the given object as a jwt payload with private key retrieved by given kid.\n * @param payload\n * @param kid\n */\n async signJwt(\n payload: SignedHttpRequest,\n kid: string,\n shrOptions?: ShrOptions,\n correlationId?: string\n ): Promise {\n const signJwtMeasurement = this.performanceClient?.startMeasurement(\n PerformanceEvents.CryptoOptsSignJwt,\n correlationId\n );\n const cachedKeyPair = await this.cache.getItem(kid);\n\n if (!cachedKeyPair) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.cryptoKeyNotFound\n );\n }\n\n // Get public key as JWK\n const publicKeyJwk = await BrowserCrypto.exportJwk(\n cachedKeyPair.publicKey\n );\n const publicKeyJwkString = getSortedObjectString(publicKeyJwk);\n // Base64URL encode public key thumbprint with keyId only: BASE64URL({ kid: \"FULL_PUBLIC_KEY_HASH\" })\n const encodedKeyIdThumbprint = urlEncode(JSON.stringify({ kid: kid }));\n // Generate header\n const shrHeader = JoseHeader.getShrHeaderString({\n ...shrOptions?.header,\n alg: publicKeyJwk.alg,\n kid: encodedKeyIdThumbprint,\n });\n\n const encodedShrHeader = urlEncode(shrHeader);\n\n // Generate payload\n payload.cnf = {\n jwk: JSON.parse(publicKeyJwkString),\n };\n const encodedPayload = urlEncode(JSON.stringify(payload));\n\n // Form token string\n const tokenString = `${encodedShrHeader}.${encodedPayload}`;\n\n // Sign token\n const encoder = new TextEncoder();\n const tokenBuffer = encoder.encode(tokenString);\n const signatureBuffer = await BrowserCrypto.sign(\n cachedKeyPair.privateKey,\n tokenBuffer\n );\n const encodedSignature = urlEncodeArr(new Uint8Array(signatureBuffer));\n\n const signedJwt = `${tokenString}.${encodedSignature}`;\n\n if (signJwtMeasurement) {\n signJwtMeasurement.end({\n success: true,\n });\n }\n\n return signedJwt;\n }\n\n /**\n * Returns the SHA-256 hash of an input string\n * @param plainText\n */\n async hashString(plainText: string): Promise {\n return BrowserCrypto.hashString(plainText);\n }\n}\n\nfunction getSortedObjectString(obj: object): string {\n return JSON.stringify(obj, Object.keys(obj).sort());\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ClientAuthErrorCodes,\n createClientAuthError,\n} from \"@azure/msal-common/browser\";\nimport { IWindowStorage } from \"./IWindowStorage.js\";\n\n// Cookie life calculation (hours * minutes * seconds * ms)\nconst COOKIE_LIFE_MULTIPLIER = 24 * 60 * 60 * 1000;\n\nexport const SameSiteOptions = {\n Lax: \"Lax\",\n None: \"None\",\n} as const;\nexport type SameSiteOptions =\n (typeof SameSiteOptions)[keyof typeof SameSiteOptions];\n\nexport class CookieStorage implements IWindowStorage {\n initialize(): Promise {\n return Promise.resolve();\n }\n\n getItem(key: string): string | null {\n const name = `${encodeURIComponent(key)}`;\n const cookieList = document.cookie.split(\";\");\n for (let i = 0; i < cookieList.length; i++) {\n const cookie = cookieList[i];\n const [key, ...rest] = decodeURIComponent(cookie).trim().split(\"=\");\n const value = rest.join(\"=\");\n\n if (key === name) {\n return value;\n }\n }\n return \"\";\n }\n\n getUserData(): string | null {\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\n }\n\n setItem(\n key: string,\n value: string,\n cookieLifeDays?: number,\n secure: boolean = true,\n sameSite: SameSiteOptions = SameSiteOptions.Lax\n ): void {\n let cookieStr = `${encodeURIComponent(key)}=${encodeURIComponent(\n value\n )};path=/;SameSite=${sameSite};`;\n\n if (cookieLifeDays) {\n const expireTime = getCookieExpirationTime(cookieLifeDays);\n cookieStr += `expires=${expireTime};`;\n }\n\n if (secure || sameSite === SameSiteOptions.None) {\n // SameSite None requires Secure flag\n cookieStr += \"Secure;\";\n }\n\n document.cookie = cookieStr;\n }\n\n async setUserData(): Promise {\n return Promise.reject(\n createClientAuthError(ClientAuthErrorCodes.methodNotImplemented)\n );\n }\n\n removeItem(key: string): void {\n // Setting expiration to -1 removes it\n this.setItem(key, \"\", -1);\n }\n\n getKeys(): string[] {\n const cookieList = document.cookie.split(\";\");\n const keys: Array = [];\n cookieList.forEach((cookie) => {\n const cookieParts = decodeURIComponent(cookie).trim().split(\"=\");\n keys.push(cookieParts[0]);\n });\n\n return keys;\n }\n\n containsKey(key: string): boolean {\n return this.getKeys().includes(key);\n }\n\n decryptData(): Promise {\n // Cookie storage does not support encryption, so this method is a no-op\n return Promise.resolve(null);\n }\n}\n\n/**\n * Get cookie expiration time\n * @param cookieLifeDays\n */\nexport function getCookieExpirationTime(cookieLifeDays: number): string {\n const today = new Date();\n const expr = new Date(\n today.getTime() + cookieLifeDays * COOKIE_LIFE_MULTIPLIER\n );\n return expr.toUTCString();\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TokenKeys } from \"@azure/msal-common/browser\";\nimport { IWindowStorage } from \"./IWindowStorage.js\";\nimport * as CacheKeys from \"./CacheKeys.js\";\n\n/**\n * Returns a list of cache keys for all known accounts\n * @param storage\n * @returns\n */\nexport function getAccountKeys(\n storage: IWindowStorage,\n schemaVersion?: number\n): Array {\n const accountKeys = storage.getItem(\n CacheKeys.getAccountKeysCacheKey(schemaVersion)\n );\n if (accountKeys) {\n return JSON.parse(accountKeys);\n }\n\n return [];\n}\n\n/**\n * Returns a list of cache keys for all known tokens\n * @param clientId\n * @param storage\n * @returns\n */\nexport function getTokenKeys(\n clientId: string,\n storage: IWindowStorage,\n schemaVersion?: number\n): TokenKeys {\n const item = storage.getItem(\n CacheKeys.getTokenKeysCacheKey(clientId, schemaVersion)\n );\n if (item) {\n const tokenKeys = JSON.parse(item);\n if (\n tokenKeys &&\n tokenKeys.hasOwnProperty(\"idToken\") &&\n tokenKeys.hasOwnProperty(\"accessToken\") &&\n tokenKeys.hasOwnProperty(\"refreshToken\")\n ) {\n return tokenKeys as TokenKeys;\n }\n }\n\n return {\n idToken: [],\n accessToken: [],\n refreshToken: [],\n };\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport type EncryptedData = {\n id: string;\n nonce: string;\n data: string;\n lastUpdatedAt: string;\n};\n\nexport function isEncrypted(data: object): data is EncryptedData {\n return (\n data.hasOwnProperty(\"id\") &&\n data.hasOwnProperty(\"nonce\") &&\n data.hasOwnProperty(\"data\")\n );\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n TokenKeys,\n IPerformanceClient,\n invokeAsync,\n PerformanceEvents,\n Logger,\n invoke,\n} from \"@azure/msal-common/browser\";\nimport {\n createNewGuid,\n decrypt,\n encrypt,\n generateBaseKey,\n generateHKDF,\n} from \"../crypto/BrowserCrypto.js\";\nimport { base64DecToArr } from \"../encode/Base64Decode.js\";\nimport { urlEncodeArr } from \"../encode/Base64Encode.js\";\nimport {\n BrowserAuthErrorCodes,\n createBrowserAuthError,\n} from \"../error/BrowserAuthError.js\";\nimport {\n BrowserConfigurationAuthErrorCodes,\n createBrowserConfigurationAuthError,\n} from \"../error/BrowserConfigurationAuthError.js\";\nimport { CookieStorage, SameSiteOptions } from \"./CookieStorage.js\";\nimport { IWindowStorage } from \"./IWindowStorage.js\";\nimport { MemoryStorage } from \"./MemoryStorage.js\";\nimport { getAccountKeys, getTokenKeys } from \"./CacheHelpers.js\";\nimport * as CacheKeys from \"./CacheKeys.js\";\nimport { EncryptedData, isEncrypted } from \"./EncryptedData.js\";\n\nconst ENCRYPTION_KEY = \"msal.cache.encryption\";\nconst BROADCAST_CHANNEL_NAME = \"msal.broadcast.cache\";\n\ntype EncryptionCookie = {\n id: string;\n key: CryptoKey;\n};\n\nexport class LocalStorage implements IWindowStorage {\n private clientId: string;\n private initialized: boolean;\n private memoryStorage: MemoryStorage;\n private performanceClient: IPerformanceClient;\n private logger: Logger;\n private encryptionCookie?: EncryptionCookie;\n private broadcast: BroadcastChannel;\n\n constructor(\n clientId: string,\n logger: Logger,\n performanceClient: IPerformanceClient\n ) {\n if (!window.localStorage) {\n throw createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.storageNotSupported\n );\n }\n this.memoryStorage = new MemoryStorage();\n this.initialized = false;\n this.clientId = clientId;\n this.logger = logger;\n this.performanceClient = performanceClient;\n this.broadcast = new BroadcastChannel(BROADCAST_CHANNEL_NAME);\n }\n\n async initialize(correlationId: string): Promise {\n const cookies = new CookieStorage();\n const cookieString = cookies.getItem(ENCRYPTION_KEY);\n let parsedCookie = { key: \"\", id: \"\" };\n if (cookieString) {\n try {\n parsedCookie = JSON.parse(cookieString);\n } catch (e) {}\n }\n if (parsedCookie.key && parsedCookie.id) {\n // Encryption key already exists, import\n const baseKey = invoke(\n base64DecToArr,\n PerformanceEvents.Base64Decode,\n this.logger,\n this.performanceClient,\n correlationId\n )(parsedCookie.key);\n this.encryptionCookie = {\n id: parsedCookie.id,\n key: await invokeAsync(\n generateHKDF,\n PerformanceEvents.GenerateHKDF,\n this.logger,\n this.performanceClient,\n correlationId\n )(baseKey),\n };\n } else {\n // Encryption key doesn't exist or is invalid, generate a new one\n const id = createNewGuid();\n const baseKey = await invokeAsync(\n generateBaseKey,\n PerformanceEvents.GenerateBaseKey,\n this.logger,\n this.performanceClient,\n correlationId\n )();\n const keyStr = invoke(\n urlEncodeArr,\n PerformanceEvents.UrlEncodeArr,\n this.logger,\n this.performanceClient,\n correlationId\n )(new Uint8Array(baseKey));\n this.encryptionCookie = {\n id: id,\n key: await invokeAsync(\n generateHKDF,\n PerformanceEvents.GenerateHKDF,\n this.logger,\n this.performanceClient,\n correlationId\n )(baseKey),\n };\n\n const cookieData = {\n id: id,\n key: keyStr,\n };\n\n cookies.setItem(\n ENCRYPTION_KEY,\n JSON.stringify(cookieData),\n 0, // Expiration - 0 means cookie will be cleared at the end of the browser session\n true, // Secure flag\n SameSiteOptions.None // SameSite must be None to support iframed apps\n );\n }\n\n await invokeAsync(\n this.importExistingCache.bind(this),\n PerformanceEvents.ImportExistingCache,\n this.logger,\n this.performanceClient,\n correlationId\n )(correlationId);\n\n // Register listener for cache updates in other tabs\n this.broadcast.addEventListener(\"message\", this.updateCache.bind(this));\n\n this.initialized = true;\n }\n\n getItem(key: string): string | null {\n return window.localStorage.getItem(key);\n }\n\n getUserData(key: string): string | null {\n if (!this.initialized) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.uninitializedPublicClientApplication\n );\n }\n return this.memoryStorage.getItem(key);\n }\n\n async decryptData(\n key: string,\n data: EncryptedData,\n correlationId: string\n ): Promise {\n if (!this.initialized || !this.encryptionCookie) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.uninitializedPublicClientApplication\n );\n }\n\n if (data.id !== this.encryptionCookie.id) {\n // Data was encrypted with a different key. It must be removed because it is from a previous session.\n this.performanceClient.incrementFields(\n { encryptedCacheExpiredCount: 1 },\n correlationId\n );\n return null;\n }\n\n const decryptedData = await invokeAsync(\n decrypt,\n PerformanceEvents.Decrypt,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n this.encryptionCookie.key,\n data.nonce,\n this.getContext(key),\n data.data\n );\n\n if (!decryptedData) {\n return null;\n }\n\n try {\n return JSON.parse(decryptedData);\n } catch (e) {\n this.performanceClient.incrementFields(\n { encryptedCacheCorruptionCount: 1 },\n correlationId\n );\n return null;\n }\n }\n\n setItem(key: string, value: string): void {\n window.localStorage.setItem(key, value);\n }\n\n async setUserData(\n key: string,\n value: string,\n correlationId: string,\n timestamp: string\n ): Promise {\n if (!this.initialized || !this.encryptionCookie) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.uninitializedPublicClientApplication\n );\n }\n\n const { data, nonce } = await invokeAsync(\n encrypt,\n PerformanceEvents.Encrypt,\n this.logger,\n this.performanceClient,\n correlationId\n )(this.encryptionCookie.key, value, this.getContext(key));\n const encryptedData: EncryptedData = {\n id: this.encryptionCookie.id,\n nonce: nonce,\n data: data,\n lastUpdatedAt: timestamp,\n };\n\n this.memoryStorage.setItem(key, value);\n this.setItem(key, JSON.stringify(encryptedData));\n\n // Notify other frames to update their in-memory cache\n this.broadcast.postMessage({\n key: key,\n value: value,\n context: this.getContext(key),\n });\n }\n\n removeItem(key: string): void {\n if (this.memoryStorage.containsKey(key)) {\n this.memoryStorage.removeItem(key);\n this.broadcast.postMessage({\n key: key,\n value: null,\n context: this.getContext(key),\n });\n }\n window.localStorage.removeItem(key);\n }\n\n getKeys(): string[] {\n return Object.keys(window.localStorage);\n }\n\n containsKey(key: string): boolean {\n return window.localStorage.hasOwnProperty(key);\n }\n\n /**\n * Removes all known MSAL keys from the cache\n */\n clear(): void {\n // Removes all remaining MSAL cache items\n this.memoryStorage.clear();\n\n const accountKeys = getAccountKeys(this);\n accountKeys.forEach((key) => this.removeItem(key));\n const tokenKeys = getTokenKeys(this.clientId, this);\n tokenKeys.idToken.forEach((key) => this.removeItem(key));\n tokenKeys.accessToken.forEach((key) => this.removeItem(key));\n tokenKeys.refreshToken.forEach((key) => this.removeItem(key));\n\n // Clean up anything left\n this.getKeys().forEach((cacheKey: string) => {\n if (\n cacheKey.startsWith(CacheKeys.PREFIX) ||\n cacheKey.indexOf(this.clientId) !== -1\n ) {\n this.removeItem(cacheKey);\n }\n });\n }\n\n /**\n * Helper to decrypt all known MSAL keys in localStorage and save them to inMemory storage\n * @returns\n */\n private async importExistingCache(correlationId: string): Promise {\n if (!this.encryptionCookie) {\n return;\n }\n\n let accountKeys = getAccountKeys(this);\n accountKeys = await this.importArray(accountKeys, correlationId);\n // Write valid account keys back to map\n if (accountKeys.length) {\n this.setItem(\n CacheKeys.getAccountKeysCacheKey(),\n JSON.stringify(accountKeys)\n );\n } else {\n this.removeItem(CacheKeys.getAccountKeysCacheKey());\n }\n\n const tokenKeys: TokenKeys = getTokenKeys(this.clientId, this);\n tokenKeys.idToken = await this.importArray(\n tokenKeys.idToken,\n correlationId\n );\n tokenKeys.accessToken = await this.importArray(\n tokenKeys.accessToken,\n correlationId\n );\n tokenKeys.refreshToken = await this.importArray(\n tokenKeys.refreshToken,\n correlationId\n );\n // Write valid token keys back to map\n if (\n tokenKeys.idToken.length ||\n tokenKeys.accessToken.length ||\n tokenKeys.refreshToken.length\n ) {\n this.setItem(\n CacheKeys.getTokenKeysCacheKey(this.clientId),\n JSON.stringify(tokenKeys)\n );\n } else {\n this.removeItem(CacheKeys.getTokenKeysCacheKey(this.clientId));\n }\n }\n\n /**\n * Helper to decrypt and save cache entries\n * @param key\n * @returns\n */\n private async getItemFromEncryptedCache(\n key: string,\n correlationId: string\n ): Promise {\n if (!this.encryptionCookie) {\n return null;\n }\n\n const rawCache = this.getItem(key);\n if (!rawCache) {\n return null;\n }\n\n let encObj: EncryptedData;\n try {\n encObj = JSON.parse(rawCache);\n } catch (e) {\n // Not a valid encrypted object, remove\n return null;\n }\n\n if (!isEncrypted(encObj)) {\n // Data is not encrypted\n this.performanceClient.incrementFields(\n { unencryptedCacheCount: 1 },\n correlationId\n );\n return encObj;\n }\n\n if (encObj.id !== this.encryptionCookie.id) {\n // Data was encrypted with a different key. It must be removed because it is from a previous session.\n this.performanceClient.incrementFields(\n { encryptedCacheExpiredCount: 1 },\n correlationId\n );\n return null;\n }\n\n return invokeAsync(\n decrypt,\n PerformanceEvents.Decrypt,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n this.encryptionCookie.key,\n encObj.nonce,\n this.getContext(key),\n encObj.data\n );\n }\n\n /**\n * Helper to decrypt and save an array of cache keys\n * @param arr\n * @returns Array of keys successfully imported\n */\n private async importArray(\n arr: Array,\n correlationId: string\n ): Promise> {\n const importedArr: Array = [];\n const promiseArr: Array> = [];\n arr.forEach((key) => {\n const promise = this.getItemFromEncryptedCache(\n key,\n correlationId\n ).then((value) => {\n if (value) {\n this.memoryStorage.setItem(key, value);\n importedArr.push(key);\n } else {\n // If value is empty, unencrypted or expired remove\n this.removeItem(key);\n }\n });\n promiseArr.push(promise);\n });\n\n await Promise.all(promiseArr);\n return importedArr;\n }\n\n /**\n * Gets encryption context for a given cache entry. This is clientId for app specific entries, empty string for shared entries\n * @param key\n * @returns\n */\n private getContext(key: string): string {\n let context = \"\";\n if (key.includes(this.clientId)) {\n context = this.clientId; // Used to bind encryption key to this appId\n }\n\n return context;\n }\n\n private updateCache(event: MessageEvent): void {\n this.logger.trace(\"Updating internal cache from broadcast event\");\n const perfMeasurement = this.performanceClient.startMeasurement(\n PerformanceEvents.LocalStorageUpdated\n );\n perfMeasurement.add({ isBackground: true });\n\n const { key, value, context } = event.data;\n if (!key) {\n this.logger.error(\"Broadcast event missing key\");\n perfMeasurement.end({ success: false, errorCode: \"noKey\" });\n return;\n }\n\n if (context && context !== this.clientId) {\n this.logger.trace(\n `Ignoring broadcast event from clientId: ${context}`\n );\n perfMeasurement.end({\n success: false,\n errorCode: \"contextMismatch\",\n });\n return;\n }\n\n if (!value) {\n this.memoryStorage.removeItem(key);\n this.logger.verbose(\"Removed item from internal cache\");\n } else {\n this.memoryStorage.setItem(key, value);\n this.logger.verbose(\"Updated item in internal cache\");\n }\n perfMeasurement.end({ success: true });\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n BrowserConfigurationAuthErrorCodes,\n createBrowserConfigurationAuthError,\n} from \"../error/BrowserConfigurationAuthError.js\";\nimport { IWindowStorage } from \"./IWindowStorage.js\";\n\nexport class SessionStorage implements IWindowStorage {\n constructor() {\n if (!window.sessionStorage) {\n throw createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.storageNotSupported\n );\n }\n }\n\n async initialize(): Promise {\n // Session storage does not require initialization\n }\n\n getItem(key: string): string | null {\n return window.sessionStorage.getItem(key);\n }\n\n getUserData(key: string): string | null {\n return this.getItem(key);\n }\n\n setItem(key: string, value: string): void {\n window.sessionStorage.setItem(key, value);\n }\n\n async setUserData(key: string, value: string): Promise {\n this.setItem(key, value);\n }\n\n removeItem(key: string): void {\n window.sessionStorage.removeItem(key);\n }\n\n getKeys(): string[] {\n return Object.keys(window.sessionStorage);\n }\n\n containsKey(key: string): boolean {\n return window.sessionStorage.hasOwnProperty(key);\n }\n\n decryptData(): Promise {\n // Session storage does not support encryption, so this method is a no-op\n return Promise.resolve(null);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const EventType = {\n INITIALIZE_START: \"msal:initializeStart\",\n INITIALIZE_END: \"msal:initializeEnd\",\n ACCOUNT_ADDED: \"msal:accountAdded\",\n ACCOUNT_REMOVED: \"msal:accountRemoved\",\n ACTIVE_ACCOUNT_CHANGED: \"msal:activeAccountChanged\",\n LOGIN_START: \"msal:loginStart\",\n LOGIN_SUCCESS: \"msal:loginSuccess\",\n LOGIN_FAILURE: \"msal:loginFailure\",\n ACQUIRE_TOKEN_START: \"msal:acquireTokenStart\",\n ACQUIRE_TOKEN_SUCCESS: \"msal:acquireTokenSuccess\",\n ACQUIRE_TOKEN_FAILURE: \"msal:acquireTokenFailure\",\n ACQUIRE_TOKEN_NETWORK_START: \"msal:acquireTokenFromNetworkStart\",\n SSO_SILENT_START: \"msal:ssoSilentStart\",\n SSO_SILENT_SUCCESS: \"msal:ssoSilentSuccess\",\n SSO_SILENT_FAILURE: \"msal:ssoSilentFailure\",\n ACQUIRE_TOKEN_BY_CODE_START: \"msal:acquireTokenByCodeStart\",\n ACQUIRE_TOKEN_BY_CODE_SUCCESS: \"msal:acquireTokenByCodeSuccess\",\n ACQUIRE_TOKEN_BY_CODE_FAILURE: \"msal:acquireTokenByCodeFailure\",\n HANDLE_REDIRECT_START: \"msal:handleRedirectStart\",\n HANDLE_REDIRECT_END: \"msal:handleRedirectEnd\",\n POPUP_OPENED: \"msal:popupOpened\",\n LOGOUT_START: \"msal:logoutStart\",\n LOGOUT_SUCCESS: \"msal:logoutSuccess\",\n LOGOUT_FAILURE: \"msal:logoutFailure\",\n LOGOUT_END: \"msal:logoutEnd\",\n RESTORE_FROM_BFCACHE: \"msal:restoreFromBFCache\",\n BROKER_CONNECTION_ESTABLISHED: \"msal:brokerConnectionEstablished\",\n} as const;\nexport type EventType = (typeof EventType)[keyof typeof EventType];\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/**\n * Utility function to remove an element from an array in place.\n * @param array - The array from which to remove the element.\n * @param element - The element to remove from the array.\n */\nexport function removeElementFromArray(\n array: Array,\n element: string\n): void {\n const index = array.indexOf(element);\n if (index > -1) {\n array.splice(index, 1);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n AccessTokenEntity,\n AccountEntity,\n AccountInfo,\n ActiveAccountFilters,\n AppMetadataEntity,\n AuthenticationScheme,\n AuthorityMetadataEntity,\n CacheError,\n CacheErrorCodes,\n CacheHelpers,\n CacheManager,\n CacheRecord,\n CommonAuthorizationUrlRequest,\n Constants,\n createCacheError,\n DEFAULT_CRYPTO_IMPLEMENTATION,\n ICrypto,\n IdTokenEntity,\n invokeAsync,\n IPerformanceClient,\n Logger,\n PerformanceEvents,\n PersistentCacheKeys,\n RefreshTokenEntity,\n ServerTelemetryEntity,\n StaticAuthorityOptions,\n StoreInCache,\n StringUtils,\n ThrottlingEntity,\n TimeUtils,\n TokenKeys,\n CredentialEntity,\n CredentialType,\n DEFAULT_TOKEN_RENEWAL_OFFSET_SEC,\n} from \"@azure/msal-common/browser\";\nimport { CacheOptions } from \"../config/Configuration.js\";\nimport {\n BrowserAuthErrorCodes,\n createBrowserAuthError,\n} from \"../error/BrowserAuthError.js\";\nimport {\n BrowserCacheLocation,\n InMemoryCacheKeys,\n INTERACTION_TYPE,\n TemporaryCacheKeys,\n} from \"../utils/BrowserConstants.js\";\nimport * as CacheKeys from \"./CacheKeys.js\";\nimport { LocalStorage } from \"./LocalStorage.js\";\nimport { SessionStorage } from \"./SessionStorage.js\";\nimport { MemoryStorage } from \"./MemoryStorage.js\";\nimport { IWindowStorage } from \"./IWindowStorage.js\";\nimport { PlatformAuthRequest } from \"../broker/nativeBroker/PlatformAuthRequest.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { SilentRequest } from \"../request/SilentRequest.js\";\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\nimport { PopupRequest } from \"../request/PopupRequest.js\";\nimport { base64Decode } from \"../encode/Base64Decode.js\";\nimport { base64Encode } from \"../encode/Base64Encode.js\";\nimport { CookieStorage } from \"./CookieStorage.js\";\nimport { getAccountKeys, getTokenKeys } from \"./CacheHelpers.js\";\nimport { EventType } from \"../event/EventType.js\";\nimport { EventHandler } from \"../event/EventHandler.js\";\nimport { clearHash } from \"../utils/BrowserUtils.js\";\nimport { version } from \"../packageMetadata.js\";\nimport { removeElementFromArray } from \"../utils/Helpers.js\";\nimport { EncryptedData, isEncrypted } from \"./EncryptedData.js\";\n\n/**\n * This class implements the cache storage interface for MSAL through browser local or session storage.\n * Cookies are only used if storeAuthStateInCookie is true, and are only used for\n * parameters such as state and nonce, generally.\n */\nexport class BrowserCacheManager extends CacheManager {\n // Cache configuration, either set by user or default values.\n protected cacheConfig: Required;\n // Window storage object (either local or sessionStorage)\n protected browserStorage: IWindowStorage;\n // Internal in-memory storage object used for data used by msal that does not need to persist across page loads\n protected internalStorage: MemoryStorage;\n // Temporary cache\n protected temporaryCacheStorage: IWindowStorage;\n // Cookie storage\n protected cookieStorage: CookieStorage;\n // Logger instance\n protected logger: Logger;\n // Event Handler\n private eventHandler: EventHandler;\n\n constructor(\n clientId: string,\n cacheConfig: Required,\n cryptoImpl: ICrypto,\n logger: Logger,\n performanceClient: IPerformanceClient,\n eventHandler: EventHandler,\n staticAuthorityOptions?: StaticAuthorityOptions\n ) {\n super(\n clientId,\n cryptoImpl,\n logger,\n performanceClient,\n staticAuthorityOptions\n );\n this.cacheConfig = cacheConfig;\n this.logger = logger;\n this.internalStorage = new MemoryStorage();\n this.browserStorage = getStorageImplementation(\n clientId,\n cacheConfig.cacheLocation,\n logger,\n performanceClient\n );\n this.temporaryCacheStorage = getStorageImplementation(\n clientId,\n cacheConfig.temporaryCacheLocation,\n logger,\n performanceClient\n );\n this.cookieStorage = new CookieStorage();\n this.eventHandler = eventHandler;\n }\n\n async initialize(correlationId: string): Promise {\n this.performanceClient.addFields(\n {\n cacheLocation: this.cacheConfig.cacheLocation,\n cacheRetentionDays: this.cacheConfig.cacheRetentionDays,\n },\n correlationId\n );\n await this.browserStorage.initialize(correlationId);\n await this.migrateExistingCache(correlationId);\n this.trackVersionChanges(correlationId);\n }\n\n /**\n * Migrates any existing cache data from previous versions of MSAL.js into the current cache structure.\n */\n async migrateExistingCache(correlationId: string): Promise {\n const accountKeys0 = getAccountKeys(this.browserStorage, 0);\n const tokenKeys0 = getTokenKeys(this.clientId, this.browserStorage, 0);\n this.performanceClient.addFields(\n {\n oldAccountCount: accountKeys0.length,\n oldAccessCount: tokenKeys0.accessToken.length,\n oldIdCount: tokenKeys0.idToken.length,\n oldRefreshCount: tokenKeys0.refreshToken.length,\n },\n correlationId\n );\n\n const accountKeys1 = getAccountKeys(this.browserStorage, 1);\n const tokenKeys1 = getTokenKeys(this.clientId, this.browserStorage, 1);\n this.performanceClient.addFields(\n {\n currAccountCount: accountKeys1.length,\n currAccessCount: tokenKeys1.accessToken.length,\n currIdCount: tokenKeys1.idToken.length,\n currRefreshCount: tokenKeys1.refreshToken.length,\n },\n correlationId\n );\n\n await Promise.all([\n this.updateV0ToCurrent(\n CacheKeys.ACCOUNT_SCHEMA_VERSION,\n accountKeys0,\n accountKeys1,\n correlationId\n ),\n this.updateV0ToCurrent(\n CacheKeys.CREDENTIAL_SCHEMA_VERSION,\n tokenKeys0.idToken,\n tokenKeys1.idToken,\n correlationId\n ),\n this.updateV0ToCurrent(\n CacheKeys.CREDENTIAL_SCHEMA_VERSION,\n tokenKeys0.accessToken,\n tokenKeys1.accessToken,\n correlationId\n ),\n this.updateV0ToCurrent(\n CacheKeys.CREDENTIAL_SCHEMA_VERSION,\n tokenKeys0.refreshToken,\n tokenKeys1.refreshToken,\n correlationId\n ),\n ]);\n\n if (accountKeys0.length > 0) {\n this.browserStorage.setItem(\n CacheKeys.getAccountKeysCacheKey(0),\n JSON.stringify(accountKeys0)\n );\n } else {\n this.browserStorage.removeItem(CacheKeys.getAccountKeysCacheKey(0));\n }\n\n if (accountKeys1.length > 0) {\n this.browserStorage.setItem(\n CacheKeys.getAccountKeysCacheKey(1),\n JSON.stringify(accountKeys1)\n );\n } else {\n this.browserStorage.removeItem(CacheKeys.getAccountKeysCacheKey(1));\n }\n\n this.setTokenKeys(tokenKeys0, correlationId, 0);\n this.setTokenKeys(tokenKeys1, correlationId, 1);\n }\n\n async updateV0ToCurrent(\n currentSchema: number,\n v0Keys: Array,\n v1Keys: Array,\n correlationId: string\n ): Promise {\n const upgradePromises: Array> = [];\n\n for (const v0Key of [...v0Keys]) {\n const rawV0Value = this.browserStorage.getItem(v0Key);\n const parsedV0Value = this.validateAndParseJson(\n rawV0Value || \"\"\n ) as CredentialEntity | AccountEntity | EncryptedData | null;\n\n if (!parsedV0Value) {\n removeElementFromArray(v0Keys, v0Key);\n continue;\n }\n\n if (!parsedV0Value.lastUpdatedAt) {\n // Add lastUpdatedAt to the existing v0 entry if it doesnt exist so we know when it's safe to remove it\n parsedV0Value.lastUpdatedAt = Date.now().toString();\n this.setItem(\n v0Key,\n JSON.stringify(parsedV0Value),\n correlationId\n );\n }\n\n const decryptedData = isEncrypted(parsedV0Value)\n ? await this.browserStorage.decryptData(\n v0Key,\n parsedV0Value,\n correlationId\n )\n : parsedV0Value;\n let expirationTime;\n if (decryptedData) {\n if (CacheHelpers.isAccessTokenEntity(decryptedData)) {\n expirationTime = decryptedData.expiresOn;\n } else if (CacheHelpers.isRefreshTokenEntity(decryptedData)) {\n expirationTime = decryptedData.expiresOn;\n }\n }\n if (\n !decryptedData ||\n TimeUtils.isCacheExpired(\n parsedV0Value.lastUpdatedAt,\n this.cacheConfig.cacheRetentionDays\n ) ||\n (expirationTime &&\n TimeUtils.isTokenExpired(\n expirationTime,\n DEFAULT_TOKEN_RENEWAL_OFFSET_SEC\n ))\n ) {\n this.browserStorage.removeItem(v0Key);\n removeElementFromArray(v0Keys, v0Key);\n this.performanceClient.incrementFields(\n { expiredCacheRemovedCount: 1 },\n correlationId\n );\n continue;\n }\n\n if (\n this.cacheConfig.cacheLocation !==\n BrowserCacheLocation.LocalStorage ||\n isEncrypted(parsedV0Value)\n ) {\n const v1Key = `${CacheKeys.PREFIX}.${currentSchema}${CacheKeys.CACHE_KEY_SEPARATOR}${v0Key}`;\n const rawV1Entry = this.browserStorage.getItem(v1Key);\n if (!rawV1Entry) {\n upgradePromises.push(\n this.setUserData(\n v1Key,\n JSON.stringify(decryptedData),\n correlationId,\n parsedV0Value.lastUpdatedAt\n ).then(() => {\n v1Keys.push(v1Key);\n this.performanceClient.incrementFields(\n { upgradedCacheCount: 1 },\n correlationId\n );\n })\n );\n continue;\n } else {\n const parsedV1Entry = this.validateAndParseJson(\n rawV1Entry\n ) as CredentialEntity | AccountEntity | EncryptedData;\n // If the entry already exists but is older than the v0 entry, replace it\n if (\n Number(parsedV0Value.lastUpdatedAt) >\n Number(parsedV1Entry.lastUpdatedAt)\n ) {\n upgradePromises.push(\n this.setUserData(\n v1Key,\n JSON.stringify(decryptedData),\n correlationId,\n parsedV0Value.lastUpdatedAt\n ).then(() => {\n this.performanceClient.incrementFields(\n { updatedCacheFromV0Count: 1 },\n correlationId\n );\n })\n );\n continue;\n }\n }\n }\n /*\n * Note: If we reach here for unencrypted localStorage data, we continue without migrating\n * as we can't migrate unencrypted localStorage data right now since we can't guarantee KMSI=no\n */\n }\n\n return Promise.all(upgradePromises);\n }\n\n /**\n * Tracks upgrades and downgrades for telemetry and debugging purposes\n */\n private trackVersionChanges(correlationId: string): void {\n const previousVersion = this.browserStorage.getItem(\n CacheKeys.VERSION_CACHE_KEY\n );\n if (previousVersion) {\n this.logger.info(\n `MSAL.js was last initialized by version: ${previousVersion}`\n );\n this.performanceClient.addFields(\n { previousLibraryVersion: previousVersion },\n correlationId\n );\n }\n\n if (previousVersion !== version) {\n this.setItem(CacheKeys.VERSION_CACHE_KEY, version, correlationId);\n }\n }\n\n /**\n * Parses passed value as JSON object, JSON.parse() will throw an error.\n * @param input\n */\n protected validateAndParseJson(jsonValue: string): object | null {\n if (!jsonValue) {\n return null;\n }\n try {\n const parsedJson = JSON.parse(jsonValue);\n /**\n * There are edge cases in which JSON.parse will successfully parse a non-valid JSON object\n * (e.g. JSON.parse will parse an escaped string into an unescaped string), so adding a type check\n * of the parsed value is necessary in order to be certain that the string represents a valid JSON object.\n *\n */\n return parsedJson && typeof parsedJson === \"object\"\n ? parsedJson\n : null;\n } catch (error) {\n return null;\n }\n }\n\n /**\n * Helper to setItem in browser storage, with cleanup in case of quota errors\n * @param key\n * @param value\n */\n setItem(key: string, value: string, correlationId: string): void {\n let tokenKeysV0Count = 0;\n let accessTokenKeys: Array = [];\n const maxRetries = 20;\n for (let i = 0; i <= maxRetries; i++) {\n try {\n this.browserStorage.setItem(key, value);\n if (i > 0) {\n // Finally update the token keys array with the tokens removed\n if (i <= tokenKeysV0Count) {\n this.removeAccessTokenKeys(\n accessTokenKeys.slice(0, i),\n correlationId,\n 0\n );\n } else {\n this.removeAccessTokenKeys(\n accessTokenKeys.slice(0, tokenKeysV0Count),\n correlationId,\n 0\n );\n this.removeAccessTokenKeys(\n accessTokenKeys.slice(tokenKeysV0Count, i),\n correlationId\n );\n }\n }\n break; // If setItem succeeds, exit the loop\n } catch (e) {\n const cacheError = createCacheError(e);\n if (\n cacheError.errorCode ===\n CacheErrorCodes.cacheQuotaExceeded &&\n i < maxRetries\n ) {\n if (!accessTokenKeys.length) {\n // If we are currently trying to set the token keys, use the value we're trying to set\n const tokenKeys0 =\n key ===\n CacheKeys.getTokenKeysCacheKey(this.clientId, 0)\n ? (JSON.parse(value) as TokenKeys).accessToken\n : this.getTokenKeys(0).accessToken;\n const tokenKeys1 =\n key ===\n CacheKeys.getTokenKeysCacheKey(this.clientId)\n ? (JSON.parse(value) as TokenKeys).accessToken\n : this.getTokenKeys().accessToken;\n accessTokenKeys = [...tokenKeys0, ...tokenKeys1];\n tokenKeysV0Count = tokenKeys0.length;\n }\n if (accessTokenKeys.length <= i) {\n // Nothing to remove, rethrow the error\n throw cacheError;\n }\n // When cache quota is exceeded, start removing access tokens until we can successfully set the item\n this.removeAccessToken(\n accessTokenKeys[i],\n correlationId,\n false // Don't save token keys yet, do it at the end\n );\n } else {\n // If the error is not a quota exceeded error, rethrow it\n throw cacheError;\n }\n }\n }\n }\n\n /**\n * Helper to setUserData in browser storage, with cleanup in case of quota errors\n * @param key\n * @param value\n * @param correlationId\n */\n async setUserData(\n key: string,\n value: string,\n correlationId: string,\n timestamp: string\n ): Promise {\n let tokenKeysV0Count = 0;\n let accessTokenKeys: Array = [];\n const maxRetries = 20;\n for (let i = 0; i <= maxRetries; i++) {\n try {\n await invokeAsync(\n this.browserStorage.setUserData.bind(this.browserStorage),\n PerformanceEvents.SetUserData,\n this.logger,\n this.performanceClient\n )(key, value, correlationId, timestamp);\n if (i > 0) {\n // Finally update the token keys array with the tokens removed\n if (i <= tokenKeysV0Count) {\n this.removeAccessTokenKeys(\n accessTokenKeys.slice(0, i),\n correlationId,\n 0\n );\n } else {\n this.removeAccessTokenKeys(\n accessTokenKeys.slice(0, tokenKeysV0Count),\n correlationId,\n 0\n );\n this.removeAccessTokenKeys(\n accessTokenKeys.slice(tokenKeysV0Count, i),\n correlationId\n );\n }\n }\n break; // If setItem succeeds, exit the loop\n } catch (e) {\n const cacheError = createCacheError(e);\n if (\n cacheError.errorCode ===\n CacheErrorCodes.cacheQuotaExceeded &&\n i < maxRetries\n ) {\n if (!accessTokenKeys.length) {\n const tokenKeys0 = this.getTokenKeys(0).accessToken;\n const tokenKeys1 = this.getTokenKeys().accessToken;\n accessTokenKeys = [...tokenKeys0, ...tokenKeys1];\n tokenKeysV0Count = tokenKeys0.length;\n }\n if (accessTokenKeys.length <= i) {\n // Nothing left to remove, rethrow the error\n throw cacheError;\n }\n // When cache quota is exceeded, start removing access tokens until we can successfully set the item\n this.removeAccessToken(\n accessTokenKeys[i],\n correlationId,\n false // Don't save token keys yet, do it at the end\n );\n } else {\n // If the error is not a quota exceeded error, rethrow it\n throw cacheError;\n }\n }\n }\n }\n\n /**\n * Reads account from cache, deserializes it into an account entity and returns it.\n * If account is not found from the key, returns null and removes key from map.\n * @param accountKey\n * @returns\n */\n getAccount(\n accountKey: string,\n correlationId: string\n ): AccountEntity | null {\n this.logger.trace(\"BrowserCacheManager.getAccount called\");\n const serializedAccount = this.browserStorage.getUserData(accountKey);\n if (!serializedAccount) {\n this.removeAccountKeyFromMap(accountKey, correlationId);\n return null;\n }\n\n const parsedAccount = this.validateAndParseJson(serializedAccount);\n if (!parsedAccount || !AccountEntity.isAccountEntity(parsedAccount)) {\n return null;\n }\n\n return CacheManager.toObject(\n new AccountEntity(),\n parsedAccount\n );\n }\n\n /**\n * set account entity in the platform cache\n * @param account\n */\n async setAccount(\n account: AccountEntity,\n correlationId: string\n ): Promise {\n this.logger.trace(\"BrowserCacheManager.setAccount called\");\n const key = this.generateAccountKey(account.getAccountInfo());\n const timestamp = Date.now().toString();\n account.lastUpdatedAt = timestamp;\n await this.setUserData(\n key,\n JSON.stringify(account),\n correlationId,\n timestamp\n );\n const wasAdded = this.addAccountKeyToMap(key, correlationId);\n\n /**\n * @deprecated - Remove this in next major version in favor of more consistent LOGIN event\n */\n if (\n this.cacheConfig.cacheLocation ===\n BrowserCacheLocation.LocalStorage &&\n wasAdded\n ) {\n this.eventHandler.emitEvent(\n EventType.ACCOUNT_ADDED,\n undefined,\n account.getAccountInfo()\n );\n }\n }\n\n /**\n * Returns the array of account keys currently cached\n * @returns\n */\n getAccountKeys(): Array {\n return getAccountKeys(this.browserStorage);\n }\n\n /**\n * Add a new account to the key map\n * @param key\n */\n addAccountKeyToMap(key: string, correlationId: string): boolean {\n this.logger.trace(\"BrowserCacheManager.addAccountKeyToMap called\");\n this.logger.tracePii(\n `BrowserCacheManager.addAccountKeyToMap called with key: ${key}`\n );\n const accountKeys = this.getAccountKeys();\n if (accountKeys.indexOf(key) === -1) {\n // Only add key if it does not already exist in the map\n accountKeys.push(key);\n this.setItem(\n CacheKeys.getAccountKeysCacheKey(),\n JSON.stringify(accountKeys),\n correlationId\n );\n this.logger.verbose(\n \"BrowserCacheManager.addAccountKeyToMap account key added\"\n );\n return true;\n } else {\n this.logger.verbose(\n \"BrowserCacheManager.addAccountKeyToMap account key already exists in map\"\n );\n return false;\n }\n }\n\n /**\n * Remove an account from the key map\n * @param key\n */\n removeAccountKeyFromMap(key: string, correlationId: string): void {\n this.logger.trace(\"BrowserCacheManager.removeAccountKeyFromMap called\");\n this.logger.tracePii(\n `BrowserCacheManager.removeAccountKeyFromMap called with key: ${key}`\n );\n const accountKeys = this.getAccountKeys();\n const removalIndex = accountKeys.indexOf(key);\n if (removalIndex > -1) {\n accountKeys.splice(removalIndex, 1);\n if (accountKeys.length === 0) {\n // If no keys left, remove the map\n this.removeItem(CacheKeys.getAccountKeysCacheKey());\n return;\n } else {\n this.setItem(\n CacheKeys.getAccountKeysCacheKey(),\n JSON.stringify(accountKeys),\n correlationId\n );\n }\n this.logger.trace(\n \"BrowserCacheManager.removeAccountKeyFromMap account key removed\"\n );\n } else {\n this.logger.trace(\n \"BrowserCacheManager.removeAccountKeyFromMap key not found in existing map\"\n );\n }\n }\n\n /**\n * Extends inherited removeAccount function to include removal of the account key from the map\n * @param key\n */\n removeAccount(account: AccountInfo, correlationId: string): void {\n const activeAccount = this.getActiveAccount(correlationId);\n if (\n activeAccount?.homeAccountId === account.homeAccountId &&\n activeAccount?.environment === account.environment\n ) {\n this.setActiveAccount(null, correlationId);\n }\n\n super.removeAccount(account, correlationId);\n this.removeAccountKeyFromMap(\n this.generateAccountKey(account),\n correlationId\n );\n\n // Remove all other associated cache items\n this.browserStorage.getKeys().forEach((key) => {\n if (\n key.includes(account.homeAccountId) &&\n key.includes(account.environment)\n ) {\n this.browserStorage.removeItem(key);\n }\n });\n\n /**\n * @deprecated - Remove this in next major version in favor of more consistent LOGOUT event\n */\n if (\n this.cacheConfig.cacheLocation === BrowserCacheLocation.LocalStorage\n ) {\n this.eventHandler.emitEvent(\n EventType.ACCOUNT_REMOVED,\n undefined,\n account\n );\n }\n }\n\n /**\n * Removes given idToken from the cache and from the key map\n * @param key\n */\n removeIdToken(key: string, correlationId: string): void {\n super.removeIdToken(key, correlationId);\n const tokenKeys = this.getTokenKeys();\n const idRemoval = tokenKeys.idToken.indexOf(key);\n if (idRemoval > -1) {\n this.logger.info(\"idToken removed from tokenKeys map\");\n tokenKeys.idToken.splice(idRemoval, 1);\n this.setTokenKeys(tokenKeys, correlationId);\n }\n }\n\n /**\n * Removes given accessToken from the cache and from the key map\n * @param key\n */\n removeAccessToken(\n key: string,\n correlationId: string,\n updateTokenKeys: boolean = true\n ): void {\n super.removeAccessToken(key, correlationId);\n updateTokenKeys && this.removeAccessTokenKeys([key], correlationId);\n }\n\n /**\n * Remove access token key from the key map\n * @param key\n * @param correlationId\n * @param tokenKeys\n */\n removeAccessTokenKeys(\n keys: Array,\n correlationId: string,\n schemaVersion: number = CacheKeys.CREDENTIAL_SCHEMA_VERSION\n ): void {\n this.logger.trace(\"removeAccessTokenKey called\");\n const tokenKeys = this.getTokenKeys(schemaVersion);\n let keysRemoved = 0;\n keys.forEach((key) => {\n const accessRemoval = tokenKeys.accessToken.indexOf(key);\n if (accessRemoval > -1) {\n tokenKeys.accessToken.splice(accessRemoval, 1);\n keysRemoved++;\n }\n });\n\n if (keysRemoved > 0) {\n this.logger.info(\n `removed ${keysRemoved} accessToken keys from tokenKeys map`\n );\n this.setTokenKeys(tokenKeys, correlationId, schemaVersion);\n return;\n }\n }\n\n /**\n * Removes given refreshToken from the cache and from the key map\n * @param key\n */\n removeRefreshToken(key: string, correlationId: string): void {\n super.removeRefreshToken(key, correlationId);\n const tokenKeys = this.getTokenKeys();\n const refreshRemoval = tokenKeys.refreshToken.indexOf(key);\n if (refreshRemoval > -1) {\n this.logger.info(\"refreshToken removed from tokenKeys map\");\n tokenKeys.refreshToken.splice(refreshRemoval, 1);\n this.setTokenKeys(tokenKeys, correlationId);\n }\n }\n\n /**\n * Gets the keys for the cached tokens associated with this clientId\n * @returns\n */\n getTokenKeys(\n schemaVersion: number = CacheKeys.CREDENTIAL_SCHEMA_VERSION\n ): TokenKeys {\n return getTokenKeys(this.clientId, this.browserStorage, schemaVersion);\n }\n\n /**\n * Stores the token keys in the cache\n * @param tokenKeys\n * @param correlationId\n * @returns\n */\n setTokenKeys(\n tokenKeys: TokenKeys,\n correlationId: string,\n schemaVersion: number = CacheKeys.CREDENTIAL_SCHEMA_VERSION\n ): void {\n if (\n tokenKeys.idToken.length === 0 &&\n tokenKeys.accessToken.length === 0 &&\n tokenKeys.refreshToken.length === 0\n ) {\n // If no keys left, remove the map\n this.removeItem(\n CacheKeys.getTokenKeysCacheKey(this.clientId, schemaVersion)\n );\n return;\n } else {\n this.setItem(\n CacheKeys.getTokenKeysCacheKey(this.clientId, schemaVersion),\n JSON.stringify(tokenKeys),\n correlationId\n );\n }\n }\n\n /**\n * generates idToken entity from a string\n * @param idTokenKey\n */\n getIdTokenCredential(\n idTokenKey: string,\n correlationId: string\n ): IdTokenEntity | null {\n const value = this.browserStorage.getUserData(idTokenKey);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getIdTokenCredential: called, no cache hit\"\n );\n this.removeIdToken(idTokenKey, correlationId);\n return null;\n }\n\n const parsedIdToken = this.validateAndParseJson(value);\n if (!parsedIdToken || !CacheHelpers.isIdTokenEntity(parsedIdToken)) {\n this.logger.trace(\n \"BrowserCacheManager.getIdTokenCredential: called, no cache hit\"\n );\n return null;\n }\n\n this.logger.trace(\n \"BrowserCacheManager.getIdTokenCredential: cache hit\"\n );\n return parsedIdToken as IdTokenEntity;\n }\n\n /**\n * set IdToken credential to the platform cache\n * @param idToken\n */\n async setIdTokenCredential(\n idToken: IdTokenEntity,\n correlationId: string\n ): Promise {\n this.logger.trace(\"BrowserCacheManager.setIdTokenCredential called\");\n const idTokenKey = this.generateCredentialKey(idToken);\n const timestamp = Date.now().toString();\n idToken.lastUpdatedAt = timestamp;\n\n await this.setUserData(\n idTokenKey,\n JSON.stringify(idToken),\n correlationId,\n timestamp\n );\n\n const tokenKeys = this.getTokenKeys();\n if (tokenKeys.idToken.indexOf(idTokenKey) === -1) {\n this.logger.info(\n \"BrowserCacheManager: addTokenKey - idToken added to map\"\n );\n tokenKeys.idToken.push(idTokenKey);\n this.setTokenKeys(tokenKeys, correlationId);\n }\n }\n\n /**\n * generates accessToken entity from a string\n * @param key\n */\n getAccessTokenCredential(\n accessTokenKey: string,\n correlationId: string\n ): AccessTokenEntity | null {\n const value = this.browserStorage.getUserData(accessTokenKey);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getAccessTokenCredential: called, no cache hit\"\n );\n this.removeAccessTokenKeys([accessTokenKey], correlationId);\n return null;\n }\n const parsedAccessToken = this.validateAndParseJson(value);\n if (\n !parsedAccessToken ||\n !CacheHelpers.isAccessTokenEntity(parsedAccessToken)\n ) {\n this.logger.trace(\n \"BrowserCacheManager.getAccessTokenCredential: called, no cache hit\"\n );\n return null;\n }\n\n this.logger.trace(\n \"BrowserCacheManager.getAccessTokenCredential: cache hit\"\n );\n return parsedAccessToken as AccessTokenEntity;\n }\n\n /**\n * set accessToken credential to the platform cache\n * @param accessToken\n */\n async setAccessTokenCredential(\n accessToken: AccessTokenEntity,\n correlationId: string\n ): Promise {\n this.logger.trace(\n \"BrowserCacheManager.setAccessTokenCredential called\"\n );\n const accessTokenKey = this.generateCredentialKey(accessToken);\n const timestamp = Date.now().toString();\n accessToken.lastUpdatedAt = timestamp;\n\n await this.setUserData(\n accessTokenKey,\n JSON.stringify(accessToken),\n correlationId,\n timestamp\n );\n\n const tokenKeys = this.getTokenKeys();\n const index = tokenKeys.accessToken.indexOf(accessTokenKey);\n if (index !== -1) {\n tokenKeys.accessToken.splice(index, 1); // Remove existing key before pushing to the end\n }\n this.logger.trace(\n `access token ${index === -1 ? \"added to\" : \"updated in\"} map`\n );\n tokenKeys.accessToken.push(accessTokenKey);\n this.setTokenKeys(tokenKeys, correlationId);\n }\n\n /**\n * generates refreshToken entity from a string\n * @param refreshTokenKey\n */\n getRefreshTokenCredential(\n refreshTokenKey: string,\n correlationId: string\n ): RefreshTokenEntity | null {\n const value = this.browserStorage.getUserData(refreshTokenKey);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getRefreshTokenCredential: called, no cache hit\"\n );\n this.removeRefreshToken(refreshTokenKey, correlationId);\n return null;\n }\n const parsedRefreshToken = this.validateAndParseJson(value);\n if (\n !parsedRefreshToken ||\n !CacheHelpers.isRefreshTokenEntity(parsedRefreshToken)\n ) {\n this.logger.trace(\n \"BrowserCacheManager.getRefreshTokenCredential: called, no cache hit\"\n );\n return null;\n }\n\n this.logger.trace(\n \"BrowserCacheManager.getRefreshTokenCredential: cache hit\"\n );\n return parsedRefreshToken as RefreshTokenEntity;\n }\n\n /**\n * set refreshToken credential to the platform cache\n * @param refreshToken\n */\n async setRefreshTokenCredential(\n refreshToken: RefreshTokenEntity,\n correlationId: string\n ): Promise {\n this.logger.trace(\n \"BrowserCacheManager.setRefreshTokenCredential called\"\n );\n const refreshTokenKey = this.generateCredentialKey(refreshToken);\n const timestamp = Date.now().toString();\n refreshToken.lastUpdatedAt = timestamp;\n\n await this.setUserData(\n refreshTokenKey,\n JSON.stringify(refreshToken),\n correlationId,\n timestamp\n );\n\n const tokenKeys = this.getTokenKeys();\n if (tokenKeys.refreshToken.indexOf(refreshTokenKey) === -1) {\n this.logger.info(\n \"BrowserCacheManager: addTokenKey - refreshToken added to map\"\n );\n tokenKeys.refreshToken.push(refreshTokenKey);\n this.setTokenKeys(tokenKeys, correlationId);\n }\n }\n\n /**\n * fetch appMetadata entity from the platform cache\n * @param appMetadataKey\n */\n getAppMetadata(appMetadataKey: string): AppMetadataEntity | null {\n const value = this.browserStorage.getItem(appMetadataKey);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getAppMetadata: called, no cache hit\"\n );\n return null;\n }\n\n const parsedMetadata = this.validateAndParseJson(value);\n if (\n !parsedMetadata ||\n !CacheHelpers.isAppMetadataEntity(appMetadataKey, parsedMetadata)\n ) {\n this.logger.trace(\n \"BrowserCacheManager.getAppMetadata: called, no cache hit\"\n );\n return null;\n }\n\n this.logger.trace(\"BrowserCacheManager.getAppMetadata: cache hit\");\n return parsedMetadata as AppMetadataEntity;\n }\n\n /**\n * set appMetadata entity to the platform cache\n * @param appMetadata\n */\n setAppMetadata(\n appMetadata: AppMetadataEntity,\n correlationId: string\n ): void {\n this.logger.trace(\"BrowserCacheManager.setAppMetadata called\");\n const appMetadataKey = CacheHelpers.generateAppMetadataKey(appMetadata);\n this.setItem(\n appMetadataKey,\n JSON.stringify(appMetadata),\n correlationId\n );\n }\n\n /**\n * fetch server telemetry entity from the platform cache\n * @param serverTelemetryKey\n */\n getServerTelemetry(\n serverTelemetryKey: string\n ): ServerTelemetryEntity | null {\n const value = this.browserStorage.getItem(serverTelemetryKey);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getServerTelemetry: called, no cache hit\"\n );\n return null;\n }\n const parsedEntity = this.validateAndParseJson(value);\n if (\n !parsedEntity ||\n !CacheHelpers.isServerTelemetryEntity(\n serverTelemetryKey,\n parsedEntity\n )\n ) {\n this.logger.trace(\n \"BrowserCacheManager.getServerTelemetry: called, no cache hit\"\n );\n return null;\n }\n\n this.logger.trace(\"BrowserCacheManager.getServerTelemetry: cache hit\");\n return parsedEntity as ServerTelemetryEntity;\n }\n\n /**\n * set server telemetry entity to the platform cache\n * @param serverTelemetryKey\n * @param serverTelemetry\n */\n setServerTelemetry(\n serverTelemetryKey: string,\n serverTelemetry: ServerTelemetryEntity,\n correlationId: string\n ): void {\n this.logger.trace(\"BrowserCacheManager.setServerTelemetry called\");\n this.setItem(\n serverTelemetryKey,\n JSON.stringify(serverTelemetry),\n correlationId\n );\n }\n\n /**\n *\n */\n getAuthorityMetadata(key: string): AuthorityMetadataEntity | null {\n const value = this.internalStorage.getItem(key);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getAuthorityMetadata: called, no cache hit\"\n );\n return null;\n }\n const parsedMetadata = this.validateAndParseJson(value);\n if (\n parsedMetadata &&\n CacheHelpers.isAuthorityMetadataEntity(key, parsedMetadata)\n ) {\n this.logger.trace(\n \"BrowserCacheManager.getAuthorityMetadata: cache hit\"\n );\n return parsedMetadata as AuthorityMetadataEntity;\n }\n return null;\n }\n\n /**\n *\n */\n getAuthorityMetadataKeys(): Array {\n const allKeys = this.internalStorage.getKeys();\n return allKeys.filter((key) => {\n return this.isAuthorityMetadata(key);\n });\n }\n\n /**\n * Sets wrapper metadata in memory\n * @param wrapperSKU\n * @param wrapperVersion\n */\n setWrapperMetadata(wrapperSKU: string, wrapperVersion: string): void {\n this.internalStorage.setItem(InMemoryCacheKeys.WRAPPER_SKU, wrapperSKU);\n this.internalStorage.setItem(\n InMemoryCacheKeys.WRAPPER_VER,\n wrapperVersion\n );\n }\n\n /**\n * Returns wrapper metadata from in-memory storage\n */\n getWrapperMetadata(): [string, string] {\n const sku =\n this.internalStorage.getItem(InMemoryCacheKeys.WRAPPER_SKU) ||\n Constants.EMPTY_STRING;\n const version =\n this.internalStorage.getItem(InMemoryCacheKeys.WRAPPER_VER) ||\n Constants.EMPTY_STRING;\n return [sku, version];\n }\n\n /**\n *\n * @param entity\n */\n setAuthorityMetadata(key: string, entity: AuthorityMetadataEntity): void {\n this.logger.trace(\"BrowserCacheManager.setAuthorityMetadata called\");\n this.internalStorage.setItem(key, JSON.stringify(entity));\n }\n\n /**\n * Gets the active account\n */\n getActiveAccount(correlationId: string): AccountInfo | null {\n const activeAccountKeyFilters = this.generateCacheKey(\n PersistentCacheKeys.ACTIVE_ACCOUNT_FILTERS\n );\n const activeAccountValueFilters = this.browserStorage.getItem(\n activeAccountKeyFilters\n );\n if (!activeAccountValueFilters) {\n this.logger.trace(\n \"BrowserCacheManager.getActiveAccount: No active account filters found\"\n );\n return null;\n }\n const activeAccountValueObj = this.validateAndParseJson(\n activeAccountValueFilters\n ) as AccountInfo;\n if (activeAccountValueObj) {\n this.logger.trace(\n \"BrowserCacheManager.getActiveAccount: Active account filters schema found\"\n );\n return this.getAccountInfoFilteredBy(\n {\n homeAccountId: activeAccountValueObj.homeAccountId,\n localAccountId: activeAccountValueObj.localAccountId,\n tenantId: activeAccountValueObj.tenantId,\n },\n correlationId\n );\n }\n this.logger.trace(\n \"BrowserCacheManager.getActiveAccount: No active account found\"\n );\n return null;\n }\n\n /**\n * Sets the active account's localAccountId in cache\n * @param account\n */\n setActiveAccount(account: AccountInfo | null, correlationId: string): void {\n const activeAccountKey = this.generateCacheKey(\n PersistentCacheKeys.ACTIVE_ACCOUNT_FILTERS\n );\n if (account) {\n this.logger.verbose(\"setActiveAccount: Active account set\");\n const activeAccountValue: ActiveAccountFilters = {\n homeAccountId: account.homeAccountId,\n localAccountId: account.localAccountId,\n tenantId: account.tenantId,\n lastUpdatedAt: TimeUtils.nowSeconds().toString(),\n };\n this.setItem(\n activeAccountKey,\n JSON.stringify(activeAccountValue),\n correlationId\n );\n } else {\n this.logger.verbose(\n \"setActiveAccount: No account passed, active account not set\"\n );\n this.browserStorage.removeItem(activeAccountKey);\n }\n this.eventHandler.emitEvent(EventType.ACTIVE_ACCOUNT_CHANGED);\n }\n\n /**\n * fetch throttling entity from the platform cache\n * @param throttlingCacheKey\n */\n getThrottlingCache(throttlingCacheKey: string): ThrottlingEntity | null {\n const value = this.browserStorage.getItem(throttlingCacheKey);\n if (!value) {\n this.logger.trace(\n \"BrowserCacheManager.getThrottlingCache: called, no cache hit\"\n );\n return null;\n }\n\n const parsedThrottlingCache = this.validateAndParseJson(value);\n if (\n !parsedThrottlingCache ||\n !CacheHelpers.isThrottlingEntity(\n throttlingCacheKey,\n parsedThrottlingCache\n )\n ) {\n this.logger.trace(\n \"BrowserCacheManager.getThrottlingCache: called, no cache hit\"\n );\n return null;\n }\n\n this.logger.trace(\"BrowserCacheManager.getThrottlingCache: cache hit\");\n return parsedThrottlingCache as ThrottlingEntity;\n }\n\n /**\n * set throttling entity to the platform cache\n * @param throttlingCacheKey\n * @param throttlingCache\n */\n setThrottlingCache(\n throttlingCacheKey: string,\n throttlingCache: ThrottlingEntity,\n correlationId: string\n ): void {\n this.logger.trace(\"BrowserCacheManager.setThrottlingCache called\");\n this.setItem(\n throttlingCacheKey,\n JSON.stringify(throttlingCache),\n correlationId\n );\n }\n\n /**\n * Gets cache item with given key.\n * Will retrieve from cookies if storeAuthStateInCookie is set to true.\n * @param key\n */\n getTemporaryCache(cacheKey: string, generateKey?: boolean): string | null {\n const key = generateKey ? this.generateCacheKey(cacheKey) : cacheKey;\n if (this.cacheConfig.storeAuthStateInCookie) {\n const itemCookie = this.cookieStorage.getItem(key);\n if (itemCookie) {\n this.logger.trace(\n \"BrowserCacheManager.getTemporaryCache: storeAuthStateInCookies set to true, retrieving from cookies\"\n );\n return itemCookie;\n }\n }\n\n const value = this.temporaryCacheStorage.getItem(key);\n if (!value) {\n // If temp cache item not found in session/memory, check local storage for items set by old versions\n if (\n this.cacheConfig.cacheLocation ===\n BrowserCacheLocation.LocalStorage\n ) {\n const item = this.browserStorage.getItem(key);\n if (item) {\n this.logger.trace(\n \"BrowserCacheManager.getTemporaryCache: Temporary cache item found in local storage\"\n );\n return item;\n }\n }\n this.logger.trace(\n \"BrowserCacheManager.getTemporaryCache: No cache item found in local storage\"\n );\n return null;\n }\n this.logger.trace(\n \"BrowserCacheManager.getTemporaryCache: Temporary cache item returned\"\n );\n return value;\n }\n\n /**\n * Sets the cache item with the key and value given.\n * Stores in cookie if storeAuthStateInCookie is set to true.\n * This can cause cookie overflow if used incorrectly.\n * @param key\n * @param value\n */\n setTemporaryCache(\n cacheKey: string,\n value: string,\n generateKey?: boolean\n ): void {\n const key = generateKey ? this.generateCacheKey(cacheKey) : cacheKey;\n\n this.temporaryCacheStorage.setItem(key, value);\n if (this.cacheConfig.storeAuthStateInCookie) {\n this.logger.trace(\n \"BrowserCacheManager.setTemporaryCache: storeAuthStateInCookie set to true, setting item cookie\"\n );\n this.cookieStorage.setItem(\n key,\n value,\n undefined,\n this.cacheConfig.secureCookies\n );\n }\n }\n\n /**\n * Removes the cache item with the given key.\n * @param key\n */\n removeItem(key: string): void {\n this.browserStorage.removeItem(key);\n }\n\n /**\n * Removes the temporary cache item with the given key.\n * Will also clear the cookie item if storeAuthStateInCookie is set to true.\n * @param key\n */\n removeTemporaryItem(key: string): void {\n this.temporaryCacheStorage.removeItem(key);\n if (this.cacheConfig.storeAuthStateInCookie) {\n this.logger.trace(\n \"BrowserCacheManager.removeItem: storeAuthStateInCookie is true, clearing item cookie\"\n );\n this.cookieStorage.removeItem(key);\n }\n }\n\n /**\n * Gets all keys in window.\n */\n getKeys(): string[] {\n return this.browserStorage.getKeys();\n }\n\n /**\n * Clears all cache entries created by MSAL.\n */\n clear(correlationId: string): void {\n // Removes all accounts and their credentials\n this.removeAllAccounts(correlationId);\n this.removeAppMetadata(correlationId);\n\n // Remove temp storage first to make sure any cookies are cleared\n this.temporaryCacheStorage.getKeys().forEach((cacheKey: string) => {\n if (\n cacheKey.indexOf(CacheKeys.PREFIX) !== -1 ||\n cacheKey.indexOf(this.clientId) !== -1\n ) {\n this.removeTemporaryItem(cacheKey);\n }\n });\n\n // Removes all remaining MSAL cache items\n this.browserStorage.getKeys().forEach((cacheKey: string) => {\n if (\n cacheKey.indexOf(CacheKeys.PREFIX) !== -1 ||\n cacheKey.indexOf(this.clientId) !== -1\n ) {\n this.browserStorage.removeItem(cacheKey);\n }\n });\n\n this.internalStorage.clear();\n }\n\n /**\n * Clears all access tokes that have claims prior to saving the current one\n * @param performanceClient {IPerformanceClient}\n * @param correlationId {string} correlation id\n * @returns\n */\n clearTokensAndKeysWithClaims(correlationId: string): void {\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.ClearTokensAndKeysWithClaims,\n correlationId\n );\n\n const tokenKeys = this.getTokenKeys();\n let removedAccessTokens = 0;\n tokenKeys.accessToken.forEach((key: string) => {\n // if the access token has claims in its key, remove the token key and the token\n const credential = this.getAccessTokenCredential(\n key,\n correlationId\n );\n if (\n credential?.requestedClaimsHash &&\n key.includes(credential.requestedClaimsHash.toLowerCase())\n ) {\n this.removeAccessToken(key, correlationId);\n removedAccessTokens++;\n }\n });\n\n // warn if any access tokens are removed\n if (removedAccessTokens > 0) {\n this.logger.warning(\n `${removedAccessTokens} access tokens with claims in the cache keys have been removed from the cache.`\n );\n }\n }\n\n /**\n * Prepend msal. to each key\n * @param key\n * @param addInstanceId\n */\n generateCacheKey(key: string): string {\n if (StringUtils.startsWith(key, CacheKeys.PREFIX)) {\n return key;\n }\n return `${CacheKeys.PREFIX}.${this.clientId}.${key}`;\n }\n\n /**\n * Cache Key: msal.--------\n * IdToken Example: uid.utid-login.microsoftonline.com-idtoken-app_client_id-contoso.com\n * AccessToken Example: uid.utid-login.microsoftonline.com-accesstoken-app_client_id-contoso.com-scope1 scope2--pop\n * RefreshToken Example: uid.utid-login.microsoftonline.com-refreshtoken-1-contoso.com\n * @param credentialEntity\n * @returns\n */\n generateCredentialKey(credential: CredentialEntity): string {\n const familyId =\n (credential.credentialType === CredentialType.REFRESH_TOKEN &&\n credential.familyId) ||\n credential.clientId;\n const scheme =\n credential.tokenType &&\n credential.tokenType.toLowerCase() !==\n AuthenticationScheme.BEARER.toLowerCase()\n ? credential.tokenType.toLowerCase()\n : \"\";\n const credentialKey = [\n `${CacheKeys.PREFIX}.${CacheKeys.CREDENTIAL_SCHEMA_VERSION}`,\n credential.homeAccountId,\n credential.environment,\n credential.credentialType,\n familyId,\n credential.realm || \"\",\n credential.target || \"\",\n credential.requestedClaimsHash || \"\",\n scheme,\n ];\n\n return credentialKey.join(CacheKeys.CACHE_KEY_SEPARATOR).toLowerCase();\n }\n\n /**\n * Cache Key: msal....\n * @param account\n * @returns\n */\n generateAccountKey(account: AccountInfo): string {\n const homeTenantId = account.homeAccountId.split(\".\")[1];\n const accountKey = [\n `${CacheKeys.PREFIX}.${CacheKeys.ACCOUNT_SCHEMA_VERSION}`,\n account.homeAccountId,\n account.environment,\n homeTenantId || account.tenantId || \"\",\n ];\n\n return accountKey.join(CacheKeys.CACHE_KEY_SEPARATOR).toLowerCase();\n }\n\n /**\n * Reset all temporary cache items\n * @param state\n */\n resetRequestCache(): void {\n this.logger.trace(\"BrowserCacheManager.resetRequestCache called\");\n\n this.removeTemporaryItem(\n this.generateCacheKey(TemporaryCacheKeys.REQUEST_PARAMS)\n );\n this.removeTemporaryItem(\n this.generateCacheKey(TemporaryCacheKeys.VERIFIER)\n );\n this.removeTemporaryItem(\n this.generateCacheKey(TemporaryCacheKeys.ORIGIN_URI)\n );\n this.removeTemporaryItem(\n this.generateCacheKey(TemporaryCacheKeys.URL_HASH)\n );\n this.removeTemporaryItem(\n this.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST)\n );\n this.setInteractionInProgress(false);\n }\n\n cacheAuthorizeRequest(\n authCodeRequest: CommonAuthorizationUrlRequest,\n codeVerifier?: string\n ): void {\n this.logger.trace(\"BrowserCacheManager.cacheAuthorizeRequest called\");\n\n const encodedValue = base64Encode(JSON.stringify(authCodeRequest));\n this.setTemporaryCache(\n TemporaryCacheKeys.REQUEST_PARAMS,\n encodedValue,\n true\n );\n\n if (codeVerifier) {\n const encodedVerifier = base64Encode(codeVerifier);\n this.setTemporaryCache(\n TemporaryCacheKeys.VERIFIER,\n encodedVerifier,\n true\n );\n }\n }\n\n /**\n * Gets the token exchange parameters from the cache. Throws an error if nothing is found.\n */\n getCachedRequest(): [CommonAuthorizationUrlRequest, string] {\n this.logger.trace(\"BrowserCacheManager.getCachedRequest called\");\n // Get token request from cache and parse as TokenExchangeParameters.\n const encodedTokenRequest = this.getTemporaryCache(\n TemporaryCacheKeys.REQUEST_PARAMS,\n true\n );\n if (!encodedTokenRequest) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.noTokenRequestCacheError\n );\n }\n const encodedVerifier = this.getTemporaryCache(\n TemporaryCacheKeys.VERIFIER,\n true\n );\n\n let parsedRequest: CommonAuthorizationUrlRequest;\n let verifier = \"\";\n try {\n parsedRequest = JSON.parse(base64Decode(encodedTokenRequest));\n if (encodedVerifier) {\n verifier = base64Decode(encodedVerifier);\n }\n } catch (e) {\n this.logger.errorPii(`Attempted to parse: ${encodedTokenRequest}`);\n this.logger.error(\n `Parsing cached token request threw with error: ${e}`\n );\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.unableToParseTokenRequestCacheError\n );\n }\n\n return [parsedRequest, verifier];\n }\n\n /**\n * Gets cached native request for redirect flows\n */\n getCachedNativeRequest(): PlatformAuthRequest | null {\n this.logger.trace(\"BrowserCacheManager.getCachedNativeRequest called\");\n const cachedRequest = this.getTemporaryCache(\n TemporaryCacheKeys.NATIVE_REQUEST,\n true\n );\n if (!cachedRequest) {\n this.logger.trace(\n \"BrowserCacheManager.getCachedNativeRequest: No cached native request found\"\n );\n return null;\n }\n\n const parsedRequest = this.validateAndParseJson(\n cachedRequest\n ) as PlatformAuthRequest;\n if (!parsedRequest) {\n this.logger.error(\n \"BrowserCacheManager.getCachedNativeRequest: Unable to parse native request\"\n );\n return null;\n }\n\n return parsedRequest;\n }\n\n isInteractionInProgress(matchClientId?: boolean): boolean {\n const clientId = this.getInteractionInProgress()?.clientId;\n\n if (matchClientId) {\n return clientId === this.clientId;\n } else {\n return !!clientId;\n }\n }\n\n getInteractionInProgress(): {\n clientId: string;\n type: INTERACTION_TYPE;\n } | null {\n const key = `${CacheKeys.PREFIX}.${TemporaryCacheKeys.INTERACTION_STATUS_KEY}`;\n const value = this.getTemporaryCache(key, false);\n try {\n return value ? JSON.parse(value) : null;\n } catch (e) {\n // Remove interaction and other temp keys if interaction status can't be parsed\n this.logger.error(\n `Cannot parse interaction status. Removing temporary cache items and clearing url hash. Retrying interaction should fix the error`\n );\n this.removeTemporaryItem(key);\n this.resetRequestCache();\n clearHash(window);\n return null;\n }\n }\n\n setInteractionInProgress(\n inProgress: boolean,\n type: INTERACTION_TYPE = INTERACTION_TYPE.SIGNIN\n ): void {\n // Ensure we don't overwrite interaction in progress for a different clientId\n const key = `${CacheKeys.PREFIX}.${TemporaryCacheKeys.INTERACTION_STATUS_KEY}`;\n if (inProgress) {\n if (this.getInteractionInProgress()) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.interactionInProgress\n );\n } else {\n // No interaction is in progress\n this.setTemporaryCache(\n key,\n JSON.stringify({ clientId: this.clientId, type }),\n false\n );\n }\n } else if (\n !inProgress &&\n this.getInteractionInProgress()?.clientId === this.clientId\n ) {\n this.removeTemporaryItem(key);\n }\n }\n\n /**\n * Builds credential entities from AuthenticationResult object and saves the resulting credentials to the cache\n * @param result\n * @param request\n */\n async hydrateCache(\n result: AuthenticationResult,\n request:\n | SilentRequest\n | SsoSilentRequest\n | RedirectRequest\n | PopupRequest\n ): Promise {\n const idTokenEntity = CacheHelpers.createIdTokenEntity(\n result.account?.homeAccountId,\n result.account?.environment,\n result.idToken,\n this.clientId,\n result.tenantId\n );\n\n let claimsHash;\n if (request.claims) {\n claimsHash = await this.cryptoImpl.hashString(request.claims);\n }\n\n /**\n * meta data for cache stores time in seconds from epoch\n * AuthenticationResult returns expiresOn and extExpiresOn in milliseconds (as a Date object which is in ms)\n * We need to map these for the cache when building tokens from AuthenticationResult\n *\n * The next MSAL VFuture should map these both to same value if possible\n */\n\n const accessTokenEntity = CacheHelpers.createAccessTokenEntity(\n result.account?.homeAccountId,\n result.account.environment,\n result.accessToken,\n this.clientId,\n result.tenantId,\n result.scopes.join(\" \"),\n // Access token expiresOn stored in seconds, converting from AuthenticationResult expiresOn stored as Date\n result.expiresOn\n ? TimeUtils.toSecondsFromDate(result.expiresOn)\n : 0,\n result.extExpiresOn\n ? TimeUtils.toSecondsFromDate(result.extExpiresOn)\n : 0,\n base64Decode,\n undefined, // refreshOn\n result.tokenType as AuthenticationScheme,\n undefined, // userAssertionHash\n request.sshKid,\n request.claims,\n claimsHash\n );\n\n const cacheRecord = {\n idToken: idTokenEntity,\n accessToken: accessTokenEntity,\n };\n return this.saveCacheRecord(cacheRecord, result.correlationId);\n }\n\n /**\n * saves a cache record\n * @param cacheRecord {CacheRecord}\n * @param storeInCache {?StoreInCache}\n * @param correlationId {?string} correlation id\n */\n async saveCacheRecord(\n cacheRecord: CacheRecord,\n correlationId: string,\n storeInCache?: StoreInCache\n ): Promise {\n try {\n await super.saveCacheRecord(\n cacheRecord,\n correlationId,\n storeInCache\n );\n } catch (e) {\n if (\n e instanceof CacheError &&\n this.performanceClient &&\n correlationId\n ) {\n try {\n const tokenKeys = this.getTokenKeys();\n\n this.performanceClient.addFields(\n {\n cacheRtCount: tokenKeys.refreshToken.length,\n cacheIdCount: tokenKeys.idToken.length,\n cacheAtCount: tokenKeys.accessToken.length,\n },\n correlationId\n );\n } catch (e) {}\n }\n\n throw e;\n }\n }\n}\n\n/**\n * Returns a window storage class implementing the IWindowStorage interface that corresponds to the configured cacheLocation.\n * @param cacheLocation\n */\nfunction getStorageImplementation(\n clientId: string,\n cacheLocation: BrowserCacheLocation | string,\n logger: Logger,\n performanceClient: IPerformanceClient\n): IWindowStorage {\n try {\n switch (cacheLocation) {\n case BrowserCacheLocation.LocalStorage:\n return new LocalStorage(clientId, logger, performanceClient);\n case BrowserCacheLocation.SessionStorage:\n return new SessionStorage();\n case BrowserCacheLocation.MemoryStorage:\n default:\n break;\n }\n } catch (e) {\n logger.error(e as string);\n }\n\n return new MemoryStorage();\n}\n\nexport const DEFAULT_BROWSER_CACHE_MANAGER = (\n clientId: string,\n logger: Logger,\n performanceClient: IPerformanceClient,\n eventHandler: EventHandler\n): BrowserCacheManager => {\n const cacheOptions: Required = {\n cacheLocation: BrowserCacheLocation.MemoryStorage,\n cacheRetentionDays: 5,\n temporaryCacheLocation: BrowserCacheLocation.MemoryStorage,\n storeAuthStateInCookie: false,\n secureCookies: false,\n cacheMigrationEnabled: false,\n claimsBasedCachingEnabled: false,\n };\n return new BrowserCacheManager(\n clientId,\n cacheOptions,\n DEFAULT_CRYPTO_IMPLEMENTATION,\n logger,\n performanceClient,\n eventHandler\n );\n};\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AccountInfo, AccountFilter, Logger } from \"@azure/msal-common/browser\";\nimport { BrowserCacheManager } from \"./BrowserCacheManager.js\";\n\n/**\n * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.\n * @param accountFilter - (Optional) filter to narrow down the accounts returned\n * @returns Array of AccountInfo objects in cache\n */\nexport function getAllAccounts(\n logger: Logger,\n browserStorage: BrowserCacheManager,\n isInBrowser: boolean,\n correlationId: string,\n accountFilter?: AccountFilter\n): AccountInfo[] {\n logger.verbose(\"getAllAccounts called\");\n return isInBrowser\n ? browserStorage.getAllAccounts(accountFilter || {}, correlationId)\n : [];\n}\n\n/**\n * Returns the first account found in the cache that matches the account filter passed in.\n * @param accountFilter\n * @returns The first account found in the cache matching the provided filter or null if no account could be found.\n */\nexport function getAccount(\n accountFilter: AccountFilter,\n logger: Logger,\n browserStorage: BrowserCacheManager,\n correlationId: string\n): AccountInfo | null {\n const account: AccountInfo | null = browserStorage.getAccountInfoFilteredBy(\n accountFilter,\n correlationId\n );\n\n if (account) {\n logger.verbose(\n \"getAccount: Account matching provided filter found, returning\"\n );\n return account;\n } else {\n logger.verbose(\"getAccount: No matching account found, returning null\");\n return null;\n }\n}\n\n/**\n * Returns the signed in account matching username.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found.\n * This API is provided for convenience but getAccountById should be used for best reliability\n * @param username\n * @returns The account object stored in MSAL\n */\nexport function getAccountByUsername(\n username: string,\n logger: Logger,\n browserStorage: BrowserCacheManager,\n correlationId: string\n): AccountInfo | null {\n logger.trace(\"getAccountByUsername called\");\n if (!username) {\n logger.warning(\"getAccountByUsername: No username provided\");\n return null;\n }\n\n const account = browserStorage.getAccountInfoFilteredBy(\n {\n username,\n },\n correlationId\n );\n if (account) {\n logger.verbose(\n \"getAccountByUsername: Account matching username found, returning\"\n );\n logger.verbosePii(\n `getAccountByUsername: Returning signed-in accounts matching username: ${username}`\n );\n return account;\n } else {\n logger.verbose(\n \"getAccountByUsername: No matching account found, returning null\"\n );\n return null;\n }\n}\n\n/**\n * Returns the signed in account matching homeAccountId.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found\n * @param homeAccountId\n * @returns The account object stored in MSAL\n */\nexport function getAccountByHomeId(\n homeAccountId: string,\n logger: Logger,\n browserStorage: BrowserCacheManager,\n correlationId: string\n): AccountInfo | null {\n logger.trace(\"getAccountByHomeId called\");\n if (!homeAccountId) {\n logger.warning(\"getAccountByHomeId: No homeAccountId provided\");\n return null;\n }\n\n const account = browserStorage.getAccountInfoFilteredBy(\n {\n homeAccountId,\n },\n correlationId\n );\n if (account) {\n logger.verbose(\n \"getAccountByHomeId: Account matching homeAccountId found, returning\"\n );\n logger.verbosePii(\n `getAccountByHomeId: Returning signed-in accounts matching homeAccountId: ${homeAccountId}`\n );\n return account;\n } else {\n logger.verbose(\n \"getAccountByHomeId: No matching account found, returning null\"\n );\n return null;\n }\n}\n\n/**\n * Returns the signed in account matching localAccountId.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found\n * @param localAccountId\n * @returns The account object stored in MSAL\n */\nexport function getAccountByLocalId(\n localAccountId: string,\n logger: Logger,\n browserStorage: BrowserCacheManager,\n correlationId: string\n): AccountInfo | null {\n logger.trace(\"getAccountByLocalId called\");\n if (!localAccountId) {\n logger.warning(\"getAccountByLocalId: No localAccountId provided\");\n return null;\n }\n\n const account = browserStorage.getAccountInfoFilteredBy(\n {\n localAccountId,\n },\n correlationId\n );\n if (account) {\n logger.verbose(\n \"getAccountByLocalId: Account matching localAccountId found, returning\"\n );\n logger.verbosePii(\n `getAccountByLocalId: Returning signed-in accounts matching localAccountId: ${localAccountId}`\n );\n return account;\n } else {\n logger.verbose(\n \"getAccountByLocalId: No matching account found, returning null\"\n );\n return null;\n }\n}\n\n/**\n * Sets the account to use as the active account. If no account is passed to the acquireToken APIs, then MSAL will use this active account.\n * @param account\n */\nexport function setActiveAccount(\n account: AccountInfo | null,\n browserStorage: BrowserCacheManager,\n correlationId: string\n): void {\n browserStorage.setActiveAccount(account, correlationId);\n}\n\n/**\n * Gets the currently active account\n */\nexport function getActiveAccount(\n browserStorage: BrowserCacheManager,\n correlationId: string\n): AccountInfo | null {\n return browserStorage.getActiveAccount(correlationId);\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { Logger } from \"@azure/msal-common/browser\";\nimport { InteractionType } from \"../utils/BrowserConstants.js\";\nimport {\n EventCallbackFunction,\n EventError,\n EventMessage,\n EventPayload,\n} from \"./EventMessage.js\";\nimport { EventType } from \"./EventType.js\";\nimport { createGuid } from \"../utils/BrowserUtils.js\";\n\nconst BROADCAST_CHANNEL_NAME = \"msal.broadcast.event\";\n\nexport class EventHandler {\n // Callback for subscribing to events\n private eventCallbacks: Map<\n string,\n [EventCallbackFunction, Array]\n >;\n private logger: Logger;\n private broadcastChannel?: BroadcastChannel;\n\n constructor(logger?: Logger) {\n this.eventCallbacks = new Map();\n this.logger = logger || new Logger({});\n if (typeof BroadcastChannel !== \"undefined\") {\n this.broadcastChannel = new BroadcastChannel(\n BROADCAST_CHANNEL_NAME\n );\n }\n this.invokeCrossTabCallbacks = this.invokeCrossTabCallbacks.bind(this);\n }\n\n /**\n * Adds event callbacks to array\n * @param callback - callback to be invoked when an event is raised\n * @param eventTypes - list of events that this callback will be invoked for, if not provided callback will be invoked for all events\n * @param callbackId - Identifier for the callback, used to locate and remove the callback when no longer required\n */\n addEventCallback(\n callback: EventCallbackFunction,\n eventTypes?: Array,\n callbackId?: string\n ): string | null {\n if (typeof window !== \"undefined\") {\n const id = callbackId || createGuid();\n if (this.eventCallbacks.has(id)) {\n this.logger.error(\n `Event callback with id: ${id} is already registered. Please provide a unique id or remove the existing callback and try again.`\n );\n return null;\n }\n this.eventCallbacks.set(id, [callback, eventTypes || []]);\n this.logger.verbose(`Event callback registered with id: ${id}`);\n\n return id;\n }\n\n return null;\n }\n\n /**\n * Removes callback with provided id from callback array\n * @param callbackId\n */\n removeEventCallback(callbackId: string): void {\n this.eventCallbacks.delete(callbackId);\n this.logger.verbose(`Event callback ${callbackId} removed.`);\n }\n\n /**\n * Emits events by calling callback with event message\n * @param eventType\n * @param interactionType\n * @param payload\n * @param error\n */\n emitEvent(\n eventType: EventType,\n interactionType?: InteractionType,\n payload?: EventPayload,\n error?: EventError\n ): void {\n const message: EventMessage = {\n eventType: eventType,\n interactionType: interactionType || null,\n payload: payload || null,\n error: error || null,\n timestamp: Date.now(),\n };\n\n switch (eventType) {\n case EventType.ACCOUNT_ADDED:\n case EventType.ACCOUNT_REMOVED:\n case EventType.ACTIVE_ACCOUNT_CHANGED:\n // Send event to other open tabs / MSAL instances on same domain\n this.broadcastChannel?.postMessage(message);\n break;\n default:\n // Emit event to callbacks registered in this instance\n this.invokeCallbacks(message);\n break;\n }\n }\n\n /**\n * Invoke registered callbacks\n * @param message\n */\n private invokeCallbacks(message: EventMessage): void {\n this.eventCallbacks.forEach(\n (\n [callback, eventTypes]: [\n EventCallbackFunction,\n Array\n ],\n callbackId: string\n ) => {\n if (\n eventTypes.length === 0 ||\n eventTypes.includes(message.eventType)\n ) {\n this.logger.verbose(\n `Emitting event to callback ${callbackId}: ${message.eventType}`\n );\n callback.apply(null, [message]);\n }\n }\n );\n }\n\n /**\n * Wrapper around invokeCallbacks to handle broadcast events received from other tabs/instances\n * @param event\n */\n private invokeCrossTabCallbacks(event: MessageEvent): void {\n const message = event.data as EventMessage;\n this.invokeCallbacks(message);\n }\n\n /**\n * Listen for events broadcasted from other tabs/instances\n */\n subscribeCrossTab(): void {\n this.broadcastChannel?.addEventListener(\n \"message\",\n this.invokeCrossTabCallbacks\n );\n }\n\n /**\n * Unsubscribe from broadcast events\n */\n unsubscribeCrossTab(): void {\n this.broadcastChannel?.removeEventListener(\n \"message\",\n this.invokeCrossTabCallbacks\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ICrypto,\n INetworkModule,\n Logger,\n AccountInfo,\n UrlString,\n ServerTelemetryManager,\n ServerTelemetryRequest,\n createClientConfigurationError,\n ClientConfigurationErrorCodes,\n Authority,\n AuthorityOptions,\n AuthorityFactory,\n IPerformanceClient,\n PerformanceEvents,\n AzureCloudOptions,\n invokeAsync,\n StringDict,\n} from \"@azure/msal-common/browser\";\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\nimport { EventHandler } from \"../event/EventHandler.js\";\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\nimport { PopupRequest } from \"../request/PopupRequest.js\";\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\nimport { version } from \"../packageMetadata.js\";\nimport { BrowserConstants } from \"../utils/BrowserConstants.js\";\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\nimport { createNewGuid } from \"../crypto/BrowserCrypto.js\";\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\n\nexport abstract class BaseInteractionClient {\n protected config: BrowserConfiguration;\n protected browserStorage: BrowserCacheManager;\n protected browserCrypto: ICrypto;\n protected networkClient: INetworkModule;\n protected logger: Logger;\n protected eventHandler: EventHandler;\n protected navigationClient: INavigationClient;\n protected platformAuthProvider: IPlatformAuthHandler | undefined;\n protected correlationId: string;\n protected performanceClient: IPerformanceClient;\n\n constructor(\n config: BrowserConfiguration,\n storageImpl: BrowserCacheManager,\n browserCrypto: ICrypto,\n logger: Logger,\n eventHandler: EventHandler,\n navigationClient: INavigationClient,\n performanceClient: IPerformanceClient,\n platformAuthProvider?: IPlatformAuthHandler,\n correlationId?: string\n ) {\n this.config = config;\n this.browserStorage = storageImpl;\n this.browserCrypto = browserCrypto;\n this.networkClient = this.config.system.networkClient;\n this.eventHandler = eventHandler;\n this.navigationClient = navigationClient;\n this.platformAuthProvider = platformAuthProvider;\n this.correlationId = correlationId || createNewGuid();\n this.logger = logger.clone(\n BrowserConstants.MSAL_SKU,\n version,\n this.correlationId\n );\n this.performanceClient = performanceClient;\n }\n\n abstract acquireToken(\n request: RedirectRequest | PopupRequest | SsoSilentRequest\n ): Promise;\n\n abstract logout(\n request: EndSessionRequest | ClearCacheRequest | undefined\n ): Promise;\n\n protected async clearCacheOnLogout(\n correlationId: string,\n account?: AccountInfo | null\n ): Promise {\n if (account) {\n // Clear given account.\n try {\n this.browserStorage.removeAccount(account, correlationId);\n this.logger.verbose(\n \"Cleared cache items belonging to the account provided in the logout request.\"\n );\n } catch (error) {\n this.logger.error(\n \"Account provided in logout request was not found. Local cache unchanged.\"\n );\n }\n } else {\n try {\n this.logger.verbose(\n \"No account provided in logout request, clearing all cache items.\",\n this.correlationId\n );\n // Clear all accounts and tokens\n this.browserStorage.clear(correlationId);\n // Clear any stray keys from IndexedDB\n await this.browserCrypto.clearKeystore();\n } catch (e) {\n this.logger.error(\n \"Attempted to clear all MSAL cache items and failed. Local cache unchanged.\"\n );\n }\n }\n }\n\n /**\n *\n * Use to get the redirect uri configured in MSAL or null.\n * @param requestRedirectUri\n * @returns Redirect URL\n *\n */\n getRedirectUri(requestRedirectUri?: string): string {\n this.logger.verbose(\"getRedirectUri called\");\n const redirectUri = requestRedirectUri || this.config.auth.redirectUri;\n return UrlString.getAbsoluteUrl(\n redirectUri,\n BrowserUtils.getCurrentUri()\n );\n }\n\n /**\n *\n * @param apiId\n * @param correlationId\n * @param forceRefresh\n */\n protected initializeServerTelemetryManager(\n apiId: number,\n forceRefresh?: boolean\n ): ServerTelemetryManager {\n this.logger.verbose(\"initializeServerTelemetryManager called\");\n const telemetryPayload: ServerTelemetryRequest = {\n clientId: this.config.auth.clientId,\n correlationId: this.correlationId,\n apiId: apiId,\n forceRefresh: forceRefresh || false,\n wrapperSKU: this.browserStorage.getWrapperMetadata()[0],\n wrapperVer: this.browserStorage.getWrapperMetadata()[1],\n };\n\n return new ServerTelemetryManager(\n telemetryPayload,\n this.browserStorage\n );\n }\n\n /**\n * Used to get a discovered version of the default authority.\n * @param params {\n * requestAuthority?: string;\n * requestAzureCloudOptions?: AzureCloudOptions;\n * requestExtraQueryParameters?: StringDict;\n * account?: AccountInfo;\n * }\n */\n protected async getDiscoveredAuthority(params: {\n requestAuthority?: string;\n requestAzureCloudOptions?: AzureCloudOptions;\n requestExtraQueryParameters?: StringDict;\n account?: AccountInfo;\n }): Promise {\n const { account } = params;\n const instanceAwareEQ =\n params.requestExtraQueryParameters &&\n params.requestExtraQueryParameters.hasOwnProperty(\"instance_aware\")\n ? params.requestExtraQueryParameters[\"instance_aware\"]\n : undefined;\n\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\n this.correlationId\n );\n const authorityOptions: AuthorityOptions = {\n protocolMode: this.config.auth.protocolMode,\n OIDCOptions: this.config.auth.OIDCOptions,\n knownAuthorities: this.config.auth.knownAuthorities,\n cloudDiscoveryMetadata: this.config.auth.cloudDiscoveryMetadata,\n authorityMetadata: this.config.auth.authorityMetadata,\n skipAuthorityMetadataCache:\n this.config.auth.skipAuthorityMetadataCache,\n };\n\n // build authority string based on auth params, precedence - azureCloudInstance + tenant >> authority\n const resolvedAuthority =\n params.requestAuthority || this.config.auth.authority;\n const resolvedInstanceAware = instanceAwareEQ?.length\n ? instanceAwareEQ === \"true\"\n : this.config.auth.instanceAware;\n\n const userAuthority =\n account && resolvedInstanceAware\n ? this.config.auth.authority.replace(\n UrlString.getDomainFromUrl(resolvedAuthority),\n account.environment\n )\n : resolvedAuthority;\n\n // fall back to the authority from config\n const builtAuthority = Authority.generateAuthority(\n userAuthority,\n params.requestAzureCloudOptions ||\n this.config.auth.azureCloudOptions\n );\n const discoveredAuthority = await invokeAsync(\n AuthorityFactory.createDiscoveredInstance,\n PerformanceEvents.AuthorityFactoryCreateDiscoveredInstance,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(\n builtAuthority,\n this.config.system.networkClient,\n this.browserStorage,\n authorityOptions,\n this.logger,\n this.correlationId,\n this.performanceClient\n );\n\n if (account && !discoveredAuthority.isAlias(account.environment)) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.authorityMismatch\n );\n }\n\n return discoveredAuthority;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n AccountInfo,\n AuthenticationScheme,\n BaseAuthRequest,\n ClientConfigurationErrorCodes,\n CommonSilentFlowRequest,\n HttpMethod,\n IPerformanceClient,\n Logger,\n PerformanceEvents,\n ProtocolMode,\n StringUtils,\n createClientConfigurationError,\n invokeAsync,\n} from \"@azure/msal-common/browser\";\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\nimport { SilentRequest } from \"./SilentRequest.js\";\nimport { hashString } from \"../crypto/BrowserCrypto.js\";\nimport { PopupRequest } from \"./PopupRequest.js\";\nimport { RedirectRequest } from \"./RedirectRequest.js\";\n\n/**\n * Initializer function for all request APIs\n * @param request\n */\nexport async function initializeBaseRequest(\n request: Partial & { correlationId: string },\n config: BrowserConfiguration,\n performanceClient: IPerformanceClient,\n logger: Logger\n): Promise {\n performanceClient.addQueueMeasurement(\n PerformanceEvents.InitializeBaseRequest,\n request.correlationId\n );\n const authority = request.authority || config.auth.authority;\n\n const scopes = [...((request && request.scopes) || [])];\n\n const validatedRequest: BaseAuthRequest = {\n ...request,\n correlationId: request.correlationId,\n authority,\n scopes,\n };\n\n // Set authenticationScheme to BEARER if not explicitly set in the request\n if (!validatedRequest.authenticationScheme) {\n validatedRequest.authenticationScheme = AuthenticationScheme.BEARER;\n logger.verbose(\n 'Authentication Scheme wasn\\'t explicitly set in request, defaulting to \"Bearer\" request'\n );\n } else {\n if (\n validatedRequest.authenticationScheme === AuthenticationScheme.SSH\n ) {\n if (!request.sshJwk) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.missingSshJwk\n );\n }\n if (!request.sshKid) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.missingSshKid\n );\n }\n }\n logger.verbose(\n `Authentication Scheme set to \"${validatedRequest.authenticationScheme}\" as configured in Auth request`\n );\n }\n\n // Set requested claims hash if claims-based caching is enabled and claims were requested\n if (\n config.cache.claimsBasedCachingEnabled &&\n request.claims &&\n // Checks for empty stringified object \"{}\" which doesn't qualify as requested claims\n !StringUtils.isEmptyObj(request.claims)\n ) {\n validatedRequest.requestedClaimsHash = await hashString(request.claims);\n }\n\n return validatedRequest;\n}\n\nexport async function initializeSilentRequest(\n request: SilentRequest & { correlationId: string },\n account: AccountInfo,\n config: BrowserConfiguration,\n performanceClient: IPerformanceClient,\n logger: Logger\n): Promise {\n performanceClient.addQueueMeasurement(\n PerformanceEvents.InitializeSilentRequest,\n request.correlationId\n );\n\n const baseRequest = await invokeAsync(\n initializeBaseRequest,\n PerformanceEvents.InitializeBaseRequest,\n logger,\n performanceClient,\n request.correlationId\n )(request, config, performanceClient, logger);\n return {\n ...request,\n ...baseRequest,\n account: account,\n forceRefresh: request.forceRefresh || false,\n };\n}\n\n/**\n * Validates that the combination of request method, protocol mode and authorize body parameters is correct.\n * Returns the validated or defaulted HTTP method or throws if the configured combination is invalid.\n * @param interactionRequest\n * @param protocolMode\n * @returns\n */\nexport function validateRequestMethod(\n interactionRequest: BaseAuthRequest | PopupRequest | RedirectRequest,\n protocolMode: ProtocolMode\n): HttpMethod {\n let httpMethod: HttpMethod | undefined;\n const requestMethod = interactionRequest.httpMethod;\n\n if (protocolMode === ProtocolMode.EAR) {\n // Don't override httpMethod if it is already set, default to POST if not set\n httpMethod = requestMethod || HttpMethod.POST;\n // Validate that method is not GET if protocol mode is EAR\n if (httpMethod !== HttpMethod.POST) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.invalidRequestMethodForEAR\n );\n }\n } else {\n // For non-EAR protocol modes, default to GET if httpMethod is not set\n httpMethod = requestMethod || HttpMethod.GET;\n }\n\n // Regardless of protocolMode, if there are authorizePostBodyParameters, validate the request method is POST\n if (\n interactionRequest.authorizePostBodyParameters &&\n httpMethod !== HttpMethod.POST\n ) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.invalidAuthorizePostBodyParameters\n );\n }\n\n return httpMethod;\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ServerTelemetryManager,\n Constants,\n AuthorizationCodeClient,\n ClientConfiguration,\n UrlString,\n CommonEndSessionRequest,\n ProtocolUtils,\n ResponseMode,\n IdTokenClaims,\n AccountInfo,\n AzureCloudOptions,\n PerformanceEvents,\n invokeAsync,\n BaseAuthRequest,\n StringDict,\n CommonAuthorizationUrlRequest,\n} from \"@azure/msal-common/browser\";\nimport { BaseInteractionClient } from \"./BaseInteractionClient.js\";\nimport {\n BrowserConstants,\n InteractionType,\n} from \"../utils/BrowserConstants.js\";\nimport { version } from \"../packageMetadata.js\";\nimport { BrowserStateObject } from \"../utils/BrowserProtocolUtils.js\";\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\nimport { PopupRequest } from \"../request/PopupRequest.js\";\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\nimport { createNewGuid } from \"../crypto/BrowserCrypto.js\";\nimport {\n initializeBaseRequest,\n validateRequestMethod,\n} from \"../request/RequestHelpers.js\";\n\n/**\n * Defines the class structure and helper functions used by the \"standard\", non-brokered auth flows (popup, redirect, silent (RT), silent (iframe))\n */\nexport abstract class StandardInteractionClient extends BaseInteractionClient {\n /**\n * Initializer for the logout request.\n * @param logoutRequest\n */\n protected initializeLogoutRequest(\n logoutRequest?: EndSessionRequest\n ): CommonEndSessionRequest {\n this.logger.verbose(\n \"initializeLogoutRequest called\",\n logoutRequest?.correlationId\n );\n\n const validLogoutRequest: CommonEndSessionRequest = {\n correlationId: this.correlationId || createNewGuid(),\n ...logoutRequest,\n };\n\n /**\n * Set logout_hint to be login_hint from ID Token Claims if present\n * and logoutHint attribute wasn't manually set in logout request\n */\n if (logoutRequest) {\n // If logoutHint isn't set and an account was passed in, try to extract logoutHint from ID Token Claims\n if (!logoutRequest.logoutHint) {\n if (logoutRequest.account) {\n const logoutHint = this.getLogoutHintFromIdTokenClaims(\n logoutRequest.account\n );\n if (logoutHint) {\n this.logger.verbose(\n \"Setting logoutHint to login_hint ID Token Claim value for the account provided\"\n );\n validLogoutRequest.logoutHint = logoutHint;\n }\n } else {\n this.logger.verbose(\n \"logoutHint was not set and account was not passed into logout request, logoutHint will not be set\"\n );\n }\n } else {\n this.logger.verbose(\n \"logoutHint has already been set in logoutRequest\"\n );\n }\n } else {\n this.logger.verbose(\n \"logoutHint will not be set since no logout request was configured\"\n );\n }\n\n /*\n * Only set redirect uri if logout request isn't provided or the set uri isn't null.\n * Otherwise, use passed uri, config, or current page.\n */\n if (!logoutRequest || logoutRequest.postLogoutRedirectUri !== null) {\n if (logoutRequest && logoutRequest.postLogoutRedirectUri) {\n this.logger.verbose(\n \"Setting postLogoutRedirectUri to uri set on logout request\",\n validLogoutRequest.correlationId\n );\n validLogoutRequest.postLogoutRedirectUri =\n UrlString.getAbsoluteUrl(\n logoutRequest.postLogoutRedirectUri,\n BrowserUtils.getCurrentUri()\n );\n } else if (this.config.auth.postLogoutRedirectUri === null) {\n this.logger.verbose(\n \"postLogoutRedirectUri configured as null and no uri set on request, not passing post logout redirect\",\n validLogoutRequest.correlationId\n );\n } else if (this.config.auth.postLogoutRedirectUri) {\n this.logger.verbose(\n \"Setting postLogoutRedirectUri to configured uri\",\n validLogoutRequest.correlationId\n );\n validLogoutRequest.postLogoutRedirectUri =\n UrlString.getAbsoluteUrl(\n this.config.auth.postLogoutRedirectUri,\n BrowserUtils.getCurrentUri()\n );\n } else {\n this.logger.verbose(\n \"Setting postLogoutRedirectUri to current page\",\n validLogoutRequest.correlationId\n );\n validLogoutRequest.postLogoutRedirectUri =\n UrlString.getAbsoluteUrl(\n BrowserUtils.getCurrentUri(),\n BrowserUtils.getCurrentUri()\n );\n }\n } else {\n this.logger.verbose(\n \"postLogoutRedirectUri passed as null, not setting post logout redirect uri\",\n validLogoutRequest.correlationId\n );\n }\n\n return validLogoutRequest;\n }\n\n /**\n * Parses login_hint ID Token Claim out of AccountInfo object to be used as\n * logout_hint in end session request.\n * @param account\n */\n protected getLogoutHintFromIdTokenClaims(\n account: AccountInfo\n ): string | null {\n const idTokenClaims: IdTokenClaims | undefined = account.idTokenClaims;\n if (idTokenClaims) {\n if (idTokenClaims.login_hint) {\n return idTokenClaims.login_hint;\n } else {\n this.logger.verbose(\n \"The ID Token Claims tied to the provided account do not contain a login_hint claim, logoutHint will not be added to logout request\"\n );\n }\n } else {\n this.logger.verbose(\n \"The provided account does not contain ID Token Claims, logoutHint will not be added to logout request\"\n );\n }\n\n return null;\n }\n\n /**\n * Creates an Authorization Code Client with the given authority, or the default authority.\n * @param params {\n * serverTelemetryManager: ServerTelemetryManager;\n * authorityUrl?: string;\n * requestAzureCloudOptions?: AzureCloudOptions;\n * requestExtraQueryParameters?: StringDict;\n * account?: AccountInfo;\n * }\n */\n protected async createAuthCodeClient(params: {\n serverTelemetryManager: ServerTelemetryManager;\n requestAuthority?: string;\n requestAzureCloudOptions?: AzureCloudOptions;\n requestExtraQueryParameters?: StringDict;\n account?: AccountInfo;\n }): Promise {\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\n this.correlationId\n );\n // Create auth module.\n const clientConfig = await invokeAsync(\n this.getClientConfiguration.bind(this),\n PerformanceEvents.StandardInteractionClientGetClientConfiguration,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(params);\n\n return new AuthorizationCodeClient(\n clientConfig,\n this.performanceClient\n );\n }\n\n /**\n * Creates a Client Configuration object with the given request authority, or the default authority.\n * @param params {\n * serverTelemetryManager: ServerTelemetryManager;\n * requestAuthority?: string;\n * requestAzureCloudOptions?: AzureCloudOptions;\n * requestExtraQueryParameters?: boolean;\n * account?: AccountInfo;\n * }\n */\n protected async getClientConfiguration(params: {\n serverTelemetryManager: ServerTelemetryManager;\n requestAuthority?: string;\n requestAzureCloudOptions?: AzureCloudOptions;\n requestExtraQueryParameters?: StringDict;\n account?: AccountInfo;\n }): Promise {\n const {\n serverTelemetryManager,\n requestAuthority,\n requestAzureCloudOptions,\n requestExtraQueryParameters,\n account,\n } = params;\n\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.StandardInteractionClientGetClientConfiguration,\n this.correlationId\n );\n const discoveredAuthority = await invokeAsync(\n this.getDiscoveredAuthority.bind(this),\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\n this.logger,\n this.performanceClient,\n this.correlationId\n )({\n requestAuthority,\n requestAzureCloudOptions,\n requestExtraQueryParameters,\n account,\n });\n const logger = this.config.system.loggerOptions;\n\n return {\n authOptions: {\n clientId: this.config.auth.clientId,\n authority: discoveredAuthority,\n clientCapabilities: this.config.auth.clientCapabilities,\n redirectUri: this.config.auth.redirectUri,\n },\n systemOptions: {\n tokenRenewalOffsetSeconds:\n this.config.system.tokenRenewalOffsetSeconds,\n preventCorsPreflight: true,\n },\n loggerOptions: {\n loggerCallback: logger.loggerCallback,\n piiLoggingEnabled: logger.piiLoggingEnabled,\n logLevel: logger.logLevel,\n correlationId: this.correlationId,\n },\n cacheOptions: {\n claimsBasedCachingEnabled:\n this.config.cache.claimsBasedCachingEnabled,\n },\n cryptoInterface: this.browserCrypto,\n networkInterface: this.networkClient,\n storageInterface: this.browserStorage,\n serverTelemetryManager: serverTelemetryManager,\n libraryInfo: {\n sku: BrowserConstants.MSAL_SKU,\n version: version,\n cpu: Constants.EMPTY_STRING,\n os: Constants.EMPTY_STRING,\n },\n telemetry: this.config.telemetry,\n };\n }\n\n /**\n * Helper to initialize required request parameters for interactive APIs and ssoSilent()\n * @param request\n * @param interactionType\n */\n protected async initializeAuthorizationRequest(\n request: RedirectRequest | PopupRequest | SsoSilentRequest,\n interactionType: InteractionType\n ): Promise {\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,\n this.correlationId\n );\n\n const redirectUri = this.getRedirectUri(request.redirectUri);\n const browserState: BrowserStateObject = {\n interactionType: interactionType,\n };\n const state = ProtocolUtils.setRequestState(\n this.browserCrypto,\n (request && request.state) || Constants.EMPTY_STRING,\n browserState\n );\n\n const baseRequest: BaseAuthRequest = await invokeAsync(\n initializeBaseRequest,\n PerformanceEvents.InitializeBaseRequest,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(\n { ...request, correlationId: this.correlationId },\n this.config,\n this.performanceClient,\n this.logger\n );\n\n const interactionRequest: CommonAuthorizationUrlRequest = {\n ...baseRequest,\n redirectUri: redirectUri,\n state: state,\n nonce: request.nonce || createNewGuid(),\n responseMode: this.config.auth.OIDCOptions\n .serverResponseType as ResponseMode,\n };\n\n const validatedRequest = {\n ...interactionRequest,\n httpMethod: validateRequestMethod(\n interactionRequest,\n this.config.auth.protocolMode\n ),\n };\n\n // Skip active account lookup if either login hint or session id is set\n if (request.loginHint || request.sid) {\n return validatedRequest;\n }\n\n const account =\n request.account ||\n this.browserStorage.getActiveAccount(this.correlationId);\n if (account) {\n this.logger.verbose(\n \"Setting validated request account\",\n this.correlationId\n );\n this.logger.verbosePii(\n `Setting validated request account: ${account.homeAccountId}`,\n this.correlationId\n );\n validatedRequest.account = account;\n }\n\n return validatedRequest;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { InteractionType } from \"./BrowserConstants.js\";\nimport {\n ICrypto,\n RequestStateObject,\n ProtocolUtils,\n createClientAuthError,\n ClientAuthErrorCodes,\n} from \"@azure/msal-common/browser\";\n\nexport type BrowserStateObject = {\n interactionType: InteractionType;\n};\n\n/**\n * Extracts the BrowserStateObject from the state string.\n * @param browserCrypto\n * @param state\n */\nexport function extractBrowserRequestState(\n browserCrypto: ICrypto,\n state: string\n): BrowserStateObject | null {\n if (!state) {\n return null;\n }\n\n try {\n const requestStateObj: RequestStateObject =\n ProtocolUtils.parseRequestState(browserCrypto, state);\n return requestStateObj.libraryState.meta as BrowserStateObject;\n } catch (e) {\n throw createClientAuthError(ClientAuthErrorCodes.invalidState);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ICrypto,\n Logger,\n AuthorizeResponse,\n UrlUtils,\n} from \"@azure/msal-common/browser\";\nimport {\n BrowserAuthErrorCodes,\n createBrowserAuthError,\n} from \"../error/BrowserAuthError.js\";\nimport { extractBrowserRequestState } from \"../utils/BrowserProtocolUtils.js\";\nimport { InteractionType } from \"../utils/BrowserConstants.js\";\n\nexport function deserializeResponse(\n responseString: string,\n responseLocation: string,\n logger: Logger\n): AuthorizeResponse {\n // Deserialize hash fragment response parameters.\n const serverParams = UrlUtils.getDeserializedResponse(responseString);\n if (!serverParams) {\n if (!UrlUtils.stripLeadingHashOrQuery(responseString)) {\n // Hash or Query string is empty\n logger.error(\n `The request has returned to the redirectUri but a ${responseLocation} is not present. It's likely that the ${responseLocation} has been removed or the page has been redirected by code running on the redirectUri page.`\n );\n throw createBrowserAuthError(BrowserAuthErrorCodes.hashEmptyError);\n } else {\n logger.error(\n `A ${responseLocation} is present in the iframe but it does not contain known properties. It's likely that the ${responseLocation} has been replaced by code running on the redirectUri page.`\n );\n logger.errorPii(\n `The ${responseLocation} detected is: ${responseString}`\n );\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.hashDoesNotContainKnownProperties\n );\n }\n }\n return serverParams;\n}\n\n/**\n * Returns the interaction type that the response object belongs to\n */\nexport function validateInteractionType(\n response: AuthorizeResponse,\n browserCrypto: ICrypto,\n interactionType: InteractionType\n): void {\n if (!response.state) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.noStateInHash);\n }\n\n const platformStateObj = extractBrowserRequestState(\n browserCrypto,\n response.state\n );\n if (!platformStateObj) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.unableToParseState);\n }\n\n if (platformStateObj.interactionType !== interactionType) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.stateInteractionTypeMismatch\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n AuthorizationCodePayload,\n CommonAuthorizationCodeRequest,\n AuthorizationCodeClient,\n CcsCredential,\n Logger,\n ServerError,\n IPerformanceClient,\n PerformanceEvents,\n invokeAsync,\n CcsCredentialType,\n AuthorizeResponse,\n AuthorizeProtocol,\n CommonAuthorizationUrlRequest,\n} from \"@azure/msal-common/browser\";\n\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\n\n/**\n * Abstract class which defines operations for a browser interaction handling class.\n */\nexport class InteractionHandler {\n protected authModule: AuthorizationCodeClient;\n protected browserStorage: BrowserCacheManager;\n protected authCodeRequest: CommonAuthorizationCodeRequest;\n protected logger: Logger;\n protected performanceClient: IPerformanceClient;\n\n constructor(\n authCodeModule: AuthorizationCodeClient,\n storageImpl: BrowserCacheManager,\n authCodeRequest: CommonAuthorizationCodeRequest,\n logger: Logger,\n performanceClient: IPerformanceClient\n ) {\n this.authModule = authCodeModule;\n this.browserStorage = storageImpl;\n this.authCodeRequest = authCodeRequest;\n this.logger = logger;\n this.performanceClient = performanceClient;\n }\n\n /**\n * Function to handle response parameters from hash.\n * @param locationHash\n */\n async handleCodeResponse(\n response: AuthorizeResponse,\n request: CommonAuthorizationUrlRequest\n ): Promise {\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.HandleCodeResponse,\n request.correlationId\n );\n\n let authCodeResponse;\n try {\n authCodeResponse = AuthorizeProtocol.getAuthorizationCodePayload(\n response,\n request.state\n );\n } catch (e) {\n if (\n e instanceof ServerError &&\n e.subError === BrowserAuthErrorCodes.userCancelled\n ) {\n // Translate server error caused by user closing native prompt to corresponding first class MSAL error\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.userCancelled\n );\n } else {\n throw e;\n }\n }\n\n return invokeAsync(\n this.handleCodeResponseFromServer.bind(this),\n PerformanceEvents.HandleCodeResponseFromServer,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(authCodeResponse, request);\n }\n\n /**\n * Process auth code response from AAD\n * @param authCodeResponse\n * @param state\n * @param authority\n * @param networkModule\n * @returns\n */\n async handleCodeResponseFromServer(\n authCodeResponse: AuthorizationCodePayload,\n request: CommonAuthorizationUrlRequest,\n validateNonce: boolean = true\n ): Promise {\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.HandleCodeResponseFromServer,\n request.correlationId\n );\n this.logger.trace(\n \"InteractionHandler.handleCodeResponseFromServer called\"\n );\n\n // Assign code to request\n this.authCodeRequest.code = authCodeResponse.code;\n\n // Check for new cloud instance\n if (authCodeResponse.cloud_instance_host_name) {\n await invokeAsync(\n this.authModule.updateAuthority.bind(this.authModule),\n PerformanceEvents.UpdateTokenEndpointAuthority,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(authCodeResponse.cloud_instance_host_name, request.correlationId);\n }\n\n // Nonce validation not needed when redirect not involved (e.g. hybrid spa, renewing token via rt)\n if (validateNonce) {\n // TODO: Assigning \"response nonce\" to \"request nonce\" is confusing. Refactor the function doing validation to accept request nonce directly\n authCodeResponse.nonce = request.nonce || undefined;\n }\n\n authCodeResponse.state = request.state;\n\n // Add CCS parameters if available\n if (authCodeResponse.client_info) {\n this.authCodeRequest.clientInfo = authCodeResponse.client_info;\n } else {\n const ccsCred = this.createCcsCredentials(request);\n if (ccsCred) {\n this.authCodeRequest.ccsCredential = ccsCred;\n }\n }\n\n // Acquire token with retrieved code.\n const tokenResponse = (await invokeAsync(\n this.authModule.acquireToken.bind(this.authModule),\n PerformanceEvents.AuthClientAcquireToken,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(this.authCodeRequest, authCodeResponse)) as AuthenticationResult;\n return tokenResponse;\n }\n\n /**\n * Build ccs creds if available\n */\n protected createCcsCredentials(\n request: CommonAuthorizationUrlRequest\n ): CcsCredential | null {\n if (request.account) {\n return {\n credential: request.account.homeAccountId,\n type: CcsCredentialType.HOME_ACCOUNT_ID,\n };\n } else if (request.loginHint) {\n return {\n credential: request.loginHint,\n type: CcsCredentialType.UPN,\n };\n }\n\n return null;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const contentError = \"ContentError\";\nexport const userSwitch = \"user_switch\";\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n// Status Codes that can be thrown by WAM\nexport const USER_INTERACTION_REQUIRED = \"USER_INTERACTION_REQUIRED\";\nexport const USER_CANCEL = \"USER_CANCEL\";\nexport const NO_NETWORK = \"NO_NETWORK\";\nexport const TRANSIENT_ERROR = \"TRANSIENT_ERROR\";\nexport const PERSISTENT_ERROR = \"PERSISTENT_ERROR\";\nexport const DISABLED = \"DISABLED\";\nexport const ACCOUNT_UNAVAILABLE = \"ACCOUNT_UNAVAILABLE\";\nexport const UX_NOT_ALLOWED = \"UX_NOT_ALLOWED\";\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n AuthError,\n InteractionRequiredAuthError,\n InteractionRequiredAuthErrorCodes,\n createInteractionRequiredAuthError,\n} from \"@azure/msal-common/browser\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"./BrowserAuthError.js\";\n\nimport * as NativeAuthErrorCodes from \"./NativeAuthErrorCodes.js\";\nimport * as NativeStatusCodes from \"../broker/nativeBroker/NativeStatusCodes.js\";\nexport { NativeAuthErrorCodes };\n\nexport type OSError = {\n error?: number;\n protocol_error?: string;\n properties?: object;\n status?: string;\n retryable?: boolean;\n};\n\nconst INVALID_METHOD_ERROR = -2147186943;\n\nexport const NativeAuthErrorMessages = {\n [NativeAuthErrorCodes.userSwitch]:\n \"User attempted to switch accounts in the native broker, which is not allowed. All new accounts must sign-in through the standard web flow first, please try again.\",\n};\n\nexport class NativeAuthError extends AuthError {\n ext: OSError | undefined;\n\n constructor(errorCode: string, description?: string, ext?: OSError) {\n super(errorCode, description);\n\n Object.setPrototypeOf(this, NativeAuthError.prototype);\n this.name = \"NativeAuthError\";\n this.ext = ext;\n }\n}\n\n/**\n * These errors should result in a fallback to the 'standard' browser based auth flow.\n */\nexport function isFatalNativeAuthError(error: NativeAuthError): boolean {\n if (\n error.ext &&\n error.ext.status &&\n error.ext.status === NativeStatusCodes.DISABLED\n ) {\n return true;\n }\n\n if (\n error.ext &&\n error.ext.error &&\n error.ext.error === INVALID_METHOD_ERROR\n ) {\n return true;\n }\n\n switch (error.errorCode) {\n case NativeAuthErrorCodes.contentError:\n return true;\n default:\n return false;\n }\n}\n\n/**\n * Create the appropriate error object based on the WAM status code.\n * @param code\n * @param description\n * @param ext\n * @returns\n */\nexport function createNativeAuthError(\n code: string,\n description?: string,\n ext?: OSError\n): AuthError {\n if (ext && ext.status) {\n switch (ext.status) {\n case NativeStatusCodes.ACCOUNT_UNAVAILABLE:\n return createInteractionRequiredAuthError(\n InteractionRequiredAuthErrorCodes.nativeAccountUnavailable\n );\n case NativeStatusCodes.USER_INTERACTION_REQUIRED:\n return new InteractionRequiredAuthError(code, description);\n case NativeStatusCodes.USER_CANCEL:\n return createBrowserAuthError(\n BrowserAuthErrorCodes.userCancelled\n );\n case NativeStatusCodes.NO_NETWORK:\n return createBrowserAuthError(\n BrowserAuthErrorCodes.noNetworkConnectivity\n );\n case NativeStatusCodes.UX_NOT_ALLOWED:\n return createInteractionRequiredAuthError(\n InteractionRequiredAuthErrorCodes.uxNotAllowed\n );\n }\n }\n\n return new NativeAuthError(\n code,\n NativeAuthErrorMessages[code] || description,\n ext\n );\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { StandardInteractionClient } from \"./StandardInteractionClient.js\";\nimport {\n CommonSilentFlowRequest,\n SilentFlowClient,\n PerformanceEvents,\n invokeAsync,\n} from \"@azure/msal-common/browser\";\nimport { ApiId } from \"../utils/BrowserConstants.js\";\nimport {\n BrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\n\nexport class SilentCacheClient extends StandardInteractionClient {\n /**\n * Returns unexpired tokens from the cache, if available\n * @param silentRequest\n */\n async acquireToken(\n silentRequest: CommonSilentFlowRequest\n ): Promise {\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.SilentCacheClientAcquireToken,\n silentRequest.correlationId\n );\n // Telemetry manager only used to increment cacheHits here\n const serverTelemetryManager = this.initializeServerTelemetryManager(\n ApiId.acquireTokenSilent_silentFlow\n );\n\n const clientConfig = await invokeAsync(\n this.getClientConfiguration.bind(this),\n PerformanceEvents.StandardInteractionClientGetClientConfiguration,\n this.logger,\n this.performanceClient,\n this.correlationId\n )({\n serverTelemetryManager,\n requestAuthority: silentRequest.authority,\n requestAzureCloudOptions: silentRequest.azureCloudOptions,\n account: silentRequest.account,\n });\n const silentAuthClient = new SilentFlowClient(\n clientConfig,\n this.performanceClient\n );\n this.logger.verbose(\"Silent auth client created\");\n\n try {\n const response = await invokeAsync(\n silentAuthClient.acquireCachedToken.bind(silentAuthClient),\n PerformanceEvents.SilentFlowClientAcquireCachedToken,\n this.logger,\n this.performanceClient,\n silentRequest.correlationId\n )(silentRequest);\n const authResponse = response[0] as AuthenticationResult;\n\n this.performanceClient.addFields(\n {\n fromCache: true,\n },\n silentRequest.correlationId\n );\n return authResponse;\n } catch (error) {\n if (\n error instanceof BrowserAuthError &&\n error.errorCode === BrowserAuthErrorCodes.cryptoKeyNotFound\n ) {\n this.logger.verbose(\n \"Signing keypair for bound access token not found. Refreshing bound access token and generating a new crypto keypair.\"\n );\n }\n throw error;\n }\n }\n\n /**\n * API to silenty clear the browser cache.\n * @param logoutRequest\n */\n logout(logoutRequest?: ClearCacheRequest): Promise {\n this.logger.verbose(\"logoutRedirect called\");\n const validLogoutRequest = this.initializeLogoutRequest(logoutRequest);\n return this.clearCacheOnLogout(\n validLogoutRequest.correlationId,\n validLogoutRequest?.account\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n Logger,\n ICrypto,\n PromptValue,\n AuthToken,\n Constants,\n AccountEntity,\n AuthorityType,\n ScopeSet,\n TimeUtils,\n AuthenticationScheme,\n UrlString,\n OIDC_DEFAULT_SCOPES,\n PopTokenGenerator,\n SignedHttpRequestParameters,\n IPerformanceClient,\n PerformanceEvents,\n IdTokenEntity,\n AccessTokenEntity,\n AuthError,\n CommonSilentFlowRequest,\n AccountInfo,\n AADServerParamKeys,\n TokenClaims,\n createClientAuthError,\n ClientAuthErrorCodes,\n invokeAsync,\n updateAccountTenantProfileData,\n CacheHelpers,\n buildAccountToCache,\n InProgressPerformanceEvent,\n ServerTelemetryManager,\n} from \"@azure/msal-common/browser\";\nimport { BaseInteractionClient } from \"./BaseInteractionClient.js\";\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\nimport { EventHandler } from \"../event/EventHandler.js\";\nimport { PopupRequest } from \"../request/PopupRequest.js\";\nimport { SilentRequest } from \"../request/SilentRequest.js\";\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\nimport {\n ApiId,\n TemporaryCacheKeys,\n PlatformAuthConstants,\n BrowserConstants,\n CacheLookupPolicy,\n} from \"../utils/BrowserConstants.js\";\nimport { PlatformAuthRequest } from \"../broker/nativeBroker/PlatformAuthRequest.js\";\nimport {\n MATS,\n PlatformAuthResponse,\n} from \"../broker/nativeBroker/PlatformAuthResponse.js\";\nimport {\n NativeAuthError,\n NativeAuthErrorCodes,\n createNativeAuthError,\n isFatalNativeAuthError,\n} from \"../error/NativeAuthError.js\";\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\nimport { NavigationOptions } from \"../navigation/NavigationOptions.js\";\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport { SilentCacheClient } from \"./SilentCacheClient.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { base64Decode } from \"../encode/Base64Decode.js\";\nimport { version } from \"../packageMetadata.js\";\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\n\nexport class PlatformAuthInteractionClient extends BaseInteractionClient {\n protected apiId: ApiId;\n protected accountId: string;\n protected platformAuthProvider: IPlatformAuthHandler;\n protected silentCacheClient: SilentCacheClient;\n protected nativeStorageManager: BrowserCacheManager;\n protected skus: string;\n\n constructor(\n config: BrowserConfiguration,\n browserStorage: BrowserCacheManager,\n browserCrypto: ICrypto,\n logger: Logger,\n eventHandler: EventHandler,\n navigationClient: INavigationClient,\n apiId: ApiId,\n performanceClient: IPerformanceClient,\n provider: IPlatformAuthHandler,\n accountId: string,\n nativeStorageImpl: BrowserCacheManager,\n correlationId?: string\n ) {\n super(\n config,\n browserStorage,\n browserCrypto,\n logger,\n eventHandler,\n navigationClient,\n performanceClient,\n provider,\n correlationId\n );\n this.apiId = apiId;\n this.accountId = accountId;\n this.platformAuthProvider = provider;\n this.nativeStorageManager = nativeStorageImpl;\n this.silentCacheClient = new SilentCacheClient(\n config,\n this.nativeStorageManager,\n browserCrypto,\n logger,\n eventHandler,\n navigationClient,\n performanceClient,\n provider,\n correlationId\n );\n\n const extensionName = this.platformAuthProvider.getExtensionName();\n\n this.skus = ServerTelemetryManager.makeExtraSkuString({\n libraryName: BrowserConstants.MSAL_SKU,\n libraryVersion: version,\n extensionName: extensionName,\n extensionVersion: this.platformAuthProvider.getExtensionVersion(),\n });\n }\n\n /**\n * Adds SKUs to request extra query parameters\n * @param request {PlatformAuthRequest}\n * @private\n */\n private addRequestSKUs(request: PlatformAuthRequest): void {\n request.extraParameters = {\n ...request.extraParameters,\n [AADServerParamKeys.X_CLIENT_EXTRA_SKU]: this.skus,\n };\n }\n\n /**\n * Acquire token from native platform via browser extension\n * @param request\n */\n async acquireToken(\n request: PopupRequest | SilentRequest | SsoSilentRequest,\n cacheLookupPolicy?: CacheLookupPolicy\n ): Promise {\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.NativeInteractionClientAcquireToken,\n this.correlationId\n );\n this.logger.trace(\"NativeInteractionClient - acquireToken called.\");\n\n // start the perf measurement\n const nativeATMeasurement = this.performanceClient.startMeasurement(\n PerformanceEvents.NativeInteractionClientAcquireToken,\n this.correlationId\n );\n const reqTimestamp = TimeUtils.nowSeconds();\n\n const serverTelemetryManager = this.initializeServerTelemetryManager(\n this.apiId\n );\n\n try {\n // initialize native request\n const nativeRequest = await this.initializeNativeRequest(request);\n\n // check if the tokens can be retrieved from internal cache\n try {\n const result = await this.acquireTokensFromCache(\n this.accountId,\n nativeRequest\n );\n nativeATMeasurement.end({\n success: true,\n isNativeBroker: false, // Should be true only when the result is coming directly from the broker\n fromCache: true,\n });\n return result;\n } catch (e) {\n if (cacheLookupPolicy === CacheLookupPolicy.AccessToken) {\n this.logger.info(\n \"MSAL internal Cache does not contain tokens, return error as per cache policy\"\n );\n nativeATMeasurement.end({\n success: false,\n brokerErrorCode: \"cache_request_failed\",\n });\n throw e;\n }\n // continue with a native call for any and all errors\n this.logger.info(\n \"MSAL internal Cache does not contain tokens, proceed to make a native call\"\n );\n }\n\n const validatedResponse: PlatformAuthResponse =\n await this.platformAuthProvider.sendMessage(nativeRequest);\n\n return await this.handleNativeResponse(\n validatedResponse,\n nativeRequest,\n reqTimestamp\n )\n .then((result: AuthenticationResult) => {\n nativeATMeasurement.end({\n success: true,\n isNativeBroker: true,\n requestId: result.requestId,\n });\n serverTelemetryManager.clearNativeBrokerErrorCode();\n return result;\n })\n .catch((error: AuthError) => {\n nativeATMeasurement.end({\n success: false,\n errorCode: error.errorCode,\n subErrorCode: error.subError,\n });\n throw error;\n });\n } catch (e) {\n if (e instanceof NativeAuthError) {\n serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);\n }\n nativeATMeasurement.end({\n success: false,\n });\n throw e;\n }\n }\n\n /**\n * Creates silent flow request\n * @param request\n * @param cachedAccount\n * @returns CommonSilentFlowRequest\n */\n private createSilentCacheRequest(\n request: PlatformAuthRequest,\n cachedAccount: AccountInfo\n ): CommonSilentFlowRequest {\n return {\n authority: request.authority,\n correlationId: this.correlationId,\n scopes: ScopeSet.fromString(request.scope).asArray(),\n account: cachedAccount,\n forceRefresh: false,\n };\n }\n\n /**\n * Fetches the tokens from the cache if un-expired\n * @param nativeAccountId\n * @param request\n * @returns authenticationResult\n */\n protected async acquireTokensFromCache(\n nativeAccountId: string,\n request: PlatformAuthRequest\n ): Promise {\n if (!nativeAccountId) {\n this.logger.warning(\n \"NativeInteractionClient:acquireTokensFromCache - No nativeAccountId provided\"\n );\n throw createClientAuthError(ClientAuthErrorCodes.noAccountFound);\n }\n // fetch the account from browser cache\n const account = this.browserStorage.getBaseAccountInfo(\n {\n nativeAccountId,\n },\n this.correlationId\n );\n\n if (!account) {\n throw createClientAuthError(ClientAuthErrorCodes.noAccountFound);\n }\n\n // leverage silent flow for cached tokens retrieval\n try {\n const silentRequest = this.createSilentCacheRequest(\n request,\n account\n );\n const result = await this.silentCacheClient.acquireToken(\n silentRequest\n );\n\n const fullAccount = {\n ...account,\n idTokenClaims: result?.idTokenClaims as TokenClaims,\n idToken: result?.idToken,\n };\n\n return {\n ...result,\n account: fullAccount,\n };\n } catch (e) {\n throw e;\n }\n }\n\n /**\n * Acquires a token from native platform then redirects to the redirectUri instead of returning the response\n * @param {RedirectRequest} request\n * @param {InProgressPerformanceEvent} rootMeasurement\n */\n async acquireTokenRedirect(\n request: RedirectRequest,\n rootMeasurement: InProgressPerformanceEvent\n ): Promise {\n this.logger.trace(\n \"NativeInteractionClient - acquireTokenRedirect called.\"\n );\n\n const { ...remainingParameters } = request;\n delete remainingParameters.onRedirectNavigate;\n\n const nativeRequest = await this.initializeNativeRequest(\n remainingParameters\n );\n\n try {\n await this.platformAuthProvider.sendMessage(nativeRequest);\n } catch (e) {\n // Only throw fatal errors here to allow application to fallback to regular redirect. Otherwise proceed and the error will be thrown in handleRedirectPromise\n if (e instanceof NativeAuthError) {\n const serverTelemetryManager =\n this.initializeServerTelemetryManager(this.apiId);\n serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);\n if (isFatalNativeAuthError(e)) {\n throw e;\n }\n }\n }\n this.browserStorage.setTemporaryCache(\n TemporaryCacheKeys.NATIVE_REQUEST,\n JSON.stringify(nativeRequest),\n true\n );\n\n const navigationOptions: NavigationOptions = {\n apiId: ApiId.acquireTokenRedirect,\n timeout: this.config.system.redirectNavigationTimeout,\n noHistory: false,\n };\n const redirectUri = this.config.auth.navigateToLoginRequestUrl\n ? window.location.href\n : this.getRedirectUri(request.redirectUri);\n rootMeasurement.end({ success: true });\n await this.navigationClient.navigateExternal(\n redirectUri,\n navigationOptions\n ); // Need to treat this as external to ensure handleRedirectPromise is run again\n }\n\n /**\n * If the previous page called native platform for a token using redirect APIs, send the same request again and return the response\n * @param performanceClient {IPerformanceClient?}\n * @param correlationId {string?} correlation identifier\n */\n async handleRedirectPromise(\n performanceClient?: IPerformanceClient,\n correlationId?: string\n ): Promise {\n this.logger.trace(\n \"NativeInteractionClient - handleRedirectPromise called.\"\n );\n if (!this.browserStorage.isInteractionInProgress(true)) {\n this.logger.info(\n \"handleRedirectPromise called but there is no interaction in progress, returning null.\"\n );\n return null;\n }\n\n // remove prompt from the request to prevent WAM from prompting twice\n const cachedRequest = this.browserStorage.getCachedNativeRequest();\n if (!cachedRequest) {\n this.logger.verbose(\n \"NativeInteractionClient - handleRedirectPromise called but there is no cached request, returning null.\"\n );\n if (performanceClient && correlationId) {\n performanceClient?.addFields(\n { errorCode: \"no_cached_request\" },\n correlationId\n );\n }\n return null;\n }\n\n const { prompt, ...request } = cachedRequest;\n if (prompt) {\n this.logger.verbose(\n \"NativeInteractionClient - handleRedirectPromise called and prompt was included in the original request, removing prompt from cached request to prevent second interaction with native broker window.\"\n );\n }\n\n this.browserStorage.removeItem(\n this.browserStorage.generateCacheKey(\n TemporaryCacheKeys.NATIVE_REQUEST\n )\n );\n\n const reqTimestamp = TimeUtils.nowSeconds();\n\n try {\n this.logger.verbose(\n \"NativeInteractionClient - handleRedirectPromise sending message to native broker.\"\n );\n const response: PlatformAuthResponse =\n await this.platformAuthProvider.sendMessage(request);\n const authResult = await this.handleNativeResponse(\n response,\n request,\n reqTimestamp\n );\n\n const serverTelemetryManager =\n this.initializeServerTelemetryManager(this.apiId);\n serverTelemetryManager.clearNativeBrokerErrorCode();\n if (performanceClient && this.correlationId) {\n this.performanceClient.addFields(\n { isNativeBroker: true },\n this.correlationId\n );\n }\n return authResult;\n } catch (e) {\n throw e;\n }\n }\n\n /**\n * Logout from native platform via browser extension\n * @param request\n */\n logout(): Promise {\n this.logger.trace(\"NativeInteractionClient - logout called.\");\n return Promise.reject(\"Logout not implemented yet\");\n }\n\n /**\n * Transform response from native platform into AuthenticationResult object which will be returned to the end user\n * @param response\n * @param request\n * @param reqTimestamp\n */\n protected async handleNativeResponse(\n response: PlatformAuthResponse,\n request: PlatformAuthRequest,\n reqTimestamp: number\n ): Promise {\n this.logger.trace(\n \"NativeInteractionClient - handleNativeResponse called.\"\n );\n\n // generate identifiers\n const idTokenClaims = AuthToken.extractTokenClaims(\n response.id_token,\n base64Decode\n );\n\n const homeAccountIdentifier = this.createHomeAccountIdentifier(\n response,\n idTokenClaims\n );\n\n const cachedhomeAccountId =\n this.browserStorage.getAccountInfoFilteredBy(\n {\n nativeAccountId: request.accountId,\n },\n this.correlationId\n )?.homeAccountId;\n\n // add exception for double brokering, please note this is temporary and will be fortified in future\n if (\n request.extraParameters?.child_client_id &&\n response.account.id !== request.accountId\n ) {\n this.logger.info(\n \"handleNativeServerResponse: Double broker flow detected, ignoring accountId mismatch\"\n );\n } else if (\n homeAccountIdentifier !== cachedhomeAccountId &&\n response.account.id !== request.accountId\n ) {\n // User switch in native broker prompt is not supported. All users must first sign in through web flow to ensure server state is in sync\n throw createNativeAuthError(NativeAuthErrorCodes.userSwitch);\n }\n\n // Get the preferred_cache domain for the given authority\n const authority = await this.getDiscoveredAuthority({\n requestAuthority: request.authority,\n });\n\n const baseAccount = buildAccountToCache(\n this.browserStorage,\n authority,\n homeAccountIdentifier,\n base64Decode,\n this.correlationId,\n idTokenClaims,\n response.client_info,\n undefined, // environment\n idTokenClaims.tid,\n undefined, // auth code payload\n response.account.id,\n this.logger\n );\n\n // Ensure expires_in is in number format\n response.expires_in = Number(response.expires_in);\n\n // generate authenticationResult\n const result = await this.generateAuthenticationResult(\n response,\n request,\n idTokenClaims,\n baseAccount,\n authority.canonicalAuthority,\n reqTimestamp\n );\n\n // cache accounts and tokens in the appropriate storage\n await this.cacheAccount(baseAccount, this.correlationId);\n await this.cacheNativeTokens(\n response,\n request,\n homeAccountIdentifier,\n idTokenClaims,\n response.access_token,\n result.tenantId,\n reqTimestamp\n );\n\n return result;\n }\n\n /**\n * creates an homeAccountIdentifier for the account\n * @param response\n * @param idTokenObj\n * @returns\n */\n protected createHomeAccountIdentifier(\n response: PlatformAuthResponse,\n idTokenClaims: TokenClaims\n ): string {\n // Save account in browser storage\n const homeAccountIdentifier = AccountEntity.generateHomeAccountId(\n response.client_info || Constants.EMPTY_STRING,\n AuthorityType.Default,\n this.logger,\n this.browserCrypto,\n idTokenClaims\n );\n\n return homeAccountIdentifier;\n }\n\n /**\n * Helper to generate scopes\n * @param response\n * @param request\n * @returns\n */\n generateScopes(requestScopes: string, responseScopes?: string): ScopeSet {\n return responseScopes\n ? ScopeSet.fromString(responseScopes)\n : ScopeSet.fromString(requestScopes);\n }\n\n /**\n * If PoP token is requesred, records the PoP token if returned from the WAM, else generates one in the browser\n * @param request\n * @param response\n */\n async generatePopAccessToken(\n response: PlatformAuthResponse,\n request: PlatformAuthRequest\n ): Promise {\n if (\n request.tokenType === AuthenticationScheme.POP &&\n request.signPopToken\n ) {\n /**\n * This code prioritizes SHR returned from the native layer. In case of error/SHR not calculated from WAM and the AT\n * is still received, SHR is calculated locally\n */\n\n // Check if native layer returned an SHR token\n if (response.shr) {\n this.logger.trace(\n \"handleNativeServerResponse: SHR is enabled in native layer\"\n );\n return response.shr;\n }\n\n // Generate SHR in msal js if WAM does not compute it when POP is enabled\n const popTokenGenerator: PopTokenGenerator = new PopTokenGenerator(\n this.browserCrypto\n );\n const shrParameters: SignedHttpRequestParameters = {\n resourceRequestMethod: request.resourceRequestMethod,\n resourceRequestUri: request.resourceRequestUri,\n shrClaims: request.shrClaims,\n shrNonce: request.shrNonce,\n };\n\n /**\n * KeyID must be present in the native request from when the PoP key was generated in order for\n * PopTokenGenerator to query the full key for signing\n */\n if (!request.keyId) {\n throw createClientAuthError(ClientAuthErrorCodes.keyIdMissing);\n }\n return popTokenGenerator.signPopToken(\n response.access_token,\n request.keyId,\n shrParameters\n );\n } else {\n return response.access_token;\n }\n }\n\n /**\n * Generates authentication result\n * @param response\n * @param request\n * @param idTokenObj\n * @param accountEntity\n * @param authority\n * @param reqTimestamp\n * @returns\n */\n protected async generateAuthenticationResult(\n response: PlatformAuthResponse,\n request: PlatformAuthRequest,\n idTokenClaims: TokenClaims,\n accountEntity: AccountEntity,\n authority: string,\n reqTimestamp: number\n ): Promise {\n // Add Native Broker fields to Telemetry\n const mats = this.addTelemetryFromNativeResponse(\n response.properties.MATS\n );\n\n // If scopes not returned in server response, use request scopes\n const responseScopes = this.generateScopes(\n request.scope,\n response.scope\n );\n\n const accountProperties = response.account.properties || {};\n const uid =\n accountProperties[\"UID\"] ||\n idTokenClaims.oid ||\n idTokenClaims.sub ||\n Constants.EMPTY_STRING;\n const tid =\n accountProperties[\"TenantId\"] ||\n idTokenClaims.tid ||\n Constants.EMPTY_STRING;\n\n const accountInfo: AccountInfo | null = updateAccountTenantProfileData(\n accountEntity.getAccountInfo(),\n undefined, // tenantProfile optional\n idTokenClaims,\n response.id_token\n );\n\n /**\n * In pairwise broker flows, this check prevents the broker's native account id\n * from being returned over the embedded app's account id.\n */\n if (accountInfo.nativeAccountId !== response.account.id) {\n accountInfo.nativeAccountId = response.account.id;\n }\n\n // generate PoP token as needed\n const responseAccessToken = await this.generatePopAccessToken(\n response,\n request\n );\n const tokenType =\n request.tokenType === AuthenticationScheme.POP\n ? AuthenticationScheme.POP\n : AuthenticationScheme.BEARER;\n\n const result: AuthenticationResult = {\n authority: authority,\n uniqueId: uid,\n tenantId: tid,\n scopes: responseScopes.asArray(),\n account: accountInfo,\n idToken: response.id_token,\n idTokenClaims: idTokenClaims,\n accessToken: responseAccessToken,\n fromCache: mats ? this.isResponseFromCache(mats) : false,\n // Request timestamp and NativeResponse expires_in are in seconds, converting to Date for AuthenticationResult\n expiresOn: TimeUtils.toDateFromSeconds(\n reqTimestamp + response.expires_in\n ),\n tokenType: tokenType,\n correlationId: this.correlationId,\n state: response.state,\n fromNativeBroker: true,\n };\n\n return result;\n }\n\n /**\n * cache the account entity in browser storage\n * @param accountEntity\n */\n async cacheAccount(\n accountEntity: AccountEntity,\n correlationId: string\n ): Promise {\n // Store the account info and hence `nativeAccountId` in browser cache\n await this.browserStorage.setAccount(accountEntity, this.correlationId);\n // Remove any existing cached tokens for this account in browser storage\n this.browserStorage.removeAccountContext(\n accountEntity.getAccountInfo(),\n correlationId\n );\n }\n\n /**\n * Stores the access_token and id_token in inmemory storage\n * @param response\n * @param request\n * @param homeAccountIdentifier\n * @param idTokenObj\n * @param responseAccessToken\n * @param tenantId\n * @param reqTimestamp\n */\n cacheNativeTokens(\n response: PlatformAuthResponse,\n request: PlatformAuthRequest,\n homeAccountIdentifier: string,\n idTokenClaims: TokenClaims,\n responseAccessToken: string,\n tenantId: string,\n reqTimestamp: number\n ): Promise {\n const cachedIdToken: IdTokenEntity | null =\n CacheHelpers.createIdTokenEntity(\n homeAccountIdentifier,\n request.authority,\n response.id_token || \"\",\n request.clientId,\n idTokenClaims.tid || \"\"\n );\n\n // cache accessToken in inmemory storage\n const expiresIn: number =\n request.tokenType === AuthenticationScheme.POP\n ? Constants.SHR_NONCE_VALIDITY\n : (typeof response.expires_in === \"string\"\n ? parseInt(response.expires_in, 10)\n : response.expires_in) || 0;\n const tokenExpirationSeconds = reqTimestamp + expiresIn;\n const responseScopes = this.generateScopes(\n response.scope,\n request.scope\n );\n\n const cachedAccessToken: AccessTokenEntity | null =\n CacheHelpers.createAccessTokenEntity(\n homeAccountIdentifier,\n request.authority,\n responseAccessToken,\n request.clientId,\n idTokenClaims.tid || tenantId,\n responseScopes.printScopes(),\n tokenExpirationSeconds,\n 0,\n base64Decode,\n undefined,\n request.tokenType as AuthenticationScheme,\n undefined,\n request.keyId\n );\n\n const nativeCacheRecord = {\n idToken: cachedIdToken,\n accessToken: cachedAccessToken,\n };\n\n return this.nativeStorageManager.saveCacheRecord(\n nativeCacheRecord,\n this.correlationId,\n request.storeInCache\n );\n }\n\n getExpiresInValue(\n tokenType: string,\n expiresIn: string | number | undefined\n ): number {\n return tokenType === AuthenticationScheme.POP\n ? Constants.SHR_NONCE_VALIDITY\n : (typeof expiresIn === \"string\"\n ? parseInt(expiresIn, 10)\n : expiresIn) || 0;\n }\n\n protected addTelemetryFromNativeResponse(\n matsResponse?: string\n ): MATS | null {\n const mats = this.getMATSFromResponse(matsResponse);\n\n if (!mats) {\n return null;\n }\n\n this.performanceClient.addFields(\n {\n extensionId: this.platformAuthProvider.getExtensionId(),\n extensionVersion:\n this.platformAuthProvider.getExtensionVersion(),\n matsBrokerVersion: mats.broker_version,\n matsAccountJoinOnStart: mats.account_join_on_start,\n matsAccountJoinOnEnd: mats.account_join_on_end,\n matsDeviceJoin: mats.device_join,\n matsPromptBehavior: mats.prompt_behavior,\n matsApiErrorCode: mats.api_error_code,\n matsUiVisible: mats.ui_visible,\n matsSilentCode: mats.silent_code,\n matsSilentBiSubCode: mats.silent_bi_sub_code,\n matsSilentMessage: mats.silent_message,\n matsSilentStatus: mats.silent_status,\n matsHttpStatus: mats.http_status,\n matsHttpEventCount: mats.http_event_count,\n },\n this.correlationId\n );\n\n return mats;\n }\n\n /**\n * Gets MATS telemetry from native response\n * @param response\n * @returns\n */\n private getMATSFromResponse(matsResponse: string | undefined): MATS | null {\n if (matsResponse) {\n try {\n return JSON.parse(matsResponse);\n } catch (e) {\n this.logger.error(\n \"NativeInteractionClient - Error parsing MATS telemetry, returning null instead\"\n );\n }\n }\n\n return null;\n }\n\n /**\n * Returns whether or not response came from native cache\n * @param response\n * @returns\n */\n protected isResponseFromCache(mats: MATS): boolean {\n if (typeof mats.is_cached === \"undefined\") {\n this.logger.verbose(\n \"NativeInteractionClient - MATS telemetry does not contain field indicating if response was served from cache. Returning false.\"\n );\n return false;\n }\n\n return !!mats.is_cached;\n }\n\n /**\n * Translates developer provided request object into NativeRequest object\n * @param request\n */\n protected async initializeNativeRequest(\n request: PopupRequest | SsoSilentRequest\n ): Promise {\n this.logger.trace(\n \"NativeInteractionClient - initializeNativeRequest called\"\n );\n\n const canonicalAuthority = await this.getCanonicalAuthority(request);\n\n // scopes are expected to be received by the native broker as \"scope\" and will be added to the request below. Other properties that should be dropped from the request to the native broker can be included in the object destructuring here.\n const { scopes, ...remainingProperties } = request;\n const scopeSet = new ScopeSet(scopes || []);\n scopeSet.appendScopes(OIDC_DEFAULT_SCOPES);\n\n const validatedRequest: PlatformAuthRequest = {\n ...remainingProperties,\n accountId: this.accountId,\n clientId: this.config.auth.clientId,\n authority: canonicalAuthority.urlString,\n scope: scopeSet.printScopes(),\n redirectUri: this.getRedirectUri(request.redirectUri),\n prompt: this.getPrompt(request.prompt),\n correlationId: this.correlationId,\n tokenType: request.authenticationScheme,\n windowTitleSubstring: document.title,\n extraParameters: {\n ...request.extraQueryParameters,\n ...request.tokenQueryParameters,\n },\n extendedExpiryToken: false, // Make this configurable?\n keyId: request.popKid,\n };\n\n // Check for PoP token requests: signPopToken should only be set to true if popKid is not set\n if (validatedRequest.signPopToken && !!request.popKid) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.invalidPopTokenRequest\n );\n }\n\n this.handleExtraBrokerParams(validatedRequest);\n validatedRequest.extraParameters =\n validatedRequest.extraParameters || {};\n validatedRequest.extraParameters.telemetry =\n PlatformAuthConstants.MATS_TELEMETRY;\n\n if (request.authenticationScheme === AuthenticationScheme.POP) {\n // add POP request type\n const shrParameters: SignedHttpRequestParameters = {\n resourceRequestUri: request.resourceRequestUri,\n resourceRequestMethod: request.resourceRequestMethod,\n shrClaims: request.shrClaims,\n shrNonce: request.shrNonce,\n };\n\n const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);\n\n // generate reqCnf if not provided in the request\n let reqCnfData;\n if (!validatedRequest.keyId) {\n const generatedReqCnfData = await invokeAsync(\n popTokenGenerator.generateCnf.bind(popTokenGenerator),\n PerformanceEvents.PopTokenGenerateCnf,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(shrParameters, this.logger);\n reqCnfData = generatedReqCnfData.reqCnfString;\n validatedRequest.keyId = generatedReqCnfData.kid;\n validatedRequest.signPopToken = true;\n } else {\n reqCnfData = this.browserCrypto.base64UrlEncode(\n JSON.stringify({ kid: validatedRequest.keyId })\n );\n validatedRequest.signPopToken = false;\n }\n\n // SPAs require whole string to be passed to broker\n validatedRequest.reqCnf = reqCnfData;\n }\n this.addRequestSKUs(validatedRequest);\n\n return validatedRequest;\n }\n\n private async getCanonicalAuthority(\n request: PopupRequest | SsoSilentRequest\n ): Promise {\n const requestAuthority =\n request.authority || this.config.auth.authority;\n\n if (request.account) {\n // validate authority\n await this.getDiscoveredAuthority({\n requestAuthority,\n requestAzureCloudOptions: request.azureCloudOptions,\n account: request.account,\n });\n }\n\n const canonicalAuthority = new UrlString(requestAuthority);\n canonicalAuthority.validateAsUri();\n return canonicalAuthority;\n }\n\n private getPrompt(prompt?: string): string | undefined {\n // If request is silent, prompt is always none\n switch (this.apiId) {\n case ApiId.ssoSilent:\n case ApiId.acquireTokenSilent_silentFlow:\n this.logger.trace(\n \"initializeNativeRequest: silent request sets prompt to none\"\n );\n return PromptValue.NONE;\n default:\n break;\n }\n\n // Prompt not provided, request may proceed and native broker decides if it needs to prompt\n if (!prompt) {\n this.logger.trace(\n \"initializeNativeRequest: prompt was not provided\"\n );\n return undefined;\n }\n\n // If request is interactive, check if prompt provided is allowed to go directly to native broker\n switch (prompt) {\n case PromptValue.NONE:\n case PromptValue.CONSENT:\n case PromptValue.LOGIN:\n this.logger.trace(\n \"initializeNativeRequest: prompt is compatible with native flow\"\n );\n return prompt;\n default:\n this.logger.trace(\n `initializeNativeRequest: prompt = ${prompt} is not compatible with native flow`\n );\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.nativePromptNotSupported\n );\n }\n }\n\n /**\n * Handles extra broker request parameters\n * @param request {PlatformAuthRequest}\n * @private\n */\n private handleExtraBrokerParams(request: PlatformAuthRequest): void {\n const hasExtraBrokerParams =\n request.extraParameters &&\n request.extraParameters.hasOwnProperty(\n AADServerParamKeys.BROKER_CLIENT_ID\n ) &&\n request.extraParameters.hasOwnProperty(\n AADServerParamKeys.BROKER_REDIRECT_URI\n ) &&\n request.extraParameters.hasOwnProperty(\n AADServerParamKeys.CLIENT_ID\n );\n\n if (!request.embeddedClientId && !hasExtraBrokerParams) {\n return;\n }\n\n let child_client_id: string = \"\";\n const child_redirect_uri = request.redirectUri;\n\n if (request.embeddedClientId) {\n request.redirectUri = this.config.auth.redirectUri;\n child_client_id = request.embeddedClientId;\n } else if (request.extraParameters) {\n request.redirectUri =\n request.extraParameters[AADServerParamKeys.BROKER_REDIRECT_URI];\n child_client_id =\n request.extraParameters[AADServerParamKeys.CLIENT_ID];\n }\n\n request.extraParameters = {\n child_client_id,\n child_redirect_uri,\n };\n\n this.performanceClient?.addFields(\n {\n embeddedClientId: child_client_id,\n embeddedRedirectUri: child_redirect_uri,\n },\n this.correlationId\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n AuthenticationScheme,\n Authority,\n AuthorizeProtocol,\n ClientConfigurationErrorCodes,\n CommonAuthorizationUrlRequest,\n createClientConfigurationError,\n invokeAsync,\n IPerformanceClient,\n Logger,\n PerformanceEvents,\n PopTokenGenerator,\n ProtocolMode,\n RequestParameterBuilder,\n OAuthResponseType,\n Constants,\n CommonAuthorizationCodeRequest,\n AuthorizationCodeClient,\n ProtocolUtils,\n ThrottlingUtils,\n AuthorizeResponse,\n ResponseHandler,\n TimeUtils,\n AuthorizationCodePayload,\n ServerAuthorizationTokenResponse,\n} from \"@azure/msal-common/browser\";\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\nimport { ApiId, BrowserConstants } from \"../utils/BrowserConstants.js\";\nimport { version } from \"../packageMetadata.js\";\nimport { CryptoOps } from \"../crypto/CryptoOps.js\";\nimport {\n BrowserAuthErrorCodes,\n createBrowserAuthError,\n} from \"../error/BrowserAuthError.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { InteractionHandler } from \"../interaction_handler/InteractionHandler.js\";\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\nimport { PlatformAuthInteractionClient } from \"../interaction_client/PlatformAuthInteractionClient.js\";\nimport { EventHandler } from \"../event/EventHandler.js\";\nimport { decryptEarResponse } from \"../crypto/BrowserCrypto.js\";\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\n\n/**\n * Returns map of parameters that are applicable to all calls to /authorize whether using PKCE or EAR\n * @param config\n * @param authority\n * @param request\n * @param logger\n * @param performanceClient\n * @returns\n */\nasync function getStandardParameters(\n config: BrowserConfiguration,\n authority: Authority,\n request: CommonAuthorizationUrlRequest,\n logger: Logger,\n performanceClient: IPerformanceClient\n): Promise> {\n const parameters = AuthorizeProtocol.getStandardAuthorizeRequestParameters(\n { ...config.auth, authority: authority },\n request,\n logger,\n performanceClient\n );\n RequestParameterBuilder.addLibraryInfo(parameters, {\n sku: BrowserConstants.MSAL_SKU,\n version: version,\n os: \"\",\n cpu: \"\",\n });\n if (config.auth.protocolMode !== ProtocolMode.OIDC) {\n RequestParameterBuilder.addApplicationTelemetry(\n parameters,\n config.telemetry.application\n );\n }\n\n if (request.platformBroker) {\n // signal ests that this is a WAM call\n RequestParameterBuilder.addNativeBroker(parameters);\n\n // instrument JS-platform bridge specific fields\n performanceClient.addFields(\n {\n isPlatformAuthorizeRequest: true,\n },\n request.correlationId\n );\n\n // pass the req_cnf for POP\n if (request.authenticationScheme === AuthenticationScheme.POP) {\n const cryptoOps = new CryptoOps(logger, performanceClient);\n const popTokenGenerator = new PopTokenGenerator(cryptoOps);\n\n // req_cnf is always sent as a string for SPAs\n let reqCnfData;\n if (!request.popKid) {\n const generatedReqCnfData = await invokeAsync(\n popTokenGenerator.generateCnf.bind(popTokenGenerator),\n PerformanceEvents.PopTokenGenerateCnf,\n logger,\n performanceClient,\n request.correlationId\n )(request, logger);\n reqCnfData = generatedReqCnfData.reqCnfString;\n } else {\n reqCnfData = cryptoOps.encodeKid(request.popKid);\n }\n RequestParameterBuilder.addPopToken(parameters, reqCnfData);\n }\n }\n\n RequestParameterBuilder.instrumentBrokerParams(\n parameters,\n request.correlationId,\n performanceClient\n );\n\n return parameters;\n}\n\n/**\n * Gets the full /authorize URL with request parameters when using Auth Code + PKCE\n * @param config\n * @param authority\n * @param request\n * @param logger\n * @param performanceClient\n * @returns\n */\nexport async function getAuthCodeRequestUrl(\n config: BrowserConfiguration,\n authority: Authority,\n request: CommonAuthorizationUrlRequest,\n logger: Logger,\n performanceClient: IPerformanceClient\n): Promise {\n if (!request.codeChallenge) {\n throw createClientConfigurationError(\n ClientConfigurationErrorCodes.pkceParamsMissing\n );\n }\n\n const parameters = await invokeAsync(\n getStandardParameters,\n PerformanceEvents.GetStandardParams,\n logger,\n performanceClient,\n request.correlationId\n )(config, authority, request, logger, performanceClient);\n RequestParameterBuilder.addResponseType(parameters, OAuthResponseType.CODE);\n\n RequestParameterBuilder.addCodeChallengeParams(\n parameters,\n request.codeChallenge,\n Constants.S256_CODE_CHALLENGE_METHOD\n );\n\n RequestParameterBuilder.addExtraQueryParameters(\n parameters,\n request.extraQueryParameters || {}\n );\n\n return AuthorizeProtocol.getAuthorizeUrl(\n authority,\n parameters,\n config.auth.encodeExtraQueryParams,\n request.extraQueryParameters\n );\n}\n\n/**\n * Gets the form that will be posted to /authorize with request parameters when using EAR\n */\nexport async function getEARForm(\n frame: Document,\n config: BrowserConfiguration,\n authority: Authority,\n request: CommonAuthorizationUrlRequest,\n logger: Logger,\n performanceClient: IPerformanceClient\n): Promise {\n if (!request.earJwk) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.earJwkEmpty);\n }\n\n const parameters = await getStandardParameters(\n config,\n authority,\n request,\n logger,\n performanceClient\n );\n\n RequestParameterBuilder.addResponseType(\n parameters,\n OAuthResponseType.IDTOKEN_TOKEN_REFRESHTOKEN\n );\n RequestParameterBuilder.addEARParameters(parameters, request.earJwk);\n\n const queryParams = new Map();\n RequestParameterBuilder.addExtraQueryParameters(\n queryParams,\n request.extraQueryParameters || {}\n );\n const url = AuthorizeProtocol.getAuthorizeUrl(\n authority,\n queryParams,\n config.auth.encodeExtraQueryParams,\n request.extraQueryParameters\n );\n\n return createForm(frame, url, parameters);\n}\n\n/**\n * Gets the form that will be posted to /authorize with request parameters when using POST method\n */\nexport async function getCodeForm(\n frame: Document,\n config: BrowserConfiguration,\n authority: Authority,\n request: CommonAuthorizationUrlRequest,\n logger: Logger,\n performanceClient: IPerformanceClient\n): Promise {\n const parameters = await getStandardParameters(\n config,\n authority,\n request,\n logger,\n performanceClient\n );\n\n RequestParameterBuilder.addResponseType(parameters, OAuthResponseType.CODE);\n\n RequestParameterBuilder.addCodeChallengeParams(\n parameters,\n request.codeChallenge,\n request.codeChallengeMethod || Constants.S256_CODE_CHALLENGE_METHOD\n );\n\n RequestParameterBuilder.addPostBodyParameters(\n parameters,\n request.authorizePostBodyParameters || {}\n );\n\n const queryParams = new Map();\n RequestParameterBuilder.addExtraQueryParameters(\n queryParams,\n request.extraQueryParameters || {}\n );\n\n const url = AuthorizeProtocol.getAuthorizeUrl(\n authority,\n queryParams,\n config.auth.encodeExtraQueryParams,\n request.extraQueryParameters\n );\n\n return createForm(frame, url, parameters);\n}\n\n/**\n * Creates form element in the provided document with auth parameters in the post body\n * @param frame\n * @param authorizeUrl\n * @param parameters\n * @returns\n */\nfunction createForm(\n frame: Document,\n authorizeUrl: string,\n parameters: Map\n): HTMLFormElement {\n const form = frame.createElement(\"form\");\n form.method = \"post\";\n form.action = authorizeUrl;\n\n parameters.forEach((value: string, key: string) => {\n const param = frame.createElement(\"input\");\n param.hidden = true;\n param.name = key;\n param.value = value;\n\n form.appendChild(param);\n });\n\n frame.body.appendChild(form);\n return form;\n}\n\n/**\n * Response handler when server returns accountId on the /authorize request\n * @param request\n * @param accountId\n * @param apiId\n * @param config\n * @param browserStorage\n * @param nativeStorage\n * @param eventHandler\n * @param logger\n * @param performanceClient\n * @param nativeMessageHandler\n * @returns\n */\nexport async function handleResponsePlatformBroker(\n request: CommonAuthorizationUrlRequest,\n accountId: string,\n apiId: ApiId,\n config: BrowserConfiguration,\n browserStorage: BrowserCacheManager,\n nativeStorage: BrowserCacheManager,\n eventHandler: EventHandler,\n logger: Logger,\n performanceClient: IPerformanceClient,\n platformAuthProvider?: IPlatformAuthHandler\n): Promise {\n logger.verbose(\"Account id found, calling WAM for token\");\n\n if (!platformAuthProvider) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.nativeConnectionNotEstablished\n );\n }\n const browserCrypto = new CryptoOps(logger, performanceClient);\n const nativeInteractionClient = new PlatformAuthInteractionClient(\n config,\n browserStorage,\n browserCrypto,\n logger,\n eventHandler,\n config.system.navigationClient,\n apiId,\n performanceClient,\n platformAuthProvider,\n accountId,\n nativeStorage,\n request.correlationId\n );\n const { userRequestState } = ProtocolUtils.parseRequestState(\n browserCrypto,\n request.state\n );\n return invokeAsync(\n nativeInteractionClient.acquireToken.bind(nativeInteractionClient),\n PerformanceEvents.NativeInteractionClientAcquireToken,\n logger,\n performanceClient,\n request.correlationId\n )({\n ...request,\n state: userRequestState,\n prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently\n });\n}\n\n/**\n * Response handler when server returns code on the /authorize request\n * @param request\n * @param response\n * @param codeVerifier\n * @param authClient\n * @param browserStorage\n * @param logger\n * @param performanceClient\n * @returns\n */\nexport async function handleResponseCode(\n request: CommonAuthorizationUrlRequest,\n response: AuthorizeResponse,\n codeVerifier: string,\n apiId: ApiId,\n config: BrowserConfiguration,\n authClient: AuthorizationCodeClient,\n browserStorage: BrowserCacheManager,\n nativeStorage: BrowserCacheManager,\n eventHandler: EventHandler,\n logger: Logger,\n performanceClient: IPerformanceClient,\n platformAuthProvider?: IPlatformAuthHandler\n): Promise {\n // Remove throttle if it exists\n ThrottlingUtils.removeThrottle(\n browserStorage,\n config.auth.clientId,\n request\n );\n if (response.accountId) {\n return invokeAsync(\n handleResponsePlatformBroker,\n PerformanceEvents.HandleResponsePlatformBroker,\n logger,\n performanceClient,\n request.correlationId\n )(\n request,\n response.accountId,\n apiId,\n config,\n browserStorage,\n nativeStorage,\n eventHandler,\n logger,\n performanceClient,\n platformAuthProvider\n );\n }\n const authCodeRequest: CommonAuthorizationCodeRequest = {\n ...request,\n code: response.code || \"\",\n codeVerifier: codeVerifier,\n };\n // Create popup interaction handler.\n const interactionHandler = new InteractionHandler(\n authClient,\n browserStorage,\n authCodeRequest,\n logger,\n performanceClient\n );\n // Handle response from hash string.\n const result = await invokeAsync(\n interactionHandler.handleCodeResponse.bind(interactionHandler),\n PerformanceEvents.HandleCodeResponse,\n logger,\n performanceClient,\n request.correlationId\n )(response, request);\n\n return result;\n}\n\n/**\n * Response handler when server returns ear_jwe on the /authorize request\n * @param request\n * @param response\n * @param apiId\n * @param config\n * @param authority\n * @param browserStorage\n * @param nativeStorage\n * @param eventHandler\n * @param logger\n * @param performanceClient\n * @param nativeMessageHandler\n * @returns\n */\nexport async function handleResponseEAR(\n request: CommonAuthorizationUrlRequest,\n response: AuthorizeResponse,\n apiId: ApiId,\n config: BrowserConfiguration,\n authority: Authority,\n browserStorage: BrowserCacheManager,\n nativeStorage: BrowserCacheManager,\n eventHandler: EventHandler,\n logger: Logger,\n performanceClient: IPerformanceClient,\n platformAuthProvider?: IPlatformAuthHandler\n): Promise {\n // Remove throttle if it exists\n ThrottlingUtils.removeThrottle(\n browserStorage,\n config.auth.clientId,\n request\n );\n\n // Validate state & check response for errors\n AuthorizeProtocol.validateAuthorizationResponse(response, request.state);\n\n if (!response.ear_jwe) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.earJweEmpty);\n }\n\n if (!request.earJwk) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.earJwkEmpty);\n }\n\n const decryptedData = JSON.parse(\n await invokeAsync(\n decryptEarResponse,\n PerformanceEvents.DecryptEarResponse,\n logger,\n performanceClient,\n request.correlationId\n )(request.earJwk, response.ear_jwe)\n ) as AuthorizeResponse & ServerAuthorizationTokenResponse;\n\n if (decryptedData.accountId) {\n return invokeAsync(\n handleResponsePlatformBroker,\n PerformanceEvents.HandleResponsePlatformBroker,\n logger,\n performanceClient,\n request.correlationId\n )(\n request,\n decryptedData.accountId,\n apiId,\n config,\n browserStorage,\n nativeStorage,\n eventHandler,\n logger,\n performanceClient,\n platformAuthProvider\n );\n }\n\n const responseHandler = new ResponseHandler(\n config.auth.clientId,\n browserStorage,\n new CryptoOps(logger, performanceClient),\n logger,\n null,\n null,\n performanceClient\n );\n\n // Validate response. This function throws a server error if an error is returned by the server.\n responseHandler.validateTokenResponse(decryptedData);\n\n // Temporary until response handler is refactored to be more flow agnostic.\n const additionalData: AuthorizationCodePayload = {\n code: \"\",\n state: request.state,\n nonce: request.nonce,\n client_info: decryptedData.client_info,\n cloud_graph_host_name: decryptedData.cloud_graph_host_name,\n cloud_instance_host_name: decryptedData.cloud_instance_host_name,\n cloud_instance_name: decryptedData.cloud_instance_name,\n msgraph_host: decryptedData.msgraph_host,\n };\n\n return (await invokeAsync(\n responseHandler.handleServerTokenResponse.bind(responseHandler),\n PerformanceEvents.HandleServerTokenResponse,\n logger,\n performanceClient,\n request.correlationId\n )(\n decryptedData,\n authority,\n TimeUtils.nowSeconds(),\n request,\n additionalData,\n undefined,\n undefined,\n undefined,\n undefined\n )) as AuthenticationResult;\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n IPerformanceClient,\n Logger,\n PerformanceEvents,\n PkceCodes,\n invoke,\n invokeAsync,\n} from \"@azure/msal-common/browser\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport { urlEncodeArr } from \"../encode/Base64Encode.js\";\nimport { getRandomValues, sha256Digest } from \"./BrowserCrypto.js\";\n\n// Constant byte array length\nconst RANDOM_BYTE_ARR_LENGTH = 32;\n\n/**\n * This file defines APIs to generate PKCE codes and code verifiers.\n */\n\n/**\n * Generates PKCE Codes. See the RFC for more information: https://tools.ietf.org/html/rfc7636\n */\nexport async function generatePkceCodes(\n performanceClient: IPerformanceClient,\n logger: Logger,\n correlationId: string\n): Promise {\n performanceClient.addQueueMeasurement(\n PerformanceEvents.GeneratePkceCodes,\n correlationId\n );\n const codeVerifier = invoke(\n generateCodeVerifier,\n PerformanceEvents.GenerateCodeVerifier,\n logger,\n performanceClient,\n correlationId\n )(performanceClient, logger, correlationId);\n const codeChallenge = await invokeAsync(\n generateCodeChallengeFromVerifier,\n PerformanceEvents.GenerateCodeChallengeFromVerifier,\n logger,\n performanceClient,\n correlationId\n )(codeVerifier, performanceClient, logger, correlationId);\n return {\n verifier: codeVerifier,\n challenge: codeChallenge,\n };\n}\n\n/**\n * Generates a random 32 byte buffer and returns the base64\n * encoded string to be used as a PKCE Code Verifier\n */\nfunction generateCodeVerifier(\n performanceClient: IPerformanceClient,\n logger: Logger,\n correlationId: string\n): string {\n try {\n // Generate random values as utf-8\n const buffer: Uint8Array = new Uint8Array(RANDOM_BYTE_ARR_LENGTH);\n invoke(\n getRandomValues,\n PerformanceEvents.GetRandomValues,\n logger,\n performanceClient,\n correlationId\n )(buffer);\n // encode verifier as base64\n const pkceCodeVerifierB64: string = urlEncodeArr(buffer);\n return pkceCodeVerifierB64;\n } catch (e) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.pkceNotCreated);\n }\n}\n\n/**\n * Creates a base64 encoded PKCE Code Challenge string from the\n * hash created from the PKCE Code Verifier supplied\n */\nasync function generateCodeChallengeFromVerifier(\n pkceCodeVerifier: string,\n performanceClient: IPerformanceClient,\n logger: Logger,\n correlationId: string\n): Promise {\n performanceClient.addQueueMeasurement(\n PerformanceEvents.GenerateCodeChallengeFromVerifier,\n correlationId\n );\n try {\n // hashed verifier\n const pkceHashedCodeVerifier = await invokeAsync(\n sha256Digest,\n PerformanceEvents.Sha256Digest,\n logger,\n performanceClient,\n correlationId\n )(pkceCodeVerifier, performanceClient, correlationId);\n // encode hash as base64\n return urlEncodeArr(new Uint8Array(pkceHashedCodeVerifier));\n } catch (e) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.pkceNotCreated);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n PlatformAuthConstants,\n NativeExtensionMethod,\n} from \"../../utils/BrowserConstants.js\";\nimport {\n Logger,\n AuthError,\n createAuthError,\n AuthErrorCodes,\n InProgressPerformanceEvent,\n PerformanceEvents,\n IPerformanceClient,\n} from \"@azure/msal-common/browser\";\nimport {\n NativeExtensionRequest,\n NativeExtensionRequestBody,\n PlatformAuthRequest,\n} from \"./PlatformAuthRequest.js\";\nimport { createNativeAuthError } from \"../../error/NativeAuthError.js\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../../error/BrowserAuthError.js\";\nimport { createNewGuid } from \"../../crypto/BrowserCrypto.js\";\nimport { PlatformAuthResponse } from \"./PlatformAuthResponse.js\";\nimport { IPlatformAuthHandler } from \"./IPlatformAuthHandler.js\";\n\ntype ResponseResolvers = {\n resolve: (value: T | PromiseLike) => void;\n reject: (\n value: AuthError | Error | PromiseLike | PromiseLike\n ) => void;\n};\n\nexport class PlatformAuthExtensionHandler implements IPlatformAuthHandler {\n private extensionId: string | undefined;\n private extensionVersion: string | undefined;\n private logger: Logger;\n private readonly handshakeTimeoutMs: number;\n private timeoutId: number | undefined;\n private resolvers: Map>;\n private handshakeResolvers: Map>;\n private messageChannel: MessageChannel;\n private readonly windowListener: (event: MessageEvent) => void;\n private readonly performanceClient: IPerformanceClient;\n private readonly handshakeEvent: InProgressPerformanceEvent;\n platformAuthType: string;\n\n constructor(\n logger: Logger,\n handshakeTimeoutMs: number,\n performanceClient: IPerformanceClient,\n extensionId?: string\n ) {\n this.logger = logger;\n this.handshakeTimeoutMs = handshakeTimeoutMs;\n this.extensionId = extensionId;\n this.resolvers = new Map(); // Used for non-handshake messages\n this.handshakeResolvers = new Map(); // Used for handshake messages\n this.messageChannel = new MessageChannel();\n this.windowListener = this.onWindowMessage.bind(this); // Window event callback doesn't have access to 'this' unless it's bound\n this.performanceClient = performanceClient;\n this.handshakeEvent = performanceClient.startMeasurement(\n PerformanceEvents.NativeMessageHandlerHandshake\n );\n this.platformAuthType =\n PlatformAuthConstants.PLATFORM_EXTENSION_PROVIDER;\n }\n\n /**\n * Sends a given message to the extension and resolves with the extension response\n * @param request\n */\n async sendMessage(\n request: PlatformAuthRequest\n ): Promise {\n this.logger.trace(this.platformAuthType + \" - sendMessage called.\");\n\n // fall back to native calls\n const messageBody: NativeExtensionRequestBody = {\n method: NativeExtensionMethod.GetToken,\n request: request,\n };\n\n const req: NativeExtensionRequest = {\n channel: PlatformAuthConstants.CHANNEL_ID,\n extensionId: this.extensionId,\n responseId: createNewGuid(),\n body: messageBody,\n };\n\n this.logger.trace(\n this.platformAuthType + \" - Sending request to browser extension\"\n );\n this.logger.tracePii(\n this.platformAuthType +\n ` - Sending request to browser extension: ${JSON.stringify(\n req\n )}`\n );\n this.messageChannel.port1.postMessage(req);\n\n const response: object = await new Promise((resolve, reject) => {\n this.resolvers.set(req.responseId, { resolve, reject });\n });\n\n const validatedResponse: PlatformAuthResponse =\n this.validatePlatformBrokerResponse(response);\n\n return validatedResponse;\n }\n\n /**\n * Returns an instance of the MessageHandler that has successfully established a connection with an extension\n * @param {Logger} logger\n * @param {number} handshakeTimeoutMs\n * @param {IPerformanceClient} performanceClient\n * @param {ICrypto} crypto\n */\n static async createProvider(\n logger: Logger,\n handshakeTimeoutMs: number,\n performanceClient: IPerformanceClient\n ): Promise {\n logger.trace(\"PlatformAuthExtensionHandler - createProvider called.\");\n\n try {\n const preferredProvider = new PlatformAuthExtensionHandler(\n logger,\n handshakeTimeoutMs,\n performanceClient,\n PlatformAuthConstants.PREFERRED_EXTENSION_ID\n );\n await preferredProvider.sendHandshakeRequest();\n return preferredProvider;\n } catch (e) {\n // If preferred extension fails for whatever reason, fallback to using any installed extension\n const backupProvider = new PlatformAuthExtensionHandler(\n logger,\n handshakeTimeoutMs,\n performanceClient\n );\n await backupProvider.sendHandshakeRequest();\n return backupProvider;\n }\n }\n\n /**\n * Send handshake request helper.\n */\n private async sendHandshakeRequest(): Promise {\n this.logger.trace(\n this.platformAuthType + \" - sendHandshakeRequest called.\"\n );\n // Register this event listener before sending handshake\n window.addEventListener(\"message\", this.windowListener, false); // false is important, because content script message processing should work first\n\n const req: NativeExtensionRequest = {\n channel: PlatformAuthConstants.CHANNEL_ID,\n extensionId: this.extensionId,\n responseId: createNewGuid(),\n body: {\n method: NativeExtensionMethod.HandshakeRequest,\n },\n };\n this.handshakeEvent.add({\n extensionId: this.extensionId,\n extensionHandshakeTimeoutMs: this.handshakeTimeoutMs,\n });\n\n this.messageChannel.port1.onmessage = (event) => {\n this.onChannelMessage(event);\n };\n\n window.postMessage(req, window.origin, [this.messageChannel.port2]);\n\n return new Promise((resolve, reject) => {\n this.handshakeResolvers.set(req.responseId, { resolve, reject });\n this.timeoutId = window.setTimeout(() => {\n /*\n * Throw an error if neither HandshakeResponse nor original Handshake request are received in a reasonable timeframe.\n * This typically suggests an event handler stopped propagation of the Handshake request but did not respond to it on the MessageChannel port\n */\n window.removeEventListener(\n \"message\",\n this.windowListener,\n false\n );\n this.messageChannel.port1.close();\n this.messageChannel.port2.close();\n this.handshakeEvent.end({\n extensionHandshakeTimedOut: true,\n success: false,\n });\n reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.nativeHandshakeTimeout\n )\n );\n this.handshakeResolvers.delete(req.responseId);\n }, this.handshakeTimeoutMs); // Use a reasonable timeout in milliseconds here\n });\n }\n\n /**\n * Invoked when a message is posted to the window. If a handshake request is received it means the extension is not installed.\n * @param event\n */\n private onWindowMessage(event: MessageEvent): void {\n this.logger.trace(this.platformAuthType + \" - onWindowMessage called\");\n // We only accept messages from ourselves\n if (event.source !== window) {\n return;\n }\n\n const request = event.data;\n\n if (\n !request.channel ||\n request.channel !== PlatformAuthConstants.CHANNEL_ID\n ) {\n return;\n }\n\n if (request.extensionId && request.extensionId !== this.extensionId) {\n return;\n }\n\n if (request.body.method === NativeExtensionMethod.HandshakeRequest) {\n const handshakeResolver = this.handshakeResolvers.get(\n request.responseId\n );\n /*\n * Filter out responses with no matched resolvers sooner to keep channel ports open while waiting for\n * the proper response.\n */\n if (!handshakeResolver) {\n this.logger.trace(\n this.platformAuthType +\n `.onWindowMessage - resolver can't be found for request ${request.responseId}`\n );\n return;\n }\n\n // If we receive this message back it means no extension intercepted the request, meaning no extension supporting handshake protocol is installed\n this.logger.verbose(\n request.extensionId\n ? `Extension with id: ${request.extensionId} not installed`\n : \"No extension installed\"\n );\n clearTimeout(this.timeoutId);\n this.messageChannel.port1.close();\n this.messageChannel.port2.close();\n window.removeEventListener(\"message\", this.windowListener, false);\n this.handshakeEvent.end({\n success: false,\n extensionInstalled: false,\n });\n handshakeResolver.reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.nativeExtensionNotInstalled\n )\n );\n }\n }\n\n /**\n * Invoked when a message is received from the extension on the MessageChannel port\n * @param event\n */\n private onChannelMessage(event: MessageEvent): void {\n this.logger.trace(\n this.platformAuthType + \" - onChannelMessage called.\"\n );\n const request = event.data;\n\n const resolver = this.resolvers.get(request.responseId);\n const handshakeResolver = this.handshakeResolvers.get(\n request.responseId\n );\n\n try {\n const method = request.body.method;\n\n if (method === NativeExtensionMethod.Response) {\n if (!resolver) {\n return;\n }\n const response = request.body.response;\n this.logger.trace(\n this.platformAuthType +\n \" - Received response from browser extension\"\n );\n this.logger.tracePii(\n this.platformAuthType +\n ` - Received response from browser extension: ${JSON.stringify(\n response\n )}`\n );\n if (response.status !== \"Success\") {\n resolver.reject(\n createNativeAuthError(\n response.code,\n response.description,\n response.ext\n )\n );\n } else if (response.result) {\n if (\n response.result[\"code\"] &&\n response.result[\"description\"]\n ) {\n resolver.reject(\n createNativeAuthError(\n response.result[\"code\"],\n response.result[\"description\"],\n response.result[\"ext\"]\n )\n );\n } else {\n resolver.resolve(response.result);\n }\n } else {\n throw createAuthError(\n AuthErrorCodes.unexpectedError,\n \"Event does not contain result.\"\n );\n }\n this.resolvers.delete(request.responseId);\n } else if (method === NativeExtensionMethod.HandshakeResponse) {\n if (!handshakeResolver) {\n this.logger.trace(\n this.platformAuthType +\n `.onChannelMessage - resolver can't be found for request ${request.responseId}`\n );\n return;\n }\n clearTimeout(this.timeoutId); // Clear setTimeout\n window.removeEventListener(\n \"message\",\n this.windowListener,\n false\n ); // Remove 'No extension' listener\n this.extensionId = request.extensionId;\n this.extensionVersion = request.body.version;\n this.logger.verbose(\n this.platformAuthType +\n ` - Received HandshakeResponse from extension: ${this.extensionId}`\n );\n this.handshakeEvent.end({\n extensionInstalled: true,\n success: true,\n });\n\n handshakeResolver.resolve();\n this.handshakeResolvers.delete(request.responseId);\n }\n // Do nothing if method is not Response or HandshakeResponse\n } catch (err) {\n this.logger.error(\"Error parsing response from WAM Extension\");\n this.logger.errorPii(\n `Error parsing response from WAM Extension: ${err as string}`\n );\n this.logger.errorPii(`Unable to parse ${event}`);\n\n if (resolver) {\n resolver.reject(err as AuthError);\n } else if (handshakeResolver) {\n handshakeResolver.reject(err as AuthError);\n }\n }\n }\n\n /**\n * Validates native platform response before processing\n * @param response\n */\n private validatePlatformBrokerResponse(\n response: object\n ): PlatformAuthResponse {\n if (\n response.hasOwnProperty(\"access_token\") &&\n response.hasOwnProperty(\"id_token\") &&\n response.hasOwnProperty(\"client_info\") &&\n response.hasOwnProperty(\"account\") &&\n response.hasOwnProperty(\"scope\") &&\n response.hasOwnProperty(\"expires_in\")\n ) {\n return response as PlatformAuthResponse;\n } else {\n throw createAuthError(\n AuthErrorCodes.unexpectedError,\n \"Response missing expected properties.\"\n );\n }\n }\n\n /**\n * Returns the Id for the browser extension this handler is communicating with\n * @returns\n */\n getExtensionId(): string | undefined {\n return this.extensionId;\n }\n\n /**\n * Returns the version for the browser extension this handler is communicating with\n * @returns\n */\n getExtensionVersion(): string | undefined {\n return this.extensionVersion;\n }\n\n getExtensionName(): string | undefined {\n return this.getExtensionId() ===\n PlatformAuthConstants.PREFERRED_EXTENSION_ID\n ? \"chrome\"\n : this.getExtensionId()?.length\n ? \"unknown\"\n : undefined;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n Logger,\n createAuthError,\n AuthErrorCodes,\n IPerformanceClient,\n StringDict,\n} from \"@azure/msal-common/browser\";\nimport {\n DOMExtraParameters,\n PlatformAuthRequest,\n PlatformDOMTokenRequest,\n} from \"./PlatformAuthRequest.js\";\nimport { PlatformAuthConstants } from \"../../utils/BrowserConstants.js\";\nimport {\n PlatformAuthResponse,\n PlatformDOMTokenResponse,\n} from \"./PlatformAuthResponse.js\";\nimport { createNativeAuthError } from \"../../error/NativeAuthError.js\";\nimport { IPlatformAuthHandler } from \"./IPlatformAuthHandler.js\";\n\nexport class PlatformAuthDOMHandler implements IPlatformAuthHandler {\n protected logger: Logger;\n protected performanceClient: IPerformanceClient;\n protected correlationId: string;\n platformAuthType: string;\n\n constructor(\n logger: Logger,\n performanceClient: IPerformanceClient,\n correlationId: string\n ) {\n this.logger = logger;\n this.performanceClient = performanceClient;\n this.correlationId = correlationId;\n this.platformAuthType = PlatformAuthConstants.PLATFORM_DOM_PROVIDER;\n }\n\n static async createProvider(\n logger: Logger,\n performanceClient: IPerformanceClient,\n correlationId: string\n ): Promise {\n logger.trace(\"PlatformAuthDOMHandler: createProvider called\");\n\n // @ts-ignore\n if (window.navigator?.platformAuthentication) {\n const supportedContracts =\n // @ts-ignore\n await window.navigator.platformAuthentication.getSupportedContracts(\n PlatformAuthConstants.MICROSOFT_ENTRA_BROKERID\n );\n if (\n supportedContracts?.includes(\n PlatformAuthConstants.PLATFORM_DOM_APIS\n )\n ) {\n logger.trace(\"Platform auth api available in DOM\");\n return new PlatformAuthDOMHandler(\n logger,\n performanceClient,\n correlationId\n );\n }\n }\n return undefined;\n }\n\n /**\n * Returns the Id for the broker extension this handler is communicating with\n * @returns\n */\n getExtensionId(): string {\n return PlatformAuthConstants.MICROSOFT_ENTRA_BROKERID;\n }\n\n getExtensionVersion(): string | undefined {\n return \"\";\n }\n\n getExtensionName(): string | undefined {\n return PlatformAuthConstants.DOM_API_NAME;\n }\n\n /**\n * Send token request to platform broker via browser DOM API\n * @param request\n * @returns\n */\n async sendMessage(\n request: PlatformAuthRequest\n ): Promise {\n this.logger.trace(\n this.platformAuthType + \" - Sending request to browser DOM API\"\n );\n\n try {\n const platformDOMRequest: PlatformDOMTokenRequest =\n this.initializePlatformDOMRequest(request);\n const response: object =\n // @ts-ignore\n await window.navigator.platformAuthentication.executeGetToken(\n platformDOMRequest\n );\n return this.validatePlatformBrokerResponse(response);\n } catch (e) {\n this.logger.error(\n this.platformAuthType + \" - executeGetToken DOM API error\"\n );\n throw e;\n }\n }\n\n private initializePlatformDOMRequest(\n request: PlatformAuthRequest\n ): PlatformDOMTokenRequest {\n this.logger.trace(\n this.platformAuthType + \" - initializeNativeDOMRequest called\"\n );\n\n const {\n accountId,\n clientId,\n authority,\n scope,\n redirectUri,\n correlationId,\n state,\n storeInCache,\n embeddedClientId,\n extraParameters,\n ...remainingProperties\n } = request;\n\n const validExtraParameters: DOMExtraParameters =\n this.getDOMExtraParams(remainingProperties);\n\n const platformDOMRequest: PlatformDOMTokenRequest = {\n accountId: accountId,\n brokerId: this.getExtensionId(),\n authority: authority,\n clientId: clientId,\n correlationId: correlationId || this.correlationId,\n extraParameters: { ...extraParameters, ...validExtraParameters },\n isSecurityTokenService: false,\n redirectUri: redirectUri,\n scope: scope,\n state: state,\n storeInCache: storeInCache,\n embeddedClientId: embeddedClientId,\n };\n\n return platformDOMRequest;\n }\n\n private validatePlatformBrokerResponse(\n response: object\n ): PlatformAuthResponse {\n if (response.hasOwnProperty(\"isSuccess\")) {\n if (\n response.hasOwnProperty(\"accessToken\") &&\n response.hasOwnProperty(\"idToken\") &&\n response.hasOwnProperty(\"clientInfo\") &&\n response.hasOwnProperty(\"account\") &&\n response.hasOwnProperty(\"scopes\") &&\n response.hasOwnProperty(\"expiresIn\")\n ) {\n this.logger.trace(\n this.platformAuthType +\n \" - platform broker returned successful and valid response\"\n );\n return this.convertToPlatformBrokerResponse(\n response as PlatformDOMTokenResponse\n );\n } else if (response.hasOwnProperty(\"error\")) {\n const errorResponse = response as PlatformDOMTokenResponse;\n if (\n errorResponse.isSuccess === false &&\n errorResponse.error &&\n errorResponse.error.code\n ) {\n this.logger.trace(\n this.platformAuthType +\n \" - platform broker returned error response\"\n );\n throw createNativeAuthError(\n errorResponse.error.code,\n errorResponse.error.description,\n {\n error: parseInt(errorResponse.error.errorCode),\n protocol_error: errorResponse.error.protocolError,\n status: errorResponse.error.status,\n properties: errorResponse.error.properties,\n }\n );\n }\n }\n }\n throw createAuthError(\n AuthErrorCodes.unexpectedError,\n \"Response missing expected properties.\"\n );\n }\n\n private convertToPlatformBrokerResponse(\n response: PlatformDOMTokenResponse\n ): PlatformAuthResponse {\n this.logger.trace(\n this.platformAuthType + \" - convertToNativeResponse called\"\n );\n const nativeResponse: PlatformAuthResponse = {\n access_token: response.accessToken,\n id_token: response.idToken,\n client_info: response.clientInfo,\n account: response.account,\n expires_in: response.expiresIn,\n scope: response.scopes,\n state: response.state || \"\",\n properties: response.properties || {},\n extendedLifetimeToken: response.extendedLifetimeToken ?? false,\n shr: response.proofOfPossessionPayload,\n };\n\n return nativeResponse;\n }\n\n private getDOMExtraParams(\n extraParameters: Record\n ): DOMExtraParameters {\n const stringifiedParams = Object.entries(extraParameters).reduce(\n (record, [key, value]) => {\n record[key] = String(value);\n return record;\n },\n {} as StringDict\n );\n\n const validExtraParams: DOMExtraParameters = {\n ...stringifiedParams,\n };\n\n return validExtraParams;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n LoggerOptions,\n IPerformanceClient,\n Logger,\n AuthenticationScheme,\n StubPerformanceClient,\n} from \"@azure/msal-common/browser\";\nimport { name, version } from \"../../packageMetadata.js\";\nimport {\n BrowserConfiguration,\n DEFAULT_NATIVE_BROKER_HANDSHAKE_TIMEOUT_MS,\n} from \"../../config/Configuration.js\";\nimport { PlatformAuthExtensionHandler } from \"./PlatformAuthExtensionHandler.js\";\nimport { IPlatformAuthHandler } from \"./IPlatformAuthHandler.js\";\nimport { PlatformAuthDOMHandler } from \"./PlatformAuthDOMHandler.js\";\nimport { createNewGuid } from \"../../crypto/BrowserCrypto.js\";\nimport { BrowserCacheLocation } from \"../../utils/BrowserConstants.js\";\nimport { PLATFORM_AUTH_DOM_SUPPORT } from \"../../cache/CacheKeys.js\";\n\n/**\n * Checks if the platform broker is available in the current environment.\n * @param loggerOptions\n * @param perfClient\n * @returns\n */\nexport async function isPlatformBrokerAvailable(\n loggerOptions?: LoggerOptions,\n perfClient?: IPerformanceClient,\n correlationId?: string\n): Promise {\n const logger = new Logger(loggerOptions || {}, name, version);\n\n logger.trace(\"isPlatformBrokerAvailable called\");\n\n const performanceClient = perfClient || new StubPerformanceClient();\n\n if (typeof window === \"undefined\") {\n logger.trace(\"Non-browser environment detected, returning false\");\n return false;\n }\n\n return !!(await getPlatformAuthProvider(\n logger,\n performanceClient,\n correlationId || createNewGuid()\n ));\n}\n\nexport async function getPlatformAuthProvider(\n logger: Logger,\n performanceClient: IPerformanceClient,\n correlationId: string,\n nativeBrokerHandshakeTimeout?: number\n): Promise {\n logger.trace(\"getPlatformAuthProvider called\", correlationId);\n\n const enablePlatformBrokerDOMSupport = isDomEnabledForPlatformAuth();\n\n logger.trace(\n \"Has client allowed platform auth via DOM API: \" +\n enablePlatformBrokerDOMSupport\n );\n let platformAuthProvider: IPlatformAuthHandler | undefined;\n try {\n if (enablePlatformBrokerDOMSupport) {\n // Check if DOM platform API is supported first\n platformAuthProvider = await PlatformAuthDOMHandler.createProvider(\n logger,\n performanceClient,\n correlationId\n );\n }\n if (!platformAuthProvider) {\n logger.trace(\n \"Platform auth via DOM API not available, checking for extension\"\n );\n /*\n * If DOM APIs are not available, check if browser extension is available.\n * Platform authentication via DOM APIs is preferred over extension APIs.\n */\n platformAuthProvider =\n await PlatformAuthExtensionHandler.createProvider(\n logger,\n nativeBrokerHandshakeTimeout ||\n DEFAULT_NATIVE_BROKER_HANDSHAKE_TIMEOUT_MS,\n performanceClient\n );\n }\n } catch (e) {\n logger.trace(\"Platform auth not available\", e as string);\n }\n return platformAuthProvider;\n}\n\n/**\n * Returns true if the DOM API support for platform auth is enabled in session storage\n * @returns boolean\n * @deprecated\n */\nexport function isDomEnabledForPlatformAuth(): boolean {\n let sessionStorage: Storage | undefined;\n try {\n sessionStorage = window[BrowserCacheLocation.SessionStorage];\n // Mute errors if it's a non-browser environment or cookies are blocked.\n return sessionStorage?.getItem(PLATFORM_AUTH_DOM_SUPPORT) === \"true\";\n } catch (e) {\n return false;\n }\n}\n\n/**\n * Returns boolean indicating whether or not the request should attempt to use native broker\n * @param logger\n * @param config\n * @param platformAuthProvider\n * @param authenticationScheme\n */\nexport function isPlatformAuthAllowed(\n config: BrowserConfiguration,\n logger: Logger,\n platformAuthProvider?: IPlatformAuthHandler,\n authenticationScheme?: AuthenticationScheme\n): boolean {\n logger.trace(\"isPlatformAuthAllowed called\");\n if (!config.system.allowPlatformBroker) {\n logger.trace(\n \"isPlatformAuthAllowed: allowPlatformBroker is not enabled, returning false\"\n );\n // Developer disabled WAM\n return false;\n }\n\n if (!platformAuthProvider) {\n logger.trace(\n \"isPlatformAuthAllowed: Platform auth provider is not initialized, returning false\"\n );\n // Platform broker auth providers are not available\n return false;\n }\n\n if (authenticationScheme) {\n switch (authenticationScheme) {\n case AuthenticationScheme.BEARER:\n case AuthenticationScheme.POP:\n logger.trace(\n \"isPlatformAuthAllowed: authenticationScheme is supported, returning true\"\n );\n return true;\n default:\n logger.trace(\n \"isPlatformAuthAllowed: authenticationScheme is not supported, returning false\"\n );\n return false;\n }\n }\n return true;\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n AuthorizationCodeClient,\n CommonEndSessionRequest,\n UrlString,\n AuthError,\n OIDC_DEFAULT_SCOPES,\n PerformanceEvents,\n IPerformanceClient,\n Logger,\n ICrypto,\n ProtocolMode,\n ServerResponseType,\n invokeAsync,\n invoke,\n PkceCodes,\n CommonAuthorizationUrlRequest,\n HttpMethod,\n} from \"@azure/msal-common/browser\";\nimport { StandardInteractionClient } from \"./StandardInteractionClient.js\";\nimport { EventType } from \"../event/EventType.js\";\nimport {\n InteractionType,\n ApiId,\n BrowserConstants,\n} from \"../utils/BrowserConstants.js\";\nimport { EndSessionPopupRequest } from \"../request/EndSessionPopupRequest.js\";\nimport { NavigationOptions } from \"../navigation/NavigationOptions.js\";\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\nimport { PopupRequest } from \"../request/PopupRequest.js\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\nimport { EventHandler } from \"../event/EventHandler.js\";\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\nimport { PopupWindowAttributes } from \"../request/PopupWindowAttributes.js\";\nimport { EventError } from \"../event/EventMessage.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport * as ResponseHandler from \"../response/ResponseHandler.js\";\nimport * as Authorize from \"../protocol/Authorize.js\";\nimport { generatePkceCodes } from \"../crypto/PkceGenerator.js\";\nimport { isPlatformAuthAllowed } from \"../broker/nativeBroker/PlatformAuthProvider.js\";\nimport { generateEarKey } from \"../crypto/BrowserCrypto.js\";\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\nimport { validateRequestMethod } from \"../request/RequestHelpers.js\";\n\nexport type PopupParams = {\n popup?: Window | null;\n popupName: string;\n popupWindowAttributes: PopupWindowAttributes;\n popupWindowParent: Window;\n};\n\nexport class PopupClient extends StandardInteractionClient {\n private currentWindow: Window | undefined;\n protected nativeStorage: BrowserCacheManager;\n\n constructor(\n config: BrowserConfiguration,\n storageImpl: BrowserCacheManager,\n browserCrypto: ICrypto,\n logger: Logger,\n eventHandler: EventHandler,\n navigationClient: INavigationClient,\n performanceClient: IPerformanceClient,\n nativeStorageImpl: BrowserCacheManager,\n platformAuthHandler?: IPlatformAuthHandler,\n correlationId?: string\n ) {\n super(\n config,\n storageImpl,\n browserCrypto,\n logger,\n eventHandler,\n navigationClient,\n performanceClient,\n platformAuthHandler,\n correlationId\n );\n // Properly sets this reference for the unload event.\n this.unloadWindow = this.unloadWindow.bind(this);\n this.nativeStorage = nativeStorageImpl;\n this.eventHandler = eventHandler;\n }\n\n /**\n * Acquires tokens by opening a popup window to the /authorize endpoint of the authority\n * @param request\n * @param pkceCodes\n */\n acquireToken(\n request: PopupRequest,\n pkceCodes?: PkceCodes\n ): Promise {\n let popupParams: PopupParams | undefined = undefined;\n try {\n const popupName = this.generatePopupName(\n request.scopes || OIDC_DEFAULT_SCOPES,\n request.authority || this.config.auth.authority\n );\n popupParams = {\n popupName,\n popupWindowAttributes: request.popupWindowAttributes || {},\n popupWindowParent: request.popupWindowParent ?? window,\n };\n\n this.performanceClient.addFields(\n { isAsyncPopup: this.config.system.asyncPopups },\n this.correlationId\n );\n\n // asyncPopups flag is true. Acquires token without first opening popup. Popup will be opened later asynchronously.\n if (this.config.system.asyncPopups) {\n this.logger.verbose(\"asyncPopups set to true, acquiring token\");\n // Passes on popup position and dimensions if in request\n return this.acquireTokenPopupAsync(\n request,\n popupParams,\n pkceCodes\n );\n } else {\n // Pre-validate request method to avoid opening popup if the request is invalid\n const validatedRequest: PopupRequest = {\n ...request,\n httpMethod: validateRequestMethod(\n request,\n this.config.auth.protocolMode\n ),\n };\n // asyncPopups flag is set to false. Opens popup before acquiring token.\n this.logger.verbose(\n \"asyncPopup set to false, opening popup before acquiring token\"\n );\n popupParams.popup = this.openSizedPopup(\n \"about:blank\",\n popupParams\n );\n return this.acquireTokenPopupAsync(\n validatedRequest,\n popupParams,\n pkceCodes\n );\n }\n } catch (e) {\n return Promise.reject(e);\n }\n }\n\n /**\n * Clears local cache for the current user then opens a popup window prompting the user to sign-out of the server\n * @param logoutRequest\n */\n logout(logoutRequest?: EndSessionPopupRequest): Promise {\n try {\n this.logger.verbose(\"logoutPopup called\");\n const validLogoutRequest =\n this.initializeLogoutRequest(logoutRequest);\n const popupParams: PopupParams = {\n popupName: this.generateLogoutPopupName(validLogoutRequest),\n popupWindowAttributes:\n logoutRequest?.popupWindowAttributes || {},\n popupWindowParent: logoutRequest?.popupWindowParent ?? window,\n };\n const authority = logoutRequest && logoutRequest.authority;\n const mainWindowRedirectUri =\n logoutRequest && logoutRequest.mainWindowRedirectUri;\n\n // asyncPopups flag is true. Acquires token without first opening popup. Popup will be opened later asynchronously.\n if (this.config.system.asyncPopups) {\n this.logger.verbose(\"asyncPopups set to true\");\n // Passes on popup position and dimensions if in request\n return this.logoutPopupAsync(\n validLogoutRequest,\n popupParams,\n authority,\n mainWindowRedirectUri\n );\n } else {\n // asyncPopups flag is set to false. Opens popup before logging out.\n this.logger.verbose(\"asyncPopup set to false, opening popup\");\n popupParams.popup = this.openSizedPopup(\n \"about:blank\",\n popupParams\n );\n return this.logoutPopupAsync(\n validLogoutRequest,\n popupParams,\n authority,\n mainWindowRedirectUri\n );\n }\n } catch (e) {\n // Since this function is synchronous we need to reject\n return Promise.reject(e);\n }\n }\n\n /**\n * Helper which obtains an access_token for your API via opening a popup window in the user's browser\n * @param request\n * @param popupParams\n * @param pkceCodes\n *\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\n */\n protected async acquireTokenPopupAsync(\n request: PopupRequest,\n popupParams: PopupParams,\n pkceCodes?: PkceCodes\n ): Promise {\n this.logger.verbose(\"acquireTokenPopupAsync called\");\n\n const validRequest = await invokeAsync(\n this.initializeAuthorizationRequest.bind(this),\n PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(request, InteractionType.Popup);\n\n /*\n * Skip pre-connect for async popups to reduce time between user interaction and popup window creation to avoid\n * popup from being blocked by browsers with shorter popup timers\n */\n if (popupParams.popup) {\n BrowserUtils.preconnect(validRequest.authority);\n }\n\n const isPlatformBroker = isPlatformAuthAllowed(\n this.config,\n this.logger,\n this.platformAuthProvider,\n request.authenticationScheme\n );\n validRequest.platformBroker = isPlatformBroker;\n\n if (this.config.auth.protocolMode === ProtocolMode.EAR) {\n return this.executeEarFlow(validRequest, popupParams);\n } else {\n return this.executeCodeFlow(validRequest, popupParams, pkceCodes);\n }\n }\n\n /**\n * Executes auth code + PKCE flow\n * @param request\n * @param popupParams\n * @param pkceCodes\n * @returns\n */\n async executeCodeFlow(\n request: CommonAuthorizationUrlRequest,\n popupParams: PopupParams,\n pkceCodes?: PkceCodes\n ): Promise {\n const correlationId = request.correlationId;\n const serverTelemetryManager = this.initializeServerTelemetryManager(\n ApiId.acquireTokenPopup\n );\n\n const pkce =\n pkceCodes ||\n (await invokeAsync(\n generatePkceCodes,\n PerformanceEvents.GeneratePkceCodes,\n this.logger,\n this.performanceClient,\n correlationId\n )(this.performanceClient, this.logger, correlationId));\n\n const popupRequest = {\n ...request,\n codeChallenge: pkce.challenge,\n };\n\n try {\n // Initialize the client\n const authClient: AuthorizationCodeClient = await invokeAsync(\n this.createAuthCodeClient.bind(this),\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\n this.logger,\n this.performanceClient,\n correlationId\n )({\n serverTelemetryManager,\n requestAuthority: popupRequest.authority,\n requestAzureCloudOptions: popupRequest.azureCloudOptions,\n requestExtraQueryParameters: popupRequest.extraQueryParameters,\n account: popupRequest.account,\n });\n\n if (popupRequest.httpMethod === HttpMethod.POST) {\n return await this.executeCodeFlowWithPost(\n popupRequest,\n popupParams,\n authClient,\n pkce.verifier\n );\n } else {\n // Create acquire token url.\n const navigateUrl = await invokeAsync(\n Authorize.getAuthCodeRequestUrl,\n PerformanceEvents.GetAuthCodeUrl,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n this.config,\n authClient.authority,\n popupRequest,\n this.logger,\n this.performanceClient\n );\n\n // Show the UI once the url has been created. Get the window handle for the popup.\n const popupWindow: Window = this.initiateAuthRequest(\n navigateUrl,\n popupParams\n );\n this.eventHandler.emitEvent(\n EventType.POPUP_OPENED,\n InteractionType.Popup,\n { popupWindow },\n null\n );\n\n // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.\n const responseString = await this.monitorPopupForHash(\n popupWindow,\n popupParams.popupWindowParent\n );\n\n const serverParams = invoke(\n ResponseHandler.deserializeResponse,\n PerformanceEvents.DeserializeResponse,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(\n responseString,\n this.config.auth.OIDCOptions.serverResponseType,\n this.logger\n );\n\n return await invokeAsync(\n Authorize.handleResponseCode,\n PerformanceEvents.HandleResponseCode,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n request,\n serverParams,\n pkce.verifier,\n ApiId.acquireTokenPopup,\n this.config,\n authClient,\n this.browserStorage,\n this.nativeStorage,\n this.eventHandler,\n this.logger,\n this.performanceClient,\n this.platformAuthProvider\n );\n }\n } catch (e) {\n // Close the synchronous popup if an error is thrown before the window unload event is registered\n popupParams.popup?.close();\n\n if (e instanceof AuthError) {\n (e as AuthError).setCorrelationId(this.correlationId);\n serverTelemetryManager.cacheFailedRequest(e);\n }\n throw e;\n }\n }\n\n /**\n * Executes EAR flow\n * @param request\n */\n async executeEarFlow(\n request: CommonAuthorizationUrlRequest,\n popupParams: PopupParams\n ): Promise {\n const correlationId = request.correlationId;\n // Get the frame handle for the silent request\n const discoveredAuthority = await invokeAsync(\n this.getDiscoveredAuthority.bind(this),\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\n this.logger,\n this.performanceClient,\n correlationId\n )({\n requestAuthority: request.authority,\n requestAzureCloudOptions: request.azureCloudOptions,\n requestExtraQueryParameters: request.extraQueryParameters,\n account: request.account,\n });\n\n const earJwk = await invokeAsync(\n generateEarKey,\n PerformanceEvents.GenerateEarKey,\n this.logger,\n this.performanceClient,\n correlationId\n )();\n const popupRequest = {\n ...request,\n earJwk: earJwk,\n };\n const popupWindow =\n popupParams.popup || this.openPopup(\"about:blank\", popupParams);\n\n const form = await Authorize.getEARForm(\n popupWindow.document,\n this.config,\n discoveredAuthority,\n popupRequest,\n this.logger,\n this.performanceClient\n );\n form.submit();\n\n // Monitor the popup for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.\n const responseString = await invokeAsync(\n this.monitorPopupForHash.bind(this),\n PerformanceEvents.SilentHandlerMonitorIframeForHash,\n this.logger,\n this.performanceClient,\n correlationId\n )(popupWindow, popupParams.popupWindowParent);\n\n const serverParams = invoke(\n ResponseHandler.deserializeResponse,\n PerformanceEvents.DeserializeResponse,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(\n responseString,\n this.config.auth.OIDCOptions.serverResponseType,\n this.logger\n );\n\n return invokeAsync(\n Authorize.handleResponseEAR,\n PerformanceEvents.HandleResponseEar,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n popupRequest,\n serverParams,\n ApiId.acquireTokenPopup,\n this.config,\n discoveredAuthority,\n this.browserStorage,\n this.nativeStorage,\n this.eventHandler,\n this.logger,\n this.performanceClient,\n this.platformAuthProvider\n );\n }\n\n async executeCodeFlowWithPost(\n request: CommonAuthorizationUrlRequest,\n popupParams: PopupParams,\n authClient: AuthorizationCodeClient,\n pkceVerifier: string\n ): Promise {\n const correlationId = request.correlationId;\n // Get the frame handle for the silent request\n const discoveredAuthority = await invokeAsync(\n this.getDiscoveredAuthority.bind(this),\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\n this.logger,\n this.performanceClient,\n correlationId\n )({\n requestAuthority: request.authority,\n requestAzureCloudOptions: request.azureCloudOptions,\n requestExtraQueryParameters: request.extraQueryParameters,\n account: request.account,\n });\n\n const popupWindow =\n popupParams.popup || this.openPopup(\"about:blank\", popupParams);\n\n const form = await Authorize.getCodeForm(\n popupWindow.document,\n this.config,\n discoveredAuthority,\n request,\n this.logger,\n this.performanceClient\n );\n\n form.submit();\n\n // Monitor the popup for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.\n const responseString = await invokeAsync(\n this.monitorPopupForHash.bind(this),\n PerformanceEvents.SilentHandlerMonitorIframeForHash,\n this.logger,\n this.performanceClient,\n correlationId\n )(popupWindow, popupParams.popupWindowParent);\n\n const serverParams = invoke(\n ResponseHandler.deserializeResponse,\n PerformanceEvents.DeserializeResponse,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(\n responseString,\n this.config.auth.OIDCOptions.serverResponseType,\n this.logger\n );\n\n return invokeAsync(\n Authorize.handleResponseCode,\n PerformanceEvents.HandleResponseCode,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n request,\n serverParams,\n pkceVerifier,\n ApiId.acquireTokenPopup,\n this.config,\n authClient,\n this.browserStorage,\n this.nativeStorage,\n this.eventHandler,\n this.logger,\n this.performanceClient,\n this.platformAuthProvider\n );\n }\n\n /**\n *\n * @param validRequest\n * @param popupName\n * @param requestAuthority\n * @param popup\n * @param mainWindowRedirectUri\n * @param popupWindowAttributes\n */\n protected async logoutPopupAsync(\n validRequest: CommonEndSessionRequest,\n popupParams: PopupParams,\n requestAuthority?: string,\n mainWindowRedirectUri?: string\n ): Promise {\n this.logger.verbose(\"logoutPopupAsync called\");\n this.eventHandler.emitEvent(\n EventType.LOGOUT_START,\n InteractionType.Popup,\n validRequest\n );\n\n const serverTelemetryManager = this.initializeServerTelemetryManager(\n ApiId.logoutPopup\n );\n\n try {\n // Clear cache on logout\n await this.clearCacheOnLogout(\n this.correlationId,\n validRequest.account\n );\n\n // Initialize the client\n const authClient = await invokeAsync(\n this.createAuthCodeClient.bind(this),\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\n this.logger,\n this.performanceClient,\n this.correlationId\n )({\n serverTelemetryManager,\n requestAuthority: requestAuthority,\n account: validRequest.account || undefined,\n });\n\n try {\n authClient.authority.endSessionEndpoint;\n } catch {\n if (\n validRequest.account?.homeAccountId &&\n validRequest.postLogoutRedirectUri &&\n authClient.authority.protocolMode === ProtocolMode.OIDC\n ) {\n this.eventHandler.emitEvent(\n EventType.LOGOUT_SUCCESS,\n InteractionType.Popup,\n validRequest\n );\n\n if (mainWindowRedirectUri) {\n const navigationOptions: NavigationOptions = {\n apiId: ApiId.logoutPopup,\n timeout:\n this.config.system.redirectNavigationTimeout,\n noHistory: false,\n };\n const absoluteUrl = UrlString.getAbsoluteUrl(\n mainWindowRedirectUri,\n BrowserUtils.getCurrentUri()\n );\n await this.navigationClient.navigateInternal(\n absoluteUrl,\n navigationOptions\n );\n }\n\n popupParams.popup?.close();\n\n return;\n }\n }\n\n // Create logout string and navigate user window to logout.\n const logoutUri: string = authClient.getLogoutUri(validRequest);\n\n this.eventHandler.emitEvent(\n EventType.LOGOUT_SUCCESS,\n InteractionType.Popup,\n validRequest\n );\n\n // Open the popup window to requestUrl.\n const popupWindow = this.openPopup(logoutUri, popupParams);\n this.eventHandler.emitEvent(\n EventType.POPUP_OPENED,\n InteractionType.Popup,\n { popupWindow },\n null\n );\n\n await this.monitorPopupForHash(\n popupWindow,\n popupParams.popupWindowParent\n ).catch(() => {\n // Swallow any errors related to monitoring the window. Server logout is best effort\n });\n\n if (mainWindowRedirectUri) {\n const navigationOptions: NavigationOptions = {\n apiId: ApiId.logoutPopup,\n timeout: this.config.system.redirectNavigationTimeout,\n noHistory: false,\n };\n const absoluteUrl = UrlString.getAbsoluteUrl(\n mainWindowRedirectUri,\n BrowserUtils.getCurrentUri()\n );\n\n this.logger.verbose(\n \"Redirecting main window to url specified in the request\"\n );\n this.logger.verbosePii(\n `Redirecting main window to: ${absoluteUrl}`\n );\n await this.navigationClient.navigateInternal(\n absoluteUrl,\n navigationOptions\n );\n } else {\n this.logger.verbose(\"No main window navigation requested\");\n }\n } catch (e) {\n // Close the synchronous popup if an error is thrown before the window unload event is registered\n popupParams.popup?.close();\n\n if (e instanceof AuthError) {\n (e as AuthError).setCorrelationId(this.correlationId);\n serverTelemetryManager.cacheFailedRequest(e);\n }\n this.eventHandler.emitEvent(\n EventType.LOGOUT_FAILURE,\n InteractionType.Popup,\n null,\n e as EventError\n );\n this.eventHandler.emitEvent(\n EventType.LOGOUT_END,\n InteractionType.Popup\n );\n throw e;\n }\n\n this.eventHandler.emitEvent(\n EventType.LOGOUT_END,\n InteractionType.Popup\n );\n }\n\n /**\n * Opens a popup window with given request Url.\n * @param requestUrl\n */\n initiateAuthRequest(requestUrl: string, params: PopupParams): Window {\n // Check that request url is not empty.\n if (requestUrl) {\n this.logger.infoPii(`Navigate to: ${requestUrl}`);\n // Open the popup window to requestUrl.\n return this.openPopup(requestUrl, params);\n } else {\n // Throw error if request URL is empty.\n this.logger.error(\"Navigate url is empty\");\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.emptyNavigateUri\n );\n }\n }\n\n /**\n * Monitors a window until it loads a url with the same origin.\n * @param popupWindow - window that is being monitored\n * @param timeout - timeout for processing hash once popup is redirected back to application\n */\n monitorPopupForHash(\n popupWindow: Window,\n popupWindowParent: Window\n ): Promise {\n return new Promise((resolve, reject) => {\n this.logger.verbose(\n \"PopupHandler.monitorPopupForHash - polling started\"\n );\n\n const intervalId = setInterval(() => {\n // Window is closed\n if (popupWindow.closed) {\n this.logger.error(\n \"PopupHandler.monitorPopupForHash - window closed\"\n );\n clearInterval(intervalId);\n reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.userCancelled\n )\n );\n return;\n }\n\n let href = \"\";\n try {\n /*\n * Will throw if cross origin,\n * which should be caught and ignored\n * since we need the interval to keep running while on STS UI.\n */\n href = popupWindow.location.href;\n } catch (e) {}\n\n // Don't process blank pages or cross domain\n if (!href || href === \"about:blank\") {\n return;\n }\n clearInterval(intervalId);\n\n let responseString = \"\";\n const responseType =\n this.config.auth.OIDCOptions.serverResponseType;\n if (popupWindow) {\n if (responseType === ServerResponseType.QUERY) {\n responseString = popupWindow.location.search;\n } else {\n responseString = popupWindow.location.hash;\n }\n }\n\n this.logger.verbose(\n \"PopupHandler.monitorPopupForHash - popup window is on same origin as caller\"\n );\n\n resolve(responseString);\n }, this.config.system.pollIntervalMilliseconds);\n }).finally(() => {\n this.cleanPopup(popupWindow, popupWindowParent);\n });\n }\n\n /**\n * @hidden\n *\n * Configures popup window for login.\n *\n * @param urlNavigate\n * @param title\n * @param popUpWidth\n * @param popUpHeight\n * @param popupWindowAttributes\n * @ignore\n * @hidden\n */\n openPopup(urlNavigate: string, popupParams: PopupParams): Window {\n try {\n let popupWindow;\n // Popup window passed in, setting url to navigate to\n if (popupParams.popup) {\n popupWindow = popupParams.popup;\n this.logger.verbosePii(\n `Navigating popup window to: ${urlNavigate}`\n );\n popupWindow.location.assign(urlNavigate);\n } else if (typeof popupParams.popup === \"undefined\") {\n // Popup will be undefined if it was not passed in\n this.logger.verbosePii(\n `Opening popup window to: ${urlNavigate}`\n );\n popupWindow = this.openSizedPopup(urlNavigate, popupParams);\n }\n\n // Popup will be null if popups are blocked\n if (!popupWindow) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.emptyWindowError\n );\n }\n if (popupWindow.focus) {\n popupWindow.focus();\n }\n this.currentWindow = popupWindow;\n popupParams.popupWindowParent.addEventListener(\n \"beforeunload\",\n this.unloadWindow\n );\n\n return popupWindow;\n } catch (e) {\n this.logger.error(\n \"error opening popup \" + (e as AuthError).message\n );\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.popupWindowError\n );\n }\n }\n\n /**\n * Helper function to set popup window dimensions and position\n * @param urlNavigate\n * @param popupName\n * @param popupWindowAttributes\n * @returns\n */\n openSizedPopup(\n urlNavigate: string,\n { popupName, popupWindowAttributes, popupWindowParent }: PopupParams\n ): Window | null {\n /**\n * adding winLeft and winTop to account for dual monitor\n * using screenLeft and screenTop for IE8 and earlier\n */\n const winLeft = popupWindowParent.screenLeft\n ? popupWindowParent.screenLeft\n : popupWindowParent.screenX;\n const winTop = popupWindowParent.screenTop\n ? popupWindowParent.screenTop\n : popupWindowParent.screenY;\n /**\n * window.innerWidth displays browser window\"s height and width excluding toolbars\n * using document.documentElement.clientWidth for IE8 and earlier\n */\n const winWidth =\n popupWindowParent.innerWidth ||\n document.documentElement.clientWidth ||\n document.body.clientWidth;\n const winHeight =\n popupWindowParent.innerHeight ||\n document.documentElement.clientHeight ||\n document.body.clientHeight;\n\n let width = popupWindowAttributes.popupSize?.width;\n let height = popupWindowAttributes.popupSize?.height;\n let top = popupWindowAttributes.popupPosition?.top;\n let left = popupWindowAttributes.popupPosition?.left;\n\n if (!width || width < 0 || width > winWidth) {\n this.logger.verbose(\n \"Default popup window width used. Window width not configured or invalid.\"\n );\n width = BrowserConstants.POPUP_WIDTH;\n }\n\n if (!height || height < 0 || height > winHeight) {\n this.logger.verbose(\n \"Default popup window height used. Window height not configured or invalid.\"\n );\n height = BrowserConstants.POPUP_HEIGHT;\n }\n\n if (!top || top < 0 || top > winHeight) {\n this.logger.verbose(\n \"Default popup window top position used. Window top not configured or invalid.\"\n );\n top = Math.max(\n 0,\n winHeight / 2 - BrowserConstants.POPUP_HEIGHT / 2 + winTop\n );\n }\n\n if (!left || left < 0 || left > winWidth) {\n this.logger.verbose(\n \"Default popup window left position used. Window left not configured or invalid.\"\n );\n left = Math.max(\n 0,\n winWidth / 2 - BrowserConstants.POPUP_WIDTH / 2 + winLeft\n );\n }\n\n return popupWindowParent.open(\n urlNavigate,\n popupName,\n `width=${width}, height=${height}, top=${top}, left=${left}, scrollbars=yes`\n );\n }\n\n /**\n * Event callback to unload main window.\n */\n unloadWindow(e: Event): void {\n if (this.currentWindow) {\n this.currentWindow.close();\n }\n // Guarantees browser unload will happen, so no other errors will be thrown.\n e.preventDefault();\n }\n\n /**\n * Closes popup, removes any state vars created during popup calls.\n * @param popupWindow\n */\n cleanPopup(popupWindow: Window, popupWindowParent: Window): void {\n // Close window.\n popupWindow.close();\n\n // Remove window unload function\n popupWindowParent.removeEventListener(\n \"beforeunload\",\n this.unloadWindow\n );\n }\n\n /**\n * Generates the name for the popup based on the client id and request\n * @param clientId\n * @param request\n */\n generatePopupName(scopes: Array, authority: string): string {\n return `${BrowserConstants.POPUP_NAME_PREFIX}.${\n this.config.auth.clientId\n }.${scopes.join(\"-\")}.${authority}.${this.correlationId}`;\n }\n\n /**\n * Generates the name for the popup based on the client id and request for logouts\n * @param clientId\n * @param request\n */\n generateLogoutPopupName(request: CommonEndSessionRequest): string {\n const homeAccountId = request.account && request.account.homeAccountId;\n return `${BrowserConstants.POPUP_NAME_PREFIX}.${this.config.auth.clientId}.${homeAccountId}.${this.correlationId}`;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n AuthorizationCodeClient,\n UrlString,\n AuthError,\n ServerTelemetryManager,\n Constants,\n AuthorizeResponse,\n ICrypto,\n Logger,\n IPerformanceClient,\n PerformanceEvents,\n ProtocolMode,\n invokeAsync,\n ServerResponseType,\n UrlUtils,\n InProgressPerformanceEvent,\n CommonAuthorizationUrlRequest,\n HttpMethod,\n} from \"@azure/msal-common/browser\";\nimport { StandardInteractionClient } from \"./StandardInteractionClient.js\";\nimport {\n ApiId,\n INTERACTION_TYPE,\n InteractionType,\n TemporaryCacheKeys,\n} from \"../utils/BrowserConstants.js\";\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\nimport { EventType } from \"../event/EventType.js\";\nimport { NavigationOptions } from \"../navigation/NavigationOptions.js\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\nimport { EventHandler } from \"../event/EventHandler.js\";\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\nimport { EventError } from \"../event/EventMessage.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport * as ResponseHandler from \"../response/ResponseHandler.js\";\nimport * as Authorize from \"../protocol/Authorize.js\";\nimport { generatePkceCodes } from \"../crypto/PkceGenerator.js\";\nimport { isPlatformAuthAllowed } from \"../broker/nativeBroker/PlatformAuthProvider.js\";\nimport { generateEarKey } from \"../crypto/BrowserCrypto.js\";\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\n\nfunction getNavigationType(): NavigationTimingType | undefined {\n if (\n typeof window === \"undefined\" ||\n typeof window.performance === \"undefined\" ||\n typeof window.performance.getEntriesByType !== \"function\"\n ) {\n return undefined;\n }\n\n const navigationEntries = window.performance.getEntriesByType(\"navigation\");\n const navigation = navigationEntries.length\n ? (navigationEntries[0] as PerformanceNavigationTiming)\n : undefined;\n return navigation?.type;\n}\n\nexport class RedirectClient extends StandardInteractionClient {\n protected nativeStorage: BrowserCacheManager;\n\n constructor(\n config: BrowserConfiguration,\n storageImpl: BrowserCacheManager,\n browserCrypto: ICrypto,\n logger: Logger,\n eventHandler: EventHandler,\n navigationClient: INavigationClient,\n performanceClient: IPerformanceClient,\n nativeStorageImpl: BrowserCacheManager,\n platformAuthHandler?: IPlatformAuthHandler,\n correlationId?: string\n ) {\n super(\n config,\n storageImpl,\n browserCrypto,\n logger,\n eventHandler,\n navigationClient,\n performanceClient,\n platformAuthHandler,\n correlationId\n );\n this.nativeStorage = nativeStorageImpl;\n }\n\n /**\n * Redirects the page to the /authorize endpoint of the IDP\n * @param request\n */\n async acquireToken(request: RedirectRequest): Promise {\n const validRequest = await invokeAsync(\n this.initializeAuthorizationRequest.bind(this),\n PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(request, InteractionType.Redirect);\n\n validRequest.platformBroker = isPlatformAuthAllowed(\n this.config,\n this.logger,\n this.platformAuthProvider,\n request.authenticationScheme\n );\n\n const handleBackButton = (event: PageTransitionEvent) => {\n // Clear temporary cache if the back button is clicked during the redirect flow.\n if (event.persisted) {\n this.logger.verbose(\n \"Page was restored from back/forward cache. Clearing temporary cache.\"\n );\n this.browserStorage.resetRequestCache();\n this.eventHandler.emitEvent(\n EventType.RESTORE_FROM_BFCACHE,\n InteractionType.Redirect\n );\n }\n };\n\n const redirectStartPage = this.getRedirectStartPage(\n request.redirectStartPage\n );\n this.logger.verbosePii(`Redirect start page: ${redirectStartPage}`);\n // Cache start page, returns to this page after redirectUri if navigateToLoginRequestUrl is true\n this.browserStorage.setTemporaryCache(\n TemporaryCacheKeys.ORIGIN_URI,\n redirectStartPage,\n true\n );\n\n // Clear temporary cache if the back button is clicked during the redirect flow.\n window.addEventListener(\"pageshow\", handleBackButton);\n\n try {\n if (this.config.auth.protocolMode === ProtocolMode.EAR) {\n await this.executeEarFlow(validRequest);\n } else {\n await this.executeCodeFlow(\n validRequest,\n request.onRedirectNavigate\n );\n }\n } catch (e) {\n if (e instanceof AuthError) {\n e.setCorrelationId(this.correlationId);\n }\n window.removeEventListener(\"pageshow\", handleBackButton);\n throw e;\n }\n }\n\n /**\n * Executes auth code + PKCE flow\n * @param request\n * @returns\n */\n async executeCodeFlow(\n request: CommonAuthorizationUrlRequest,\n onRedirectNavigate?: (url: string) => boolean | void\n ): Promise {\n const correlationId = request.correlationId;\n const serverTelemetryManager = this.initializeServerTelemetryManager(\n ApiId.acquireTokenRedirect\n );\n\n const pkceCodes = await invokeAsync(\n generatePkceCodes,\n PerformanceEvents.GeneratePkceCodes,\n this.logger,\n this.performanceClient,\n correlationId\n )(this.performanceClient, this.logger, correlationId);\n\n const redirectRequest = {\n ...request,\n codeChallenge: pkceCodes.challenge,\n };\n\n this.browserStorage.cacheAuthorizeRequest(\n redirectRequest,\n pkceCodes.verifier\n );\n\n try {\n if (redirectRequest.httpMethod === HttpMethod.POST) {\n return await this.executeCodeFlowWithPost(redirectRequest);\n } else {\n // Initialize the client\n const authClient: AuthorizationCodeClient = await invokeAsync(\n this.createAuthCodeClient.bind(this),\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\n this.logger,\n this.performanceClient,\n this.correlationId\n )({\n serverTelemetryManager,\n requestAuthority: redirectRequest.authority,\n requestAzureCloudOptions: redirectRequest.azureCloudOptions,\n requestExtraQueryParameters:\n redirectRequest.extraQueryParameters,\n account: redirectRequest.account,\n });\n\n // Create acquire token url.\n const navigateUrl = await invokeAsync(\n Authorize.getAuthCodeRequestUrl,\n PerformanceEvents.GetAuthCodeUrl,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(\n this.config,\n authClient.authority,\n redirectRequest,\n this.logger,\n this.performanceClient\n );\n // Show the UI once the url has been created. Response will come back in the hash, which will be handled in the handleRedirectCallback function.\n return await this.initiateAuthRequest(\n navigateUrl,\n onRedirectNavigate\n );\n }\n } catch (e) {\n if (e instanceof AuthError) {\n e.setCorrelationId(this.correlationId);\n serverTelemetryManager.cacheFailedRequest(e);\n }\n throw e;\n }\n }\n\n /**\n * Executes EAR flow\n * @param request\n */\n async executeEarFlow(\n request: CommonAuthorizationUrlRequest\n ): Promise {\n const correlationId = request.correlationId;\n // Get the frame handle for the silent request\n const discoveredAuthority = await invokeAsync(\n this.getDiscoveredAuthority.bind(this),\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\n this.logger,\n this.performanceClient,\n correlationId\n )({\n requestAuthority: request.authority,\n requestAzureCloudOptions: request.azureCloudOptions,\n requestExtraQueryParameters: request.extraQueryParameters,\n account: request.account,\n });\n\n const earJwk = await invokeAsync(\n generateEarKey,\n PerformanceEvents.GenerateEarKey,\n this.logger,\n this.performanceClient,\n correlationId\n )();\n const redirectRequest = {\n ...request,\n earJwk: earJwk,\n };\n this.browserStorage.cacheAuthorizeRequest(redirectRequest);\n\n const form = await Authorize.getEARForm(\n document,\n this.config,\n discoveredAuthority,\n redirectRequest,\n this.logger,\n this.performanceClient\n );\n form.submit();\n return new Promise((resolve, reject) => {\n setTimeout(() => {\n reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.timedOut,\n \"failed_to_redirect\"\n )\n );\n }, this.config.system.redirectNavigationTimeout);\n });\n }\n\n /**\n * Executes classic Authorization Code flow with a POST request.\n * @param request\n */\n async executeCodeFlowWithPost(\n request: CommonAuthorizationUrlRequest\n ): Promise {\n const correlationId = request.correlationId;\n // Get the frame handle for the silent request\n const discoveredAuthority = await invokeAsync(\n this.getDiscoveredAuthority.bind(this),\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\n this.logger,\n this.performanceClient,\n correlationId\n )({\n requestAuthority: request.authority,\n requestAzureCloudOptions: request.azureCloudOptions,\n requestExtraQueryParameters: request.extraQueryParameters,\n account: request.account,\n });\n\n this.browserStorage.cacheAuthorizeRequest(request);\n\n const form = await Authorize.getCodeForm(\n document,\n this.config,\n discoveredAuthority,\n request,\n this.logger,\n this.performanceClient\n );\n\n form.submit();\n return new Promise((resolve, reject) => {\n setTimeout(() => {\n reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.timedOut,\n \"failed_to_redirect\"\n )\n );\n }, this.config.system.redirectNavigationTimeout);\n });\n }\n\n /**\n * Checks if navigateToLoginRequestUrl is set, and:\n * - if true, performs logic to cache and navigate\n * - if false, handles hash string and parses response\n * @param hash {string} url hash\n * @param parentMeasurement {InProgressPerformanceEvent} parent measurement\n */\n async handleRedirectPromise(\n hash: string = \"\",\n request: CommonAuthorizationUrlRequest,\n pkceVerifier: string,\n parentMeasurement: InProgressPerformanceEvent\n ): Promise {\n const serverTelemetryManager = this.initializeServerTelemetryManager(\n ApiId.handleRedirectPromise\n );\n\n try {\n const [serverParams, responseString] = this.getRedirectResponse(\n hash || \"\"\n );\n if (!serverParams) {\n // Not a recognized server response hash or hash not associated with a redirect request\n this.logger.info(\n \"handleRedirectPromise did not detect a response as a result of a redirect. Cleaning temporary cache.\"\n );\n this.browserStorage.resetRequestCache();\n\n // Do not instrument \"no_server_response\" if user clicked back button\n if (getNavigationType() !== \"back_forward\") {\n parentMeasurement.event.errorCode = \"no_server_response\";\n } else {\n this.logger.verbose(\n \"Back navigation event detected. Muting no_server_response error\"\n );\n }\n return null;\n }\n\n // If navigateToLoginRequestUrl is true, get the url where the redirect request was initiated\n const loginRequestUrl =\n this.browserStorage.getTemporaryCache(\n TemporaryCacheKeys.ORIGIN_URI,\n true\n ) || Constants.EMPTY_STRING;\n const loginRequestUrlNormalized =\n UrlUtils.normalizeUrlForComparison(loginRequestUrl);\n const currentUrlNormalized = UrlUtils.normalizeUrlForComparison(\n window.location.href\n );\n\n if (\n loginRequestUrlNormalized === currentUrlNormalized &&\n this.config.auth.navigateToLoginRequestUrl\n ) {\n // We are on the page we need to navigate to - handle hash\n this.logger.verbose(\n \"Current page is loginRequestUrl, handling response\"\n );\n\n if (loginRequestUrl.indexOf(\"#\") > -1) {\n // Replace current hash with non-msal hash, if present\n BrowserUtils.replaceHash(loginRequestUrl);\n }\n\n const handleHashResult = await this.handleResponse(\n serverParams,\n request,\n pkceVerifier,\n serverTelemetryManager\n );\n\n return handleHashResult;\n } else if (!this.config.auth.navigateToLoginRequestUrl) {\n this.logger.verbose(\n \"NavigateToLoginRequestUrl set to false, handling response\"\n );\n return await this.handleResponse(\n serverParams,\n request,\n pkceVerifier,\n serverTelemetryManager\n );\n } else if (\n !BrowserUtils.isInIframe() ||\n this.config.system.allowRedirectInIframe\n ) {\n /*\n * Returned from authority using redirect - need to perform navigation before processing response\n * Cache the hash to be retrieved after the next redirect\n */\n this.browserStorage.setTemporaryCache(\n TemporaryCacheKeys.URL_HASH,\n responseString,\n true\n );\n const navigationOptions: NavigationOptions = {\n apiId: ApiId.handleRedirectPromise,\n timeout: this.config.system.redirectNavigationTimeout,\n noHistory: true,\n };\n\n /**\n * Default behavior is to redirect to the start page and not process the hash now.\n * The start page is expected to also call handleRedirectPromise which will process the hash in one of the checks above.\n */\n let processHashOnRedirect: boolean = true;\n if (!loginRequestUrl || loginRequestUrl === \"null\") {\n // Redirect to home page if login request url is null (real null or the string null)\n const homepage = BrowserUtils.getHomepage();\n // Cache the homepage under ORIGIN_URI to ensure cached hash is processed on homepage\n this.browserStorage.setTemporaryCache(\n TemporaryCacheKeys.ORIGIN_URI,\n homepage,\n true\n );\n this.logger.warning(\n \"Unable to get valid login request url from cache, redirecting to home page\"\n );\n processHashOnRedirect =\n await this.navigationClient.navigateInternal(\n homepage,\n navigationOptions\n );\n } else {\n // Navigate to page that initiated the redirect request\n this.logger.verbose(\n `Navigating to loginRequestUrl: ${loginRequestUrl}`\n );\n processHashOnRedirect =\n await this.navigationClient.navigateInternal(\n loginRequestUrl,\n navigationOptions\n );\n }\n\n // If navigateInternal implementation returns false, handle the hash now\n if (!processHashOnRedirect) {\n return await this.handleResponse(\n serverParams,\n request,\n pkceVerifier,\n serverTelemetryManager\n );\n }\n }\n\n return null;\n } catch (e) {\n if (e instanceof AuthError) {\n (e as AuthError).setCorrelationId(this.correlationId);\n serverTelemetryManager.cacheFailedRequest(e);\n }\n throw e;\n }\n }\n\n /**\n * Gets the response hash for a redirect request\n * Returns null if interactionType in the state value is not \"redirect\" or the hash does not contain known properties\n * @param hash\n */\n protected getRedirectResponse(\n userProvidedResponse: string\n ): [AuthorizeResponse | null, string] {\n this.logger.verbose(\"getRedirectResponseHash called\");\n // Get current location hash from window or cache.\n let responseString = userProvidedResponse;\n if (!responseString) {\n if (\n this.config.auth.OIDCOptions.serverResponseType ===\n ServerResponseType.QUERY\n ) {\n responseString = window.location.search;\n } else {\n responseString = window.location.hash;\n }\n }\n let response = UrlUtils.getDeserializedResponse(responseString);\n\n if (response) {\n try {\n ResponseHandler.validateInteractionType(\n response,\n this.browserCrypto,\n InteractionType.Redirect\n );\n } catch (e) {\n if (e instanceof AuthError) {\n this.logger.error(\n `Interaction type validation failed due to ${e.errorCode}: ${e.errorMessage}`\n );\n }\n return [null, \"\"];\n }\n\n BrowserUtils.clearHash(window);\n this.logger.verbose(\n \"Hash contains known properties, returning response hash\"\n );\n return [response, responseString];\n }\n\n const cachedHash = this.browserStorage.getTemporaryCache(\n TemporaryCacheKeys.URL_HASH,\n true\n );\n this.browserStorage.removeItem(\n this.browserStorage.generateCacheKey(TemporaryCacheKeys.URL_HASH)\n );\n\n if (cachedHash) {\n response = UrlUtils.getDeserializedResponse(cachedHash);\n if (response) {\n this.logger.verbose(\n \"Hash does not contain known properties, returning cached hash\"\n );\n return [response, cachedHash];\n }\n }\n\n return [null, \"\"];\n }\n\n /**\n * Checks if hash exists and handles in window.\n * @param hash\n * @param state\n */\n protected async handleResponse(\n serverParams: AuthorizeResponse,\n request: CommonAuthorizationUrlRequest,\n codeVerifier: string,\n serverTelemetryManager: ServerTelemetryManager\n ): Promise {\n const state = serverParams.state;\n if (!state) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.noStateInHash);\n }\n\n if (serverParams.ear_jwe) {\n const discoveredAuthority = await invokeAsync(\n this.getDiscoveredAuthority.bind(this),\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\n this.logger,\n this.performanceClient,\n request.correlationId\n )({\n requestAuthority: request.authority,\n requestAzureCloudOptions: request.azureCloudOptions,\n requestExtraQueryParameters: request.extraQueryParameters,\n account: request.account,\n });\n return invokeAsync(\n Authorize.handleResponseEAR,\n PerformanceEvents.HandleResponseEar,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(\n request,\n serverParams,\n ApiId.acquireTokenRedirect,\n this.config,\n discoveredAuthority,\n this.browserStorage,\n this.nativeStorage,\n this.eventHandler,\n this.logger,\n this.performanceClient,\n this.platformAuthProvider\n );\n }\n\n const authClient = await invokeAsync(\n this.createAuthCodeClient.bind(this),\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\n this.logger,\n this.performanceClient,\n this.correlationId\n )({ serverTelemetryManager, requestAuthority: request.authority });\n return invokeAsync(\n Authorize.handleResponseCode,\n PerformanceEvents.HandleResponseCode,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(\n request,\n serverParams,\n codeVerifier,\n ApiId.acquireTokenRedirect,\n this.config,\n authClient,\n this.browserStorage,\n this.nativeStorage,\n this.eventHandler,\n this.logger,\n this.performanceClient,\n this.platformAuthProvider\n );\n }\n\n /**\n * Redirects window to given URL.\n * @param urlNavigate\n * @param onRedirectNavigateRequest - onRedirectNavigate callback provided on the request\n */\n async initiateAuthRequest(\n requestUrl: string,\n onRedirectNavigateRequest?: (url: string) => boolean | void\n ): Promise {\n this.logger.verbose(\"RedirectHandler.initiateAuthRequest called\");\n // Navigate if valid URL\n if (requestUrl) {\n this.logger.infoPii(\n `RedirectHandler.initiateAuthRequest: Navigate to: ${requestUrl}`\n );\n const navigationOptions: NavigationOptions = {\n apiId: ApiId.acquireTokenRedirect,\n timeout: this.config.system.redirectNavigationTimeout,\n noHistory: false,\n };\n\n const onRedirectNavigate =\n onRedirectNavigateRequest ||\n this.config.auth.onRedirectNavigate;\n\n // If onRedirectNavigate is implemented, invoke it and provide requestUrl\n if (typeof onRedirectNavigate === \"function\") {\n this.logger.verbose(\n \"RedirectHandler.initiateAuthRequest: Invoking onRedirectNavigate callback\"\n );\n const navigate = onRedirectNavigate(requestUrl);\n\n // Returning false from onRedirectNavigate will stop navigation\n if (navigate !== false) {\n this.logger.verbose(\n \"RedirectHandler.initiateAuthRequest: onRedirectNavigate did not return false, navigating\"\n );\n await this.navigationClient.navigateExternal(\n requestUrl,\n navigationOptions\n );\n return;\n } else {\n this.logger.verbose(\n \"RedirectHandler.initiateAuthRequest: onRedirectNavigate returned false, stopping navigation\"\n );\n return;\n }\n } else {\n // Navigate window to request URL\n this.logger.verbose(\n \"RedirectHandler.initiateAuthRequest: Navigating window to navigate url\"\n );\n await this.navigationClient.navigateExternal(\n requestUrl,\n navigationOptions\n );\n return;\n }\n } else {\n // Throw error if request URL is empty.\n this.logger.info(\n \"RedirectHandler.initiateAuthRequest: Navigate url is empty\"\n );\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.emptyNavigateUri\n );\n }\n }\n\n /**\n * Use to log out the current user, and redirect the user to the postLogoutRedirectUri.\n * Default behaviour is to redirect the user to `window.location.href`.\n * @param logoutRequest\n */\n async logout(logoutRequest?: EndSessionRequest): Promise {\n this.logger.verbose(\"logoutRedirect called\");\n const validLogoutRequest = this.initializeLogoutRequest(logoutRequest);\n const serverTelemetryManager = this.initializeServerTelemetryManager(\n ApiId.logout\n );\n\n try {\n this.eventHandler.emitEvent(\n EventType.LOGOUT_START,\n InteractionType.Redirect,\n logoutRequest\n );\n\n // Clear cache on logout\n await this.clearCacheOnLogout(\n this.correlationId,\n validLogoutRequest.account\n );\n\n const navigationOptions: NavigationOptions = {\n apiId: ApiId.logout,\n timeout: this.config.system.redirectNavigationTimeout,\n noHistory: false,\n };\n\n const authClient = await invokeAsync(\n this.createAuthCodeClient.bind(this),\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\n this.logger,\n this.performanceClient,\n this.correlationId\n )({\n serverTelemetryManager,\n requestAuthority: logoutRequest && logoutRequest.authority,\n requestExtraQueryParameters:\n logoutRequest?.extraQueryParameters,\n account: (logoutRequest && logoutRequest.account) || undefined,\n });\n\n if (authClient.authority.protocolMode === ProtocolMode.OIDC) {\n try {\n authClient.authority.endSessionEndpoint;\n } catch {\n if (validLogoutRequest.account?.homeAccountId) {\n this.eventHandler.emitEvent(\n EventType.LOGOUT_SUCCESS,\n InteractionType.Redirect,\n validLogoutRequest\n );\n\n return;\n }\n }\n }\n\n // Create logout string and navigate user window to logout.\n const logoutUri: string =\n authClient.getLogoutUri(validLogoutRequest);\n\n this.eventHandler.emitEvent(\n EventType.LOGOUT_SUCCESS,\n InteractionType.Redirect,\n validLogoutRequest\n );\n // Check if onRedirectNavigate is implemented, and invoke it if so\n if (\n logoutRequest &&\n typeof logoutRequest.onRedirectNavigate === \"function\"\n ) {\n const navigate = logoutRequest.onRedirectNavigate(logoutUri);\n\n if (navigate !== false) {\n this.logger.verbose(\n \"Logout onRedirectNavigate did not return false, navigating\"\n );\n // Ensure interaction is in progress\n if (!this.browserStorage.getInteractionInProgress()) {\n this.browserStorage.setInteractionInProgress(\n true,\n INTERACTION_TYPE.SIGNOUT\n );\n }\n await this.navigationClient.navigateExternal(\n logoutUri,\n navigationOptions\n );\n return;\n } else {\n // Ensure interaction is not in progress\n this.browserStorage.setInteractionInProgress(false);\n this.logger.verbose(\n \"Logout onRedirectNavigate returned false, stopping navigation\"\n );\n }\n } else {\n // Ensure interaction is in progress\n if (!this.browserStorage.getInteractionInProgress()) {\n this.browserStorage.setInteractionInProgress(\n true,\n INTERACTION_TYPE.SIGNOUT\n );\n }\n await this.navigationClient.navigateExternal(\n logoutUri,\n navigationOptions\n );\n return;\n }\n } catch (e) {\n if (e instanceof AuthError) {\n (e as AuthError).setCorrelationId(this.correlationId);\n serverTelemetryManager.cacheFailedRequest(e);\n }\n this.eventHandler.emitEvent(\n EventType.LOGOUT_FAILURE,\n InteractionType.Redirect,\n null,\n e as EventError\n );\n this.eventHandler.emitEvent(\n EventType.LOGOUT_END,\n InteractionType.Redirect\n );\n throw e;\n }\n\n this.eventHandler.emitEvent(\n EventType.LOGOUT_END,\n InteractionType.Redirect\n );\n }\n\n /**\n * Use to get the redirectStartPage either from request or use current window\n * @param requestStartPage\n */\n protected getRedirectStartPage(requestStartPage?: string): string {\n const redirectStartPage = requestStartPage || window.location.href;\n return UrlString.getAbsoluteUrl(\n redirectStartPage,\n BrowserUtils.getCurrentUri()\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n Logger,\n IPerformanceClient,\n PerformanceEvents,\n invokeAsync,\n invoke,\n ServerResponseType,\n Authority,\n CommonAuthorizationUrlRequest,\n} from \"@azure/msal-common/browser\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport {\n BrowserConfiguration,\n DEFAULT_IFRAME_TIMEOUT_MS,\n} from \"../config/Configuration.js\";\nimport { getCodeForm, getEARForm } from \"../protocol/Authorize.js\";\n\n/**\n * Creates a hidden iframe to given URL using user-requested scopes as an id.\n * @param urlNavigate\n * @param userRequestScopes\n */\nexport async function initiateCodeRequest(\n requestUrl: string,\n performanceClient: IPerformanceClient,\n logger: Logger,\n correlationId: string,\n navigateFrameWait?: number\n): Promise {\n performanceClient.addQueueMeasurement(\n PerformanceEvents.SilentHandlerInitiateAuthRequest,\n correlationId\n );\n\n if (!requestUrl) {\n // Throw error if request URL is empty.\n logger.info(\"Navigate url is empty\");\n throw createBrowserAuthError(BrowserAuthErrorCodes.emptyNavigateUri);\n }\n if (navigateFrameWait) {\n return invokeAsync(\n loadFrame,\n PerformanceEvents.SilentHandlerLoadFrame,\n logger,\n performanceClient,\n correlationId\n )(requestUrl, navigateFrameWait, performanceClient, correlationId);\n }\n return invoke(\n loadFrameSync,\n PerformanceEvents.SilentHandlerLoadFrameSync,\n logger,\n performanceClient,\n correlationId\n )(requestUrl);\n}\n\nexport async function initiateCodeFlowWithPost(\n config: BrowserConfiguration,\n authority: Authority,\n request: CommonAuthorizationUrlRequest,\n logger: Logger,\n performanceClient: IPerformanceClient\n): Promise {\n const frame = createHiddenIframe();\n if (!frame.contentDocument) {\n throw \"No document associated with iframe!\";\n }\n const form = await getCodeForm(\n frame.contentDocument,\n config,\n authority,\n request,\n logger,\n performanceClient\n );\n form.submit();\n return frame;\n}\n\nexport async function initiateEarRequest(\n config: BrowserConfiguration,\n authority: Authority,\n request: CommonAuthorizationUrlRequest,\n logger: Logger,\n performanceClient: IPerformanceClient\n): Promise {\n const frame = createHiddenIframe();\n if (!frame.contentDocument) {\n throw \"No document associated with iframe!\";\n }\n const form = await getEARForm(\n frame.contentDocument,\n config,\n authority,\n request,\n logger,\n performanceClient\n );\n form.submit();\n return frame;\n}\n\n/**\n * Monitors an iframe content window until it loads a url with a known hash, or hits a specified timeout.\n * @param iframe\n * @param timeout\n */\nexport async function monitorIframeForHash(\n iframe: HTMLIFrameElement,\n timeout: number,\n pollIntervalMilliseconds: number,\n performanceClient: IPerformanceClient,\n logger: Logger,\n correlationId: string,\n responseType: ServerResponseType\n): Promise {\n performanceClient.addQueueMeasurement(\n PerformanceEvents.SilentHandlerMonitorIframeForHash,\n correlationId\n );\n\n return new Promise((resolve, reject) => {\n if (timeout < DEFAULT_IFRAME_TIMEOUT_MS) {\n logger.warning(\n `system.loadFrameTimeout or system.iframeHashTimeout set to lower (${timeout}ms) than the default (${DEFAULT_IFRAME_TIMEOUT_MS}ms). This may result in timeouts.`\n );\n }\n\n /*\n * Polling for iframes can be purely timing based,\n * since we don't need to account for interaction.\n */\n const timeoutId = window.setTimeout(() => {\n window.clearInterval(intervalId);\n reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.monitorWindowTimeout\n )\n );\n }, timeout);\n\n const intervalId = window.setInterval(() => {\n let href: string = \"\";\n const contentWindow = iframe.contentWindow;\n try {\n /*\n * Will throw if cross origin,\n * which should be caught and ignored\n * since we need the interval to keep running while on STS UI.\n */\n href = contentWindow ? contentWindow.location.href : \"\";\n } catch (e) {}\n\n if (!href || href === \"about:blank\") {\n return;\n }\n\n let responseString = \"\";\n if (contentWindow) {\n if (responseType === ServerResponseType.QUERY) {\n responseString = contentWindow.location.search;\n } else {\n responseString = contentWindow.location.hash;\n }\n }\n window.clearTimeout(timeoutId);\n window.clearInterval(intervalId);\n resolve(responseString);\n }, pollIntervalMilliseconds);\n }).finally(() => {\n invoke(\n removeHiddenIframe,\n PerformanceEvents.RemoveHiddenIframe,\n logger,\n performanceClient,\n correlationId\n )(iframe);\n });\n}\n\n/**\n * @hidden\n * Loads iframe with authorization endpoint URL\n * @ignore\n * @deprecated\n */\nfunction loadFrame(\n urlNavigate: string,\n navigateFrameWait: number,\n performanceClient: IPerformanceClient,\n correlationId: string\n): Promise {\n performanceClient.addQueueMeasurement(\n PerformanceEvents.SilentHandlerLoadFrame,\n correlationId\n );\n\n /*\n * This trick overcomes iframe navigation in IE\n * IE does not load the page consistently in iframe\n */\n\n return new Promise((resolve, reject) => {\n const frameHandle = createHiddenIframe();\n\n window.setTimeout(() => {\n if (!frameHandle) {\n reject(\"Unable to load iframe\");\n return;\n }\n\n frameHandle.src = urlNavigate;\n\n resolve(frameHandle);\n }, navigateFrameWait);\n });\n}\n/**\n * @hidden\n * Loads the iframe synchronously when the navigateTimeFrame is set to `0`\n * @param urlNavigate\n * @param frameName\n * @param logger\n */\nfunction loadFrameSync(urlNavigate: string): HTMLIFrameElement {\n const frameHandle = createHiddenIframe();\n\n frameHandle.src = urlNavigate;\n\n return frameHandle;\n}\n\n/**\n * @hidden\n * Creates a new hidden iframe or gets an existing one for silent token renewal.\n * @ignore\n */\nfunction createHiddenIframe(): HTMLIFrameElement {\n const authFrame = document.createElement(\"iframe\");\n\n authFrame.className = \"msalSilentIframe\";\n authFrame.style.visibility = \"hidden\";\n authFrame.style.position = \"absolute\";\n authFrame.style.width = authFrame.style.height = \"0\";\n authFrame.style.border = \"0\";\n authFrame.setAttribute(\n \"sandbox\",\n \"allow-scripts allow-same-origin allow-forms\"\n );\n document.body.appendChild(authFrame);\n\n return authFrame;\n}\n\n/**\n * @hidden\n * Removes a hidden iframe from the page.\n * @ignore\n */\nfunction removeHiddenIframe(iframe: HTMLIFrameElement): void {\n if (document.body === iframe.parentNode) {\n document.body.removeChild(iframe);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ICrypto,\n Logger,\n PromptValue,\n AuthorizationCodeClient,\n AuthError,\n IPerformanceClient,\n PerformanceEvents,\n invokeAsync,\n invoke,\n ProtocolMode,\n CommonAuthorizationUrlRequest,\n HttpMethod,\n} from \"@azure/msal-common/browser\";\nimport { StandardInteractionClient } from \"./StandardInteractionClient.js\";\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\nimport { EventHandler } from \"../event/EventHandler.js\";\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport {\n InteractionType,\n ApiId,\n BrowserConstants,\n} from \"../utils/BrowserConstants.js\";\nimport {\n initiateCodeRequest,\n initiateCodeFlowWithPost,\n initiateEarRequest,\n monitorIframeForHash,\n} from \"../interaction_handler/SilentHandler.js\";\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\nimport * as ResponseHandler from \"../response/ResponseHandler.js\";\nimport * as Authorize from \"../protocol/Authorize.js\";\nimport { generatePkceCodes } from \"../crypto/PkceGenerator.js\";\nimport { isPlatformAuthAllowed } from \"../broker/nativeBroker/PlatformAuthProvider.js\";\nimport { generateEarKey } from \"../crypto/BrowserCrypto.js\";\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\n\nexport class SilentIframeClient extends StandardInteractionClient {\n protected apiId: ApiId;\n protected nativeStorage: BrowserCacheManager;\n\n constructor(\n config: BrowserConfiguration,\n storageImpl: BrowserCacheManager,\n browserCrypto: ICrypto,\n logger: Logger,\n eventHandler: EventHandler,\n navigationClient: INavigationClient,\n apiId: ApiId,\n performanceClient: IPerformanceClient,\n nativeStorageImpl: BrowserCacheManager,\n platformAuthProvider?: IPlatformAuthHandler,\n correlationId?: string\n ) {\n super(\n config,\n storageImpl,\n browserCrypto,\n logger,\n eventHandler,\n navigationClient,\n performanceClient,\n platformAuthProvider,\n correlationId\n );\n this.apiId = apiId;\n this.nativeStorage = nativeStorageImpl;\n }\n\n /**\n * Acquires a token silently by opening a hidden iframe to the /authorize endpoint with prompt=none or prompt=no_session\n * @param request\n */\n async acquireToken(\n request: SsoSilentRequest\n ): Promise {\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.SilentIframeClientAcquireToken,\n request.correlationId\n );\n // Check that we have some SSO data\n if (\n !request.loginHint &&\n !request.sid &&\n (!request.account || !request.account.username)\n ) {\n this.logger.warning(\n \"No user hint provided. The authorization server may need more information to complete this request.\"\n );\n }\n\n // Check the prompt value\n const inputRequest = { ...request };\n if (inputRequest.prompt) {\n if (\n inputRequest.prompt !== PromptValue.NONE &&\n inputRequest.prompt !== PromptValue.NO_SESSION\n ) {\n this.logger.warning(\n `SilentIframeClient. Replacing invalid prompt ${inputRequest.prompt} with ${PromptValue.NONE}`\n );\n inputRequest.prompt = PromptValue.NONE;\n }\n } else {\n inputRequest.prompt = PromptValue.NONE;\n }\n\n // Create silent request\n const silentRequest: CommonAuthorizationUrlRequest = await invokeAsync(\n this.initializeAuthorizationRequest.bind(this),\n PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(inputRequest, InteractionType.Silent);\n silentRequest.platformBroker = isPlatformAuthAllowed(\n this.config,\n this.logger,\n this.platformAuthProvider,\n silentRequest.authenticationScheme\n );\n BrowserUtils.preconnect(silentRequest.authority);\n\n if (this.config.auth.protocolMode === ProtocolMode.EAR) {\n return this.executeEarFlow(silentRequest);\n } else {\n return this.executeCodeFlow(silentRequest);\n }\n }\n\n /**\n * Executes auth code + PKCE flow\n * @param request\n * @returns\n */\n async executeCodeFlow(\n request: CommonAuthorizationUrlRequest\n ): Promise {\n let authClient: AuthorizationCodeClient | undefined;\n const serverTelemetryManager = this.initializeServerTelemetryManager(\n this.apiId\n );\n\n try {\n // Initialize the client\n authClient = await invokeAsync(\n this.createAuthCodeClient.bind(this),\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\n this.logger,\n this.performanceClient,\n request.correlationId\n )({\n serverTelemetryManager,\n requestAuthority: request.authority,\n requestAzureCloudOptions: request.azureCloudOptions,\n requestExtraQueryParameters: request.extraQueryParameters,\n account: request.account,\n });\n\n return await invokeAsync(\n this.silentTokenHelper.bind(this),\n PerformanceEvents.SilentIframeClientTokenHelper,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(authClient, request);\n } catch (e) {\n if (e instanceof AuthError) {\n (e as AuthError).setCorrelationId(this.correlationId);\n serverTelemetryManager.cacheFailedRequest(e);\n }\n\n if (\n !authClient ||\n !(e instanceof AuthError) ||\n e.errorCode !== BrowserConstants.INVALID_GRANT_ERROR\n ) {\n throw e;\n }\n\n this.performanceClient.addFields(\n {\n retryError: e.errorCode,\n },\n this.correlationId\n );\n\n return await invokeAsync(\n this.silentTokenHelper.bind(this),\n PerformanceEvents.SilentIframeClientTokenHelper,\n this.logger,\n this.performanceClient,\n this.correlationId\n )(authClient, request);\n }\n }\n\n /**\n * Executes EAR flow\n * @param request\n */\n async executeEarFlow(\n request: CommonAuthorizationUrlRequest\n ): Promise {\n const correlationId = request.correlationId;\n const discoveredAuthority = await invokeAsync(\n this.getDiscoveredAuthority.bind(this),\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\n this.logger,\n this.performanceClient,\n correlationId\n )({\n requestAuthority: request.authority,\n requestAzureCloudOptions: request.azureCloudOptions,\n requestExtraQueryParameters: request.extraQueryParameters,\n account: request.account,\n });\n\n const earJwk = await invokeAsync(\n generateEarKey,\n PerformanceEvents.GenerateEarKey,\n this.logger,\n this.performanceClient,\n correlationId\n )();\n const silentRequest = {\n ...request,\n earJwk: earJwk,\n };\n const msalFrame = await invokeAsync(\n initiateEarRequest,\n PerformanceEvents.SilentHandlerInitiateAuthRequest,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n this.config,\n discoveredAuthority,\n silentRequest,\n this.logger,\n this.performanceClient\n );\n\n const responseType = this.config.auth.OIDCOptions.serverResponseType;\n // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.\n const responseString = await invokeAsync(\n monitorIframeForHash,\n PerformanceEvents.SilentHandlerMonitorIframeForHash,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n msalFrame,\n this.config.system.iframeHashTimeout,\n this.config.system.pollIntervalMilliseconds,\n this.performanceClient,\n this.logger,\n correlationId,\n responseType\n );\n\n const serverParams = invoke(\n ResponseHandler.deserializeResponse,\n PerformanceEvents.DeserializeResponse,\n this.logger,\n this.performanceClient,\n correlationId\n )(responseString, responseType, this.logger);\n\n return invokeAsync(\n Authorize.handleResponseEAR,\n PerformanceEvents.HandleResponseEar,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n silentRequest,\n serverParams,\n this.apiId,\n this.config,\n discoveredAuthority,\n this.browserStorage,\n this.nativeStorage,\n this.eventHandler,\n this.logger,\n this.performanceClient,\n this.platformAuthProvider\n );\n }\n\n /**\n * Currently Unsupported\n */\n logout(): Promise {\n // Synchronous so we must reject\n return Promise.reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.silentLogoutUnsupported\n )\n );\n }\n\n /**\n * Helper which acquires an authorization code silently using a hidden iframe from given url\n * using the scopes requested as part of the id, and exchanges the code for a set of OAuth tokens.\n * @param navigateUrl\n * @param userRequestScopes\n */\n protected async silentTokenHelper(\n authClient: AuthorizationCodeClient,\n request: CommonAuthorizationUrlRequest\n ): Promise {\n const correlationId = request.correlationId;\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.SilentIframeClientTokenHelper,\n correlationId\n );\n const pkceCodes = await invokeAsync(\n generatePkceCodes,\n PerformanceEvents.GeneratePkceCodes,\n this.logger,\n this.performanceClient,\n correlationId\n )(this.performanceClient, this.logger, correlationId);\n\n const silentRequest = {\n ...request,\n codeChallenge: pkceCodes.challenge,\n };\n\n let msalFrame: HTMLIFrameElement;\n\n if (request.httpMethod === HttpMethod.POST) {\n msalFrame = await invokeAsync(\n initiateCodeFlowWithPost,\n PerformanceEvents.SilentHandlerInitiateAuthRequest,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n this.config,\n authClient.authority,\n silentRequest,\n this.logger,\n this.performanceClient\n );\n } else {\n // Create authorize request url\n const navigateUrl = await invokeAsync(\n Authorize.getAuthCodeRequestUrl,\n PerformanceEvents.GetAuthCodeUrl,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n this.config,\n authClient.authority,\n silentRequest,\n this.logger,\n this.performanceClient\n );\n\n // Get the frame handle for the silent request\n msalFrame = await invokeAsync(\n initiateCodeRequest,\n PerformanceEvents.SilentHandlerInitiateAuthRequest,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n navigateUrl,\n this.performanceClient,\n this.logger,\n correlationId,\n this.config.system.navigateFrameWait\n );\n }\n\n const responseType = this.config.auth.OIDCOptions.serverResponseType;\n // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.\n const responseString = await invokeAsync(\n monitorIframeForHash,\n PerformanceEvents.SilentHandlerMonitorIframeForHash,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n msalFrame,\n this.config.system.iframeHashTimeout,\n this.config.system.pollIntervalMilliseconds,\n this.performanceClient,\n this.logger,\n correlationId,\n responseType\n );\n const serverParams = invoke(\n ResponseHandler.deserializeResponse,\n PerformanceEvents.DeserializeResponse,\n this.logger,\n this.performanceClient,\n correlationId\n )(responseString, responseType, this.logger);\n\n return invokeAsync(\n Authorize.handleResponseCode,\n PerformanceEvents.HandleResponseCode,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n request,\n serverParams,\n pkceCodes.verifier,\n this.apiId,\n this.config,\n authClient,\n this.browserStorage,\n this.nativeStorage,\n this.eventHandler,\n this.logger,\n this.performanceClient,\n this.platformAuthProvider\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { StandardInteractionClient } from \"./StandardInteractionClient.js\";\nimport {\n CommonSilentFlowRequest,\n ServerTelemetryManager,\n RefreshTokenClient,\n AuthError,\n AzureCloudOptions,\n PerformanceEvents,\n invokeAsync,\n AccountInfo,\n StringDict,\n} from \"@azure/msal-common/browser\";\nimport { ApiId } from \"../utils/BrowserConstants.js\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { initializeBaseRequest } from \"../request/RequestHelpers.js\";\n\nexport class SilentRefreshClient extends StandardInteractionClient {\n /**\n * Exchanges the refresh token for new tokens\n * @param request\n */\n async acquireToken(\n request: CommonSilentFlowRequest\n ): Promise {\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.SilentRefreshClientAcquireToken,\n request.correlationId\n );\n\n const baseRequest = await invokeAsync(\n initializeBaseRequest,\n PerformanceEvents.InitializeBaseRequest,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request, this.config, this.performanceClient, this.logger);\n const silentRequest: CommonSilentFlowRequest = {\n ...request,\n ...baseRequest,\n };\n\n if (request.redirectUri) {\n // Make sure any passed redirectUri is converted to an absolute URL - redirectUri is not a required parameter for refresh token redemption so only include if explicitly provided\n silentRequest.redirectUri = this.getRedirectUri(\n request.redirectUri\n );\n }\n\n const serverTelemetryManager = this.initializeServerTelemetryManager(\n ApiId.acquireTokenSilent_silentFlow\n );\n\n const refreshTokenClient = await this.createRefreshTokenClient({\n serverTelemetryManager,\n authorityUrl: silentRequest.authority,\n azureCloudOptions: silentRequest.azureCloudOptions,\n account: silentRequest.account,\n });\n // Send request to renew token. Auth module will throw errors if token cannot be renewed.\n return invokeAsync(\n refreshTokenClient.acquireTokenByRefreshToken.bind(\n refreshTokenClient\n ),\n PerformanceEvents.RefreshTokenClientAcquireTokenByRefreshToken,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(silentRequest).catch((e: AuthError) => {\n (e as AuthError).setCorrelationId(this.correlationId);\n serverTelemetryManager.cacheFailedRequest(e);\n throw e;\n }) as Promise;\n }\n\n /**\n * Currently Unsupported\n */\n logout(): Promise {\n // Synchronous so we must reject\n return Promise.reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.silentLogoutUnsupported\n )\n );\n }\n\n /**\n * Creates a Refresh Client with the given authority, or the default authority.\n * @param params {\n * serverTelemetryManager: ServerTelemetryManager;\n * authorityUrl?: string;\n * azureCloudOptions?: AzureCloudOptions;\n * extraQueryParams?: StringDict;\n * account?: AccountInfo;\n * }\n */\n protected async createRefreshTokenClient(params: {\n serverTelemetryManager: ServerTelemetryManager;\n authorityUrl?: string;\n azureCloudOptions?: AzureCloudOptions;\n extraQueryParameters?: StringDict;\n account?: AccountInfo;\n }): Promise {\n // Create auth module.\n const clientConfig = await invokeAsync(\n this.getClientConfiguration.bind(this),\n PerformanceEvents.StandardInteractionClientGetClientConfiguration,\n this.logger,\n this.performanceClient,\n this.correlationId\n )({\n serverTelemetryManager: params.serverTelemetryManager,\n requestAuthority: params.authorityUrl,\n requestAzureCloudOptions: params.azureCloudOptions,\n requestExtraQueryParameters: params.extraQueryParameters,\n account: params.account,\n });\n return new RefreshTokenClient(clientConfig, this.performanceClient);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n AccessTokenEntity,\n ICrypto,\n IdTokenEntity,\n Logger,\n ScopeSet,\n Authority,\n AuthorityOptions,\n ExternalTokenResponse,\n AccountEntity,\n AuthToken,\n RefreshTokenEntity,\n CacheRecord,\n TokenClaims,\n CacheHelpers,\n buildAccountToCache,\n TimeUtils,\n} from \"@azure/msal-common/browser\";\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\nimport type { SilentRequest } from \"../request/SilentRequest.js\";\nimport { BrowserCacheManager } from \"./BrowserCacheManager.js\";\nimport type { ITokenCache } from \"./ITokenCache.js\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport type { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { base64Decode } from \"../encode/Base64Decode.js\";\nimport * as BrowserCrypto from \"../crypto/BrowserCrypto.js\";\n\nexport type LoadTokenOptions = {\n clientInfo?: string;\n expiresOn?: number;\n extendedExpiresOn?: number;\n};\n\n/**\n * Token cache manager\n */\nexport class TokenCache implements ITokenCache {\n // Flag to indicate if in browser environment\n public isBrowserEnvironment: boolean;\n // Input configuration by developer/user\n protected config: BrowserConfiguration;\n // Browser cache storage\n private storage: BrowserCacheManager;\n // Logger\n private logger: Logger;\n // Crypto class\n private cryptoObj: ICrypto;\n\n constructor(\n configuration: BrowserConfiguration,\n storage: BrowserCacheManager,\n logger: Logger,\n cryptoObj: ICrypto\n ) {\n this.isBrowserEnvironment = typeof window !== \"undefined\";\n this.config = configuration;\n this.storage = storage;\n this.logger = logger;\n this.cryptoObj = cryptoObj;\n }\n\n // Move getAllAccounts here and cache utility APIs\n\n /**\n * API to load tokens to msal-browser cache.\n * @param request\n * @param response\n * @param options\n * @returns `AuthenticationResult` for the response that was loaded.\n */\n async loadExternalTokens(\n request: SilentRequest,\n response: ExternalTokenResponse,\n options: LoadTokenOptions\n ): Promise {\n if (!this.isBrowserEnvironment) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.nonBrowserEnvironment\n );\n }\n\n const correlationId =\n request.correlationId || BrowserCrypto.createNewGuid();\n\n const idTokenClaims = response.id_token\n ? AuthToken.extractTokenClaims(response.id_token, base64Decode)\n : undefined;\n\n const authorityOptions: AuthorityOptions = {\n protocolMode: this.config.auth.protocolMode,\n knownAuthorities: this.config.auth.knownAuthorities,\n cloudDiscoveryMetadata: this.config.auth.cloudDiscoveryMetadata,\n authorityMetadata: this.config.auth.authorityMetadata,\n skipAuthorityMetadataCache:\n this.config.auth.skipAuthorityMetadataCache,\n };\n const authority = request.authority\n ? new Authority(\n Authority.generateAuthority(\n request.authority,\n request.azureCloudOptions\n ),\n this.config.system.networkClient,\n this.storage,\n authorityOptions,\n this.logger,\n request.correlationId || BrowserCrypto.createNewGuid()\n )\n : undefined;\n\n const cacheRecordAccount: AccountEntity = await this.loadAccount(\n request,\n options.clientInfo || response.client_info || \"\",\n correlationId,\n idTokenClaims,\n authority\n );\n\n const idToken = await this.loadIdToken(\n response,\n cacheRecordAccount.homeAccountId,\n cacheRecordAccount.environment,\n cacheRecordAccount.realm,\n correlationId\n );\n\n const accessToken = await this.loadAccessToken(\n request,\n response,\n cacheRecordAccount.homeAccountId,\n cacheRecordAccount.environment,\n cacheRecordAccount.realm,\n options,\n correlationId\n );\n\n const refreshToken = await this.loadRefreshToken(\n response,\n cacheRecordAccount.homeAccountId,\n cacheRecordAccount.environment,\n correlationId\n );\n\n return this.generateAuthenticationResult(\n request,\n {\n account: cacheRecordAccount,\n idToken,\n accessToken,\n refreshToken,\n },\n idTokenClaims,\n authority\n );\n }\n\n /**\n * Helper function to load account to msal-browser cache\n * @param idToken\n * @param environment\n * @param clientInfo\n * @param authorityType\n * @param requestHomeAccountId\n * @returns `AccountEntity`\n */\n private async loadAccount(\n request: SilentRequest,\n clientInfo: string,\n correlationId: string,\n idTokenClaims?: TokenClaims,\n authority?: Authority\n ): Promise {\n this.logger.verbose(\"TokenCache - loading account\");\n\n if (request.account) {\n const accountEntity = AccountEntity.createFromAccountInfo(\n request.account\n );\n await this.storage.setAccount(accountEntity, correlationId);\n return accountEntity;\n } else if (!authority || (!clientInfo && !idTokenClaims)) {\n this.logger.error(\n \"TokenCache - if an account is not provided on the request, authority and either clientInfo or idToken must be provided instead.\"\n );\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.unableToLoadToken\n );\n }\n\n const homeAccountId = AccountEntity.generateHomeAccountId(\n clientInfo,\n authority.authorityType,\n this.logger,\n this.cryptoObj,\n idTokenClaims\n );\n\n const claimsTenantId = idTokenClaims?.tid;\n\n const cachedAccount = buildAccountToCache(\n this.storage,\n authority,\n homeAccountId,\n base64Decode,\n correlationId,\n idTokenClaims,\n clientInfo,\n authority.hostnameAndPort,\n claimsTenantId,\n undefined, // authCodePayload\n undefined, // nativeAccountId\n this.logger\n );\n\n await this.storage.setAccount(cachedAccount, correlationId);\n return cachedAccount;\n }\n\n /**\n * Helper function to load id tokens to msal-browser cache\n * @param idToken\n * @param homeAccountId\n * @param environment\n * @param tenantId\n * @returns `IdTokenEntity`\n */\n private async loadIdToken(\n response: ExternalTokenResponse,\n homeAccountId: string,\n environment: string,\n tenantId: string,\n correlationId: string\n ): Promise {\n if (!response.id_token) {\n this.logger.verbose(\"TokenCache - no id token found in response\");\n return null;\n }\n\n this.logger.verbose(\"TokenCache - loading id token\");\n const idTokenEntity = CacheHelpers.createIdTokenEntity(\n homeAccountId,\n environment,\n response.id_token,\n this.config.auth.clientId,\n tenantId\n );\n\n await this.storage.setIdTokenCredential(idTokenEntity, correlationId);\n return idTokenEntity;\n }\n\n /**\n * Helper function to load access tokens to msal-browser cache\n * @param request\n * @param response\n * @param homeAccountId\n * @param environment\n * @param tenantId\n * @returns `AccessTokenEntity`\n */\n private async loadAccessToken(\n request: SilentRequest,\n response: ExternalTokenResponse,\n homeAccountId: string,\n environment: string,\n tenantId: string,\n options: LoadTokenOptions,\n correlationId: string\n ): Promise {\n if (!response.access_token) {\n this.logger.verbose(\n \"TokenCache - no access token found in response\"\n );\n return null;\n } else if (!response.expires_in) {\n this.logger.error(\n \"TokenCache - no expiration set on the access token. Cannot add it to the cache.\"\n );\n return null;\n } else if (\n !response.scope &&\n (!request.scopes || !request.scopes.length)\n ) {\n this.logger.error(\n \"TokenCache - scopes not specified in the request or response. Cannot add token to the cache.\"\n );\n return null;\n }\n\n this.logger.verbose(\"TokenCache - loading access token\");\n\n const scopes = response.scope\n ? ScopeSet.fromString(response.scope)\n : new ScopeSet(request.scopes);\n const expiresOn =\n options.expiresOn || response.expires_in + TimeUtils.nowSeconds();\n\n const extendedExpiresOn =\n options.extendedExpiresOn ||\n (response.ext_expires_in || response.expires_in) +\n TimeUtils.nowSeconds();\n\n const accessTokenEntity = CacheHelpers.createAccessTokenEntity(\n homeAccountId,\n environment,\n response.access_token,\n this.config.auth.clientId,\n tenantId,\n scopes.printScopes(),\n expiresOn,\n extendedExpiresOn,\n base64Decode\n );\n\n await this.storage.setAccessTokenCredential(\n accessTokenEntity,\n correlationId\n );\n return accessTokenEntity;\n }\n\n /**\n * Helper function to load refresh tokens to msal-browser cache\n * @param request\n * @param response\n * @param homeAccountId\n * @param environment\n * @returns `RefreshTokenEntity`\n */\n private async loadRefreshToken(\n response: ExternalTokenResponse,\n homeAccountId: string,\n environment: string,\n correlationId: string\n ): Promise {\n if (!response.refresh_token) {\n this.logger.verbose(\n \"TokenCache - no refresh token found in response\"\n );\n return null;\n }\n\n this.logger.verbose(\"TokenCache - loading refresh token\");\n const refreshTokenEntity = CacheHelpers.createRefreshTokenEntity(\n homeAccountId,\n environment,\n response.refresh_token,\n this.config.auth.clientId,\n response.foci,\n undefined, // userAssertionHash\n response.refresh_token_expires_in\n );\n\n await this.storage.setRefreshTokenCredential(\n refreshTokenEntity,\n correlationId\n );\n return refreshTokenEntity;\n }\n\n /**\n * Helper function to generate an `AuthenticationResult` for the result.\n * @param request\n * @param idTokenObj\n * @param cacheRecord\n * @param authority\n * @returns `AuthenticationResult`\n */\n private generateAuthenticationResult(\n request: SilentRequest,\n cacheRecord: CacheRecord & { account: AccountEntity },\n idTokenClaims?: TokenClaims,\n authority?: Authority\n ): AuthenticationResult {\n let accessToken: string = \"\";\n let responseScopes: Array = [];\n let expiresOn: Date | null = null;\n let extExpiresOn: Date | undefined;\n\n if (cacheRecord?.accessToken) {\n accessToken = cacheRecord.accessToken.secret;\n responseScopes = ScopeSet.fromString(\n cacheRecord.accessToken.target\n ).asArray();\n // Access token expiresOn stored in seconds, converting to Date for AuthenticationResult\n expiresOn = TimeUtils.toDateFromSeconds(\n cacheRecord.accessToken.expiresOn\n );\n extExpiresOn = TimeUtils.toDateFromSeconds(\n cacheRecord.accessToken.extendedExpiresOn\n );\n }\n\n const accountEntity = cacheRecord.account;\n\n return {\n authority: authority ? authority.canonicalAuthority : \"\",\n uniqueId: cacheRecord.account.localAccountId,\n tenantId: cacheRecord.account.realm,\n scopes: responseScopes,\n account: accountEntity.getAccountInfo(),\n idToken: cacheRecord.idToken?.secret || \"\",\n idTokenClaims: idTokenClaims || {},\n accessToken: accessToken,\n fromCache: true,\n expiresOn: expiresOn,\n correlationId: request.correlationId || \"\",\n requestId: \"\",\n extExpiresOn: extExpiresOn,\n familyId: cacheRecord.refreshToken?.familyId || \"\",\n tokenType: cacheRecord?.accessToken?.tokenType || \"\",\n state: request.state || \"\",\n cloudGraphHostName: accountEntity.cloudGraphHostName || \"\",\n msGraphHost: accountEntity.msGraphHost || \"\",\n fromNativeBroker: false,\n };\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n AuthorizationCodeClient,\n ClientConfiguration,\n} from \"@azure/msal-common/browser\";\n\nexport class HybridSpaAuthorizationCodeClient extends AuthorizationCodeClient {\n constructor(config: ClientConfiguration) {\n super(config);\n this.includeRedirectUri = false;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n ICrypto,\n Logger,\n CommonAuthorizationCodeRequest,\n AuthError,\n IPerformanceClient,\n PerformanceEvents,\n invokeAsync,\n CommonAuthorizationUrlRequest,\n} from \"@azure/msal-common/browser\";\nimport { StandardInteractionClient } from \"./StandardInteractionClient.js\";\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\nimport { EventHandler } from \"../event/EventHandler.js\";\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport { InteractionType, ApiId } from \"../utils/BrowserConstants.js\";\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\nimport { HybridSpaAuthorizationCodeClient } from \"./HybridSpaAuthorizationCodeClient.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { InteractionHandler } from \"../interaction_handler/InteractionHandler.js\";\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\n\nexport class SilentAuthCodeClient extends StandardInteractionClient {\n private apiId: ApiId;\n\n constructor(\n config: BrowserConfiguration,\n storageImpl: BrowserCacheManager,\n browserCrypto: ICrypto,\n logger: Logger,\n eventHandler: EventHandler,\n navigationClient: INavigationClient,\n apiId: ApiId,\n performanceClient: IPerformanceClient,\n platformAuthProvider?: IPlatformAuthHandler,\n correlationId?: string\n ) {\n super(\n config,\n storageImpl,\n browserCrypto,\n logger,\n eventHandler,\n navigationClient,\n performanceClient,\n platformAuthProvider,\n correlationId\n );\n this.apiId = apiId;\n }\n\n /**\n * Acquires a token silently by redeeming an authorization code against the /token endpoint\n * @param request\n */\n async acquireToken(\n request: AuthorizationCodeRequest\n ): Promise {\n // Auth code payload is required\n if (!request.code) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.authCodeRequired\n );\n }\n\n // Create silent request\n const silentRequest: CommonAuthorizationUrlRequest = await invokeAsync(\n this.initializeAuthorizationRequest.bind(this),\n PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request, InteractionType.Silent);\n\n const serverTelemetryManager = this.initializeServerTelemetryManager(\n this.apiId\n );\n\n try {\n // Create auth code request (PKCE not needed)\n const authCodeRequest: CommonAuthorizationCodeRequest = {\n ...silentRequest,\n code: request.code,\n };\n\n // Initialize the client\n const clientConfig = await invokeAsync(\n this.getClientConfiguration.bind(this),\n PerformanceEvents.StandardInteractionClientGetClientConfiguration,\n this.logger,\n this.performanceClient,\n request.correlationId\n )({\n serverTelemetryManager,\n requestAuthority: silentRequest.authority,\n requestAzureCloudOptions: silentRequest.azureCloudOptions,\n requestExtraQueryParameters: silentRequest.extraQueryParameters,\n account: silentRequest.account,\n });\n const authClient: HybridSpaAuthorizationCodeClient =\n new HybridSpaAuthorizationCodeClient(clientConfig);\n this.logger.verbose(\"Auth code client created\");\n\n // Create silent handler\n const interactionHandler = new InteractionHandler(\n authClient,\n this.browserStorage,\n authCodeRequest,\n this.logger,\n this.performanceClient\n );\n\n // Handle auth code parameters from request\n return await invokeAsync(\n interactionHandler.handleCodeResponseFromServer.bind(\n interactionHandler\n ),\n PerformanceEvents.HandleCodeResponseFromServer,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(\n {\n code: request.code,\n msgraph_host: request.msGraphHost,\n cloud_graph_host_name: request.cloudGraphHostName,\n cloud_instance_host_name: request.cloudInstanceHostName,\n },\n silentRequest,\n false\n );\n } catch (e) {\n if (e instanceof AuthError) {\n (e as AuthError).setCorrelationId(this.correlationId);\n serverTelemetryManager.cacheFailedRequest(e);\n }\n throw e;\n }\n }\n\n /**\n * Currently Unsupported\n */\n logout(): Promise {\n // Synchronous so we must reject\n return Promise.reject(\n createBrowserAuthError(\n BrowserAuthErrorCodes.silentLogoutUnsupported\n )\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { InProgressPerformanceEvent, Logger } from \"@azure/msal-common/browser\";\n\nexport function collectInstanceStats(\n currentClientId: string,\n performanceEvent: InProgressPerformanceEvent,\n logger: Logger\n): void {\n const frameInstances: string[] =\n // @ts-ignore\n window.msal?.clientIds || [];\n\n const msalInstanceCount = frameInstances.length;\n\n const sameClientIdInstanceCount = frameInstances.filter(\n (i) => i === currentClientId\n ).length;\n\n if (sameClientIdInstanceCount > 1) {\n logger.warning(\n \"There is already an instance of MSAL.js in the window with the same client id.\"\n );\n }\n performanceEvent.add({\n msalInstanceCount: msalInstanceCount,\n sameClientIdInstanceCount: sameClientIdInstanceCount,\n });\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { CryptoOps } from \"../crypto/CryptoOps.js\";\nimport {\n InteractionRequiredAuthError,\n AccountInfo,\n Constants,\n INetworkModule,\n Logger,\n CommonSilentFlowRequest,\n ICrypto,\n DEFAULT_CRYPTO_IMPLEMENTATION,\n AuthError,\n PerformanceEvents,\n PerformanceCallbackFunction,\n IPerformanceClient,\n BaseAuthRequest,\n PromptValue,\n InProgressPerformanceEvent,\n getRequestThumbprint,\n AccountEntity,\n invokeAsync,\n invoke,\n createClientAuthError,\n ClientAuthErrorCodes,\n AccountFilter,\n buildStaticAuthorityOptions,\n InteractionRequiredAuthErrorCodes,\n PkceCodes,\n} from \"@azure/msal-common/browser\";\nimport {\n BrowserCacheManager,\n DEFAULT_BROWSER_CACHE_MANAGER,\n} from \"../cache/BrowserCacheManager.js\";\nimport * as AccountManager from \"../cache/AccountManager.js\";\nimport { BrowserConfiguration, CacheOptions } from \"../config/Configuration.js\";\nimport {\n InteractionType,\n ApiId,\n BrowserCacheLocation,\n WrapperSKU,\n CacheLookupPolicy,\n DEFAULT_REQUEST,\n BrowserConstants,\n iFrameRenewalPolicies,\n INTERACTION_TYPE,\n} from \"../utils/BrowserConstants.js\";\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\nimport { PopupRequest } from \"../request/PopupRequest.js\";\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\nimport { EventCallbackFunction, EventError } from \"../event/EventMessage.js\";\nimport { EventType } from \"../event/EventType.js\";\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\nimport { EndSessionPopupRequest } from \"../request/EndSessionPopupRequest.js\";\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\nimport { EventHandler } from \"../event/EventHandler.js\";\nimport { PopupClient } from \"../interaction_client/PopupClient.js\";\nimport { RedirectClient } from \"../interaction_client/RedirectClient.js\";\nimport { SilentIframeClient } from \"../interaction_client/SilentIframeClient.js\";\nimport { SilentRefreshClient } from \"../interaction_client/SilentRefreshClient.js\";\nimport { TokenCache } from \"../cache/TokenCache.js\";\nimport { ITokenCache } from \"../cache/ITokenCache.js\";\nimport { PlatformAuthInteractionClient } from \"../interaction_client/PlatformAuthInteractionClient.js\";\nimport { SilentRequest } from \"../request/SilentRequest.js\";\nimport {\n NativeAuthError,\n isFatalNativeAuthError,\n} from \"../error/NativeAuthError.js\";\nimport { SilentCacheClient } from \"../interaction_client/SilentCacheClient.js\";\nimport { SilentAuthCodeClient } from \"../interaction_client/SilentAuthCodeClient.js\";\nimport {\n createBrowserAuthError,\n BrowserAuthErrorCodes,\n} from \"../error/BrowserAuthError.js\";\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\nimport { PlatformAuthRequest } from \"../broker/nativeBroker/PlatformAuthRequest.js\";\nimport { StandardOperatingContext } from \"../operatingcontext/StandardOperatingContext.js\";\nimport { BaseOperatingContext } from \"../operatingcontext/BaseOperatingContext.js\";\nimport { IController } from \"./IController.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\nimport { createNewGuid } from \"../crypto/BrowserCrypto.js\";\nimport { initializeSilentRequest } from \"../request/RequestHelpers.js\";\nimport { InitializeApplicationRequest } from \"../request/InitializeApplicationRequest.js\";\nimport { generatePkceCodes } from \"../crypto/PkceGenerator.js\";\nimport {\n getPlatformAuthProvider,\n isPlatformAuthAllowed,\n} from \"../broker/nativeBroker/PlatformAuthProvider.js\";\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\nimport { collectInstanceStats } from \"../utils/MsalFrameStatsUtils.js\";\n\nfunction getAccountType(\n account?: AccountInfo\n): \"AAD\" | \"MSA\" | \"B2C\" | undefined {\n const idTokenClaims = account?.idTokenClaims;\n if (idTokenClaims?.tfp || idTokenClaims?.acr) {\n return \"B2C\";\n }\n\n if (!idTokenClaims?.tid) {\n return undefined;\n } else if (idTokenClaims?.tid === \"9188040d-6c67-4c5b-b112-36a304b66dad\") {\n return \"MSA\";\n }\n return \"AAD\";\n}\n\nfunction preflightCheck(\n initialized: boolean,\n performanceEvent: InProgressPerformanceEvent\n) {\n try {\n BrowserUtils.preflightCheck(initialized);\n } catch (e) {\n performanceEvent.end({ success: false }, e);\n throw e;\n }\n}\n\nexport class StandardController implements IController {\n // OperatingContext\n protected readonly operatingContext: StandardOperatingContext;\n\n // Crypto interface implementation\n protected readonly browserCrypto: ICrypto;\n\n // Storage interface implementation\n protected readonly browserStorage: BrowserCacheManager;\n\n // Native Cache in memory storage implementation\n protected readonly nativeInternalStorage: BrowserCacheManager;\n\n // Network interface implementation\n protected readonly networkClient: INetworkModule;\n\n // Navigation interface implementation\n protected navigationClient: INavigationClient;\n\n // Input configuration by developer/user\n protected readonly config: BrowserConfiguration;\n\n // Token cache implementation\n private tokenCache: TokenCache;\n\n // Logger\n protected logger: Logger;\n\n // Flag to indicate if in browser environment\n protected isBrowserEnvironment: boolean;\n\n protected readonly eventHandler: EventHandler;\n\n // Redirect Response Object\n protected readonly redirectResponse: Map<\n string,\n Promise\n >;\n\n // Native Extension Provider\n protected platformAuthProvider: IPlatformAuthHandler | undefined;\n\n // Hybrid auth code responses\n private hybridAuthCodeResponses: Map>;\n\n // Performance telemetry client\n protected readonly performanceClient: IPerformanceClient;\n\n // Flag representing whether or not the initialize API has been called and completed\n protected initialized: boolean;\n\n // Active requests\n private activeSilentTokenRequests: Map<\n string,\n Promise\n >;\n\n // Active Iframe request\n private activeIframeRequest: [Promise, string] | undefined;\n\n private ssoSilentMeasurement?: InProgressPerformanceEvent;\n private acquireTokenByCodeAsyncMeasurement?: InProgressPerformanceEvent;\n\n private pkceCode: PkceCodes | undefined;\n\n /**\n * @constructor\n * Constructor for the PublicClientApplication used to instantiate the PublicClientApplication object\n *\n * Important attributes in the Configuration object for auth are:\n * - clientID: the application ID of your application. You can obtain one by registering your application with our Application registration portal : https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredAppsPreview\n * - authority: the authority URL for your application.\n * - redirect_uri: the uri of your application registered in the portal.\n *\n * In Azure AD, authority is a URL indicating the Azure active directory that MSAL uses to obtain tokens.\n * It is of the form https://login.microsoftonline.com/{Enter_the_Tenant_Info_Here}\n * If your application supports Accounts in one organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with the Tenant Id or Tenant name (for example, contoso.microsoft.com).\n * If your application supports Accounts in any organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with organizations.\n * If your application supports Accounts in any organizational directory and personal Microsoft accounts, replace \"Enter_the_Tenant_Info_Here\" value with common.\n * To restrict support to Personal Microsoft accounts only, replace \"Enter_the_Tenant_Info_Here\" value with consumers.\n *\n * In Azure B2C, authority is of the form https://{instance}/tfp/{tenant}/{policyName}/\n * Full B2C functionality will be available in this library in future versions.\n *\n * @param configuration Object for the MSAL PublicClientApplication instance\n */\n constructor(operatingContext: StandardOperatingContext) {\n this.operatingContext = operatingContext;\n this.isBrowserEnvironment =\n this.operatingContext.isBrowserEnvironment();\n // Set the configuration.\n this.config = operatingContext.getConfig();\n this.initialized = false;\n\n // Initialize logger\n this.logger = this.operatingContext.getLogger();\n\n // Initialize the network module class.\n this.networkClient = this.config.system.networkClient;\n\n // Initialize the navigation client class.\n this.navigationClient = this.config.system.navigationClient;\n\n // Initialize redirectResponse Map\n this.redirectResponse = new Map();\n\n // Initial hybrid spa map\n this.hybridAuthCodeResponses = new Map();\n\n // Initialize performance client\n this.performanceClient = this.config.telemetry.client;\n\n // Initialize the crypto class.\n this.browserCrypto = this.isBrowserEnvironment\n ? new CryptoOps(this.logger, this.performanceClient)\n : DEFAULT_CRYPTO_IMPLEMENTATION;\n\n this.eventHandler = new EventHandler(this.logger);\n\n // Initialize the browser storage class.\n this.browserStorage = this.isBrowserEnvironment\n ? new BrowserCacheManager(\n this.config.auth.clientId,\n this.config.cache,\n this.browserCrypto,\n this.logger,\n this.performanceClient,\n this.eventHandler,\n buildStaticAuthorityOptions(this.config.auth)\n )\n : DEFAULT_BROWSER_CACHE_MANAGER(\n this.config.auth.clientId,\n this.logger,\n this.performanceClient,\n this.eventHandler\n );\n\n // initialize in memory storage for native flows\n const nativeCacheOptions: Required = {\n cacheLocation: BrowserCacheLocation.MemoryStorage,\n cacheRetentionDays: 5,\n temporaryCacheLocation: BrowserCacheLocation.MemoryStorage,\n storeAuthStateInCookie: false,\n secureCookies: false,\n cacheMigrationEnabled: false,\n claimsBasedCachingEnabled: false,\n };\n this.nativeInternalStorage = new BrowserCacheManager(\n this.config.auth.clientId,\n nativeCacheOptions,\n this.browserCrypto,\n this.logger,\n this.performanceClient,\n this.eventHandler\n );\n\n // Initialize the token cache\n this.tokenCache = new TokenCache(\n this.config,\n this.browserStorage,\n this.logger,\n this.browserCrypto\n );\n\n this.activeSilentTokenRequests = new Map();\n\n // Register listener functions\n this.trackPageVisibility = this.trackPageVisibility.bind(this);\n\n // Register listener functions\n this.trackPageVisibilityWithMeasurement =\n this.trackPageVisibilityWithMeasurement.bind(this);\n }\n\n static async createController(\n operatingContext: BaseOperatingContext,\n request?: InitializeApplicationRequest\n ): Promise {\n const controller = new StandardController(operatingContext);\n await controller.initialize(request);\n return controller;\n }\n\n private trackPageVisibility(correlationId?: string): void {\n if (!correlationId) {\n return;\n }\n this.logger.info(\"Perf: Visibility change detected\");\n this.performanceClient.incrementFields(\n { visibilityChangeCount: 1 },\n correlationId\n );\n }\n\n /**\n * Initializer function to perform async startup tasks such as connecting to WAM extension\n * @param request {?InitializeApplicationRequest} correlation id\n */\n async initialize(\n request?: InitializeApplicationRequest,\n isBroker?: boolean\n ): Promise {\n this.logger.trace(\"initialize called\");\n if (this.initialized) {\n this.logger.info(\n \"initialize has already been called, exiting early.\"\n );\n return;\n }\n\n if (!this.isBrowserEnvironment) {\n this.logger.info(\"in non-browser environment, exiting early.\");\n this.initialized = true;\n this.eventHandler.emitEvent(EventType.INITIALIZE_END);\n return;\n }\n\n const initCorrelationId =\n request?.correlationId || this.getRequestCorrelationId();\n const allowPlatformBroker = this.config.system.allowPlatformBroker;\n const initMeasurement = this.performanceClient.startMeasurement(\n PerformanceEvents.InitializeClientApplication,\n initCorrelationId\n );\n this.eventHandler.emitEvent(EventType.INITIALIZE_START);\n\n // Broker applications are initialized twice, so we avoid double-counting it\n if (!isBroker) {\n try {\n this.logMultipleInstances(initMeasurement);\n } catch {}\n }\n\n await invokeAsync(\n this.browserStorage.initialize.bind(this.browserStorage),\n PerformanceEvents.InitializeCache,\n this.logger,\n this.performanceClient,\n initCorrelationId\n )(initCorrelationId);\n\n if (allowPlatformBroker) {\n try {\n // check if platform authentication is available via DOM or browser extension and create relevant handlers\n this.platformAuthProvider = await getPlatformAuthProvider(\n this.logger,\n this.performanceClient,\n initCorrelationId,\n this.config.system.nativeBrokerHandshakeTimeout\n );\n } catch (e) {\n this.logger.verbose(e as string);\n }\n }\n\n if (!this.config.cache.claimsBasedCachingEnabled) {\n this.logger.verbose(\n \"Claims-based caching is disabled. Clearing the previous cache with claims\"\n );\n\n invoke(\n this.browserStorage.clearTokensAndKeysWithClaims.bind(\n this.browserStorage\n ),\n PerformanceEvents.ClearTokensAndKeysWithClaims,\n this.logger,\n this.performanceClient,\n initCorrelationId\n )(initCorrelationId);\n }\n\n this.config.system.asyncPopups &&\n (await this.preGeneratePkceCodes(initCorrelationId));\n this.initialized = true;\n this.eventHandler.emitEvent(EventType.INITIALIZE_END);\n initMeasurement.end({\n allowPlatformBroker: allowPlatformBroker,\n success: true,\n });\n }\n\n // #region Redirect Flow\n\n /**\n * Event handler function which allows users to fire events after the PublicClientApplication object\n * has loaded during redirect flows. This should be invoked on all page loads involved in redirect\n * auth flows.\n * @param hash Hash to process. Defaults to the current value of window.location.hash. Only needs to be provided explicitly if the response to be handled is not contained in the current value.\n * @returns Token response or null. If the return value is null, then no auth redirect was detected.\n */\n async handleRedirectPromise(\n hash?: string\n ): Promise {\n this.logger.verbose(\"handleRedirectPromise called\");\n // Block token acquisition before initialize has been called\n BrowserUtils.blockAPICallsBeforeInitialize(this.initialized);\n\n if (this.isBrowserEnvironment) {\n /**\n * Store the promise on the PublicClientApplication instance if this is the first invocation of handleRedirectPromise,\n * otherwise return the promise from the first invocation. Prevents race conditions when handleRedirectPromise is called\n * several times concurrently.\n */\n const redirectResponseKey = hash || \"\";\n let response = this.redirectResponse.get(redirectResponseKey);\n if (typeof response === \"undefined\") {\n response = this.handleRedirectPromiseInternal(hash);\n this.redirectResponse.set(redirectResponseKey, response);\n this.logger.verbose(\n \"handleRedirectPromise has been called for the first time, storing the promise\"\n );\n } else {\n this.logger.verbose(\n \"handleRedirectPromise has been called previously, returning the result from the first call\"\n );\n }\n\n return response;\n }\n this.logger.verbose(\n \"handleRedirectPromise returns null, not browser environment\"\n );\n return null;\n }\n\n /**\n * The internal details of handleRedirectPromise. This is separated out to a helper to allow handleRedirectPromise to memoize requests\n * @param hash\n * @returns\n */\n private async handleRedirectPromiseInternal(\n hash?: string\n ): Promise {\n if (!this.browserStorage.isInteractionInProgress(true)) {\n this.logger.info(\n \"handleRedirectPromise called but there is no interaction in progress, returning null.\"\n );\n return null;\n }\n\n const interactionType =\n this.browserStorage.getInteractionInProgress()?.type;\n if (interactionType === INTERACTION_TYPE.SIGNOUT) {\n this.logger.verbose(\n \"handleRedirectPromise removing interaction_in_progress flag and returning null after sign-out\"\n );\n this.browserStorage.setInteractionInProgress(false);\n return Promise.resolve(null);\n }\n\n const loggedInAccounts = this.getAllAccounts();\n const platformBrokerRequest: PlatformAuthRequest | null =\n this.browserStorage.getCachedNativeRequest();\n const useNative =\n platformBrokerRequest && this.platformAuthProvider && !hash;\n\n let rootMeasurement: InProgressPerformanceEvent;\n\n this.eventHandler.emitEvent(\n EventType.HANDLE_REDIRECT_START,\n InteractionType.Redirect\n );\n\n let redirectResponse: Promise;\n try {\n if (useNative && this.platformAuthProvider) {\n rootMeasurement = this.performanceClient.startMeasurement(\n PerformanceEvents.AcquireTokenRedirect,\n platformBrokerRequest?.correlationId || \"\"\n );\n this.logger.trace(\n \"handleRedirectPromise - acquiring token from native platform\"\n );\n rootMeasurement.add({\n isPlatformBrokerRequest: true,\n });\n const nativeClient = new PlatformAuthInteractionClient(\n this.config,\n this.browserStorage,\n this.browserCrypto,\n this.logger,\n this.eventHandler,\n this.navigationClient,\n ApiId.handleRedirectPromise,\n this.performanceClient,\n this.platformAuthProvider,\n platformBrokerRequest.accountId,\n this.nativeInternalStorage,\n platformBrokerRequest.correlationId\n );\n\n redirectResponse = invokeAsync(\n nativeClient.handleRedirectPromise.bind(nativeClient),\n PerformanceEvents.HandleNativeRedirectPromiseMeasurement,\n this.logger,\n this.performanceClient,\n rootMeasurement.event.correlationId\n )(this.performanceClient, rootMeasurement.event.correlationId);\n } else {\n const [standardRequest, codeVerifier] =\n this.browserStorage.getCachedRequest();\n const correlationId = standardRequest.correlationId;\n // Reset rootMeasurement now that we have correlationId\n rootMeasurement = this.performanceClient.startMeasurement(\n PerformanceEvents.AcquireTokenRedirect,\n correlationId\n );\n this.logger.trace(\n \"handleRedirectPromise - acquiring token from web flow\"\n );\n const redirectClient = this.createRedirectClient(correlationId);\n redirectResponse = invokeAsync(\n redirectClient.handleRedirectPromise.bind(redirectClient),\n PerformanceEvents.HandleRedirectPromiseMeasurement,\n this.logger,\n this.performanceClient,\n rootMeasurement.event.correlationId\n )(hash, standardRequest, codeVerifier, rootMeasurement);\n }\n } catch (e) {\n this.browserStorage.resetRequestCache();\n throw e;\n }\n\n return redirectResponse\n .then((result: AuthenticationResult | null) => {\n if (result) {\n this.browserStorage.resetRequestCache();\n // Emit login event if number of accounts change\n const isLoggingIn =\n loggedInAccounts.length < this.getAllAccounts().length;\n if (isLoggingIn) {\n this.eventHandler.emitEvent(\n EventType.LOGIN_SUCCESS,\n InteractionType.Redirect,\n result\n );\n this.logger.verbose(\n \"handleRedirectResponse returned result, login success\"\n );\n } else {\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_SUCCESS,\n InteractionType.Redirect,\n result\n );\n this.logger.verbose(\n \"handleRedirectResponse returned result, acquire token success\"\n );\n }\n rootMeasurement.end({\n success: true,\n accountType: getAccountType(result.account),\n });\n } else {\n /*\n * Instrument an event only if an error code is set. Otherwise, discard it when the redirect response\n * is empty and the error code is missing.\n */\n if (rootMeasurement.event.errorCode) {\n rootMeasurement.end({ success: false });\n } else {\n rootMeasurement.discard();\n }\n }\n\n this.eventHandler.emitEvent(\n EventType.HANDLE_REDIRECT_END,\n InteractionType.Redirect\n );\n\n return result;\n })\n .catch((e) => {\n this.browserStorage.resetRequestCache();\n const eventError = e as EventError;\n // Emit login event if there is an account\n if (loggedInAccounts.length > 0) {\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_FAILURE,\n InteractionType.Redirect,\n null,\n eventError\n );\n } else {\n this.eventHandler.emitEvent(\n EventType.LOGIN_FAILURE,\n InteractionType.Redirect,\n null,\n eventError\n );\n }\n this.eventHandler.emitEvent(\n EventType.HANDLE_REDIRECT_END,\n InteractionType.Redirect\n );\n\n rootMeasurement.end(\n {\n success: false,\n },\n eventError\n );\n\n throw e;\n });\n }\n\n /**\n * Use when you want to obtain an access_token for your API by redirecting the user's browser window to the authorization endpoint. This function redirects\n * the page, so any code that follows this function will not execute.\n *\n * IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current\n * browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.\n *\n * @param request\n */\n async acquireTokenRedirect(request: RedirectRequest): Promise {\n // Preflight request\n const correlationId = this.getRequestCorrelationId(request);\n this.logger.verbose(\"acquireTokenRedirect called\", correlationId);\n\n const atrMeasurement = this.performanceClient.startMeasurement(\n PerformanceEvents.AcquireTokenPreRedirect,\n correlationId\n );\n atrMeasurement.add({\n accountType: getAccountType(request.account),\n scenarioId: request.scenarioId,\n });\n\n // Override on request only if set, as onRedirectNavigate field is deprecated\n const onRedirectNavigateCb = request.onRedirectNavigate;\n if (onRedirectNavigateCb) {\n request.onRedirectNavigate = (url: string) => {\n const navigate =\n typeof onRedirectNavigateCb === \"function\"\n ? onRedirectNavigateCb(url)\n : undefined;\n atrMeasurement.add({\n navigateCallbackResult: navigate !== false,\n });\n atrMeasurement.event =\n atrMeasurement.end({ success: true }) ||\n atrMeasurement.event;\n return navigate;\n };\n } else {\n const configOnRedirectNavigateCb =\n this.config.auth.onRedirectNavigate;\n this.config.auth.onRedirectNavigate = (url: string) => {\n const navigate =\n typeof configOnRedirectNavigateCb === \"function\"\n ? configOnRedirectNavigateCb(url)\n : undefined;\n atrMeasurement.add({\n navigateCallbackResult: navigate !== false,\n });\n atrMeasurement.event =\n atrMeasurement.end({ success: true }) ||\n atrMeasurement.event;\n return navigate;\n };\n }\n\n // If logged in, emit acquire token events\n const isLoggedIn = this.getAllAccounts().length > 0;\n try {\n BrowserUtils.redirectPreflightCheck(this.initialized, this.config);\n this.browserStorage.setInteractionInProgress(\n true,\n INTERACTION_TYPE.SIGNIN\n );\n\n if (isLoggedIn) {\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_START,\n InteractionType.Redirect,\n request\n );\n } else {\n this.eventHandler.emitEvent(\n EventType.LOGIN_START,\n InteractionType.Redirect,\n request\n );\n }\n\n let result: Promise;\n\n if (\n this.platformAuthProvider &&\n this.canUsePlatformBroker(request)\n ) {\n const nativeClient = new PlatformAuthInteractionClient(\n this.config,\n this.browserStorage,\n this.browserCrypto,\n this.logger,\n this.eventHandler,\n this.navigationClient,\n ApiId.acquireTokenRedirect,\n this.performanceClient,\n this.platformAuthProvider,\n this.getNativeAccountId(request),\n this.nativeInternalStorage,\n correlationId\n );\n\n result = nativeClient\n .acquireTokenRedirect(request, atrMeasurement)\n .catch((e: AuthError) => {\n atrMeasurement.add({\n brokerErrorName: e.name,\n brokerErrorCode: e.errorCode,\n });\n if (\n e instanceof NativeAuthError &&\n isFatalNativeAuthError(e)\n ) {\n this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt platform broker calls\n const redirectClient =\n this.createRedirectClient(correlationId);\n return redirectClient.acquireToken(request);\n } else if (e instanceof InteractionRequiredAuthError) {\n this.logger.verbose(\n \"acquireTokenRedirect - Resolving interaction required error thrown by native broker by falling back to web flow\"\n );\n const redirectClient =\n this.createRedirectClient(correlationId);\n return redirectClient.acquireToken(request);\n }\n throw e;\n });\n } else {\n const redirectClient = this.createRedirectClient(correlationId);\n result = redirectClient.acquireToken(request);\n }\n\n return await result;\n } catch (e) {\n this.browserStorage.resetRequestCache();\n /*\n * Pre-redirect event completes before navigation occurs.\n * Timed out navigation needs to be instrumented separately as a post-redirect event.\n */\n if (atrMeasurement.event.status === 2) {\n this.performanceClient\n .startMeasurement(\n PerformanceEvents.AcquireTokenRedirect,\n correlationId\n )\n .end({ success: false }, e);\n } else {\n atrMeasurement.end({ success: false }, e);\n }\n\n if (isLoggedIn) {\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_FAILURE,\n InteractionType.Redirect,\n null,\n e as EventError\n );\n } else {\n this.eventHandler.emitEvent(\n EventType.LOGIN_FAILURE,\n InteractionType.Redirect,\n null,\n e as EventError\n );\n }\n throw e;\n }\n }\n\n // #endregion\n\n // #region Popup Flow\n\n /**\n * Use when you want to obtain an access_token for your API via opening a popup window in the user's browser\n *\n * @param request\n *\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\n */\n acquireTokenPopup(request: PopupRequest): Promise {\n const correlationId = this.getRequestCorrelationId(request);\n const atPopupMeasurement = this.performanceClient.startMeasurement(\n PerformanceEvents.AcquireTokenPopup,\n correlationId\n );\n\n atPopupMeasurement.add({\n scenarioId: request.scenarioId,\n accountType: getAccountType(request.account),\n });\n\n try {\n this.logger.verbose(\"acquireTokenPopup called\", correlationId);\n preflightCheck(this.initialized, atPopupMeasurement);\n this.browserStorage.setInteractionInProgress(\n true,\n INTERACTION_TYPE.SIGNIN\n );\n } catch (e) {\n // Since this function is syncronous we need to reject\n return Promise.reject(e);\n }\n\n // If logged in, emit acquire token events\n const loggedInAccounts = this.getAllAccounts();\n if (loggedInAccounts.length > 0) {\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_START,\n InteractionType.Popup,\n request\n );\n } else {\n this.eventHandler.emitEvent(\n EventType.LOGIN_START,\n InteractionType.Popup,\n request\n );\n }\n\n let result: Promise;\n const pkce = this.getPreGeneratedPkceCodes(correlationId);\n\n if (this.canUsePlatformBroker(request)) {\n atPopupMeasurement.add({\n isPlatformBrokerRequest: true,\n });\n result = this.acquireTokenNative(\n {\n ...request,\n correlationId,\n },\n ApiId.acquireTokenPopup\n )\n .then((response) => {\n atPopupMeasurement.end({\n success: true,\n accountType: getAccountType(response.account),\n });\n return response;\n })\n .catch((e: AuthError) => {\n atPopupMeasurement.add({\n brokerErrorName: e.name,\n brokerErrorCode: e.errorCode,\n });\n if (\n e instanceof NativeAuthError &&\n isFatalNativeAuthError(e)\n ) {\n this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to continuing to attempt platform broker calls\n const popupClient =\n this.createPopupClient(correlationId);\n return popupClient.acquireToken(request, pkce);\n } else if (e instanceof InteractionRequiredAuthError) {\n this.logger.verbose(\n \"acquireTokenPopup - Resolving interaction required error thrown by native broker by falling back to web flow\"\n );\n const popupClient =\n this.createPopupClient(correlationId);\n return popupClient.acquireToken(request, pkce);\n }\n throw e;\n });\n } else {\n const popupClient = this.createPopupClient(correlationId);\n result = popupClient.acquireToken(request, pkce);\n }\n\n return result\n .then((result) => {\n /*\n * If logged in, emit acquire token events\n */\n const isLoggingIn =\n loggedInAccounts.length < this.getAllAccounts().length;\n if (isLoggingIn) {\n this.eventHandler.emitEvent(\n EventType.LOGIN_SUCCESS,\n InteractionType.Popup,\n result\n );\n } else {\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_SUCCESS,\n InteractionType.Popup,\n result\n );\n }\n\n atPopupMeasurement.end({\n success: true,\n accessTokenSize: result.accessToken.length,\n idTokenSize: result.idToken.length,\n accountType: getAccountType(result.account),\n });\n return result;\n })\n .catch((e: Error) => {\n if (loggedInAccounts.length > 0) {\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_FAILURE,\n InteractionType.Popup,\n null,\n e\n );\n } else {\n this.eventHandler.emitEvent(\n EventType.LOGIN_FAILURE,\n InteractionType.Popup,\n null,\n e\n );\n }\n\n atPopupMeasurement.end(\n {\n success: false,\n },\n e\n );\n\n // Since this function is syncronous we need to reject\n return Promise.reject(e);\n })\n .finally(async () => {\n this.browserStorage.setInteractionInProgress(false);\n if (this.config.system.asyncPopups) {\n await this.preGeneratePkceCodes(correlationId);\n }\n });\n }\n\n private trackPageVisibilityWithMeasurement(): void {\n const measurement =\n this.ssoSilentMeasurement ||\n this.acquireTokenByCodeAsyncMeasurement;\n if (!measurement) {\n return;\n }\n\n this.logger.info(\n \"Perf: Visibility change detected in \",\n measurement.event.name\n );\n measurement.increment({\n visibilityChangeCount: 1,\n });\n }\n // #endregion\n\n // #region Silent Flow\n\n /**\n * This function uses a hidden iframe to fetch an authorization code from the eSTS. There are cases where this may not work:\n * - Any browser using a form of Intelligent Tracking Prevention\n * - If there is not an established session with the service\n *\n * In these cases, the request must be done inside a popup or full frame redirect.\n *\n * For the cases where interaction is required, you cannot send a request with prompt=none.\n *\n * If your refresh token has expired, you can use this function to fetch a new set of tokens silently as long as\n * you session on the server still exists.\n * @param request {@link SsoSilentRequest}\n *\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\n */\n async ssoSilent(request: SsoSilentRequest): Promise {\n const correlationId = this.getRequestCorrelationId(request);\n const validRequest = {\n ...request,\n // will be PromptValue.NONE or PromptValue.NO_SESSION\n prompt: request.prompt,\n correlationId: correlationId,\n };\n this.ssoSilentMeasurement = this.performanceClient.startMeasurement(\n PerformanceEvents.SsoSilent,\n correlationId\n );\n this.ssoSilentMeasurement?.add({\n scenarioId: request.scenarioId,\n accountType: getAccountType(request.account),\n });\n preflightCheck(this.initialized, this.ssoSilentMeasurement);\n this.ssoSilentMeasurement?.increment({\n visibilityChangeCount: 0,\n });\n\n document.addEventListener(\n \"visibilitychange\",\n this.trackPageVisibilityWithMeasurement\n );\n this.logger.verbose(\"ssoSilent called\", correlationId);\n this.eventHandler.emitEvent(\n EventType.SSO_SILENT_START,\n InteractionType.Silent,\n validRequest\n );\n\n let result: Promise;\n\n if (this.canUsePlatformBroker(validRequest)) {\n this.ssoSilentMeasurement?.add({\n isPlatformBrokerRequest: true,\n });\n result = this.acquireTokenNative(\n validRequest,\n ApiId.ssoSilent\n ).catch((e: AuthError) => {\n this.ssoSilentMeasurement?.add({\n brokerErrorName: e.name,\n brokerErrorCode: e.errorCode,\n });\n // If native token acquisition fails for availability reasons fallback to standard flow\n if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {\n this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt\n const silentIframeClient = this.createSilentIframeClient(\n validRequest.correlationId\n );\n return silentIframeClient.acquireToken(validRequest);\n }\n throw e;\n });\n } else {\n const silentIframeClient = this.createSilentIframeClient(\n validRequest.correlationId\n );\n result = silentIframeClient.acquireToken(validRequest);\n }\n\n return result\n .then((response) => {\n this.eventHandler.emitEvent(\n EventType.SSO_SILENT_SUCCESS,\n InteractionType.Silent,\n response\n );\n this.ssoSilentMeasurement?.end({\n success: true,\n accessTokenSize: response.accessToken.length,\n idTokenSize: response.idToken.length,\n accountType: getAccountType(response.account),\n });\n return response;\n })\n .catch((e: Error) => {\n this.eventHandler.emitEvent(\n EventType.SSO_SILENT_FAILURE,\n InteractionType.Silent,\n null,\n e\n );\n this.ssoSilentMeasurement?.end(\n {\n success: false,\n },\n e\n );\n throw e;\n })\n .finally(() => {\n document.removeEventListener(\n \"visibilitychange\",\n this.trackPageVisibilityWithMeasurement\n );\n });\n }\n\n /**\n * This function redeems an authorization code (passed as code) from the eSTS token endpoint.\n * This authorization code should be acquired server-side using a confidential client to acquire a spa_code.\n * This API is not indended for normal authorization code acquisition and redemption.\n *\n * Redemption of this authorization code will not require PKCE, as it was acquired by a confidential client.\n *\n * @param request {@link AuthorizationCodeRequest}\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\n */\n async acquireTokenByCode(\n request: AuthorizationCodeRequest\n ): Promise {\n const correlationId = this.getRequestCorrelationId(request);\n this.logger.trace(\"acquireTokenByCode called\", correlationId);\n const atbcMeasurement = this.performanceClient.startMeasurement(\n PerformanceEvents.AcquireTokenByCode,\n correlationId\n );\n preflightCheck(this.initialized, atbcMeasurement);\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_BY_CODE_START,\n InteractionType.Silent,\n request\n );\n atbcMeasurement.add({ scenarioId: request.scenarioId });\n\n try {\n if (request.code && request.nativeAccountId) {\n // Throw error in case server returns both spa_code and spa_accountid in exchange for auth code.\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.spaCodeAndNativeAccountIdPresent\n );\n } else if (request.code) {\n const hybridAuthCode = request.code;\n let response = this.hybridAuthCodeResponses.get(hybridAuthCode);\n if (!response) {\n this.logger.verbose(\n \"Initiating new acquireTokenByCode request\",\n correlationId\n );\n response = this.acquireTokenByCodeAsync({\n ...request,\n correlationId,\n })\n .then((result: AuthenticationResult) => {\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_BY_CODE_SUCCESS,\n InteractionType.Silent,\n result\n );\n this.hybridAuthCodeResponses.delete(hybridAuthCode);\n atbcMeasurement.end({\n success: true,\n accessTokenSize: result.accessToken.length,\n idTokenSize: result.idToken.length,\n accountType: getAccountType(result.account),\n });\n return result;\n })\n .catch((error: Error) => {\n this.hybridAuthCodeResponses.delete(hybridAuthCode);\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_BY_CODE_FAILURE,\n InteractionType.Silent,\n null,\n error\n );\n atbcMeasurement.end(\n {\n success: false,\n },\n error\n );\n throw error;\n });\n this.hybridAuthCodeResponses.set(hybridAuthCode, response);\n } else {\n this.logger.verbose(\n \"Existing acquireTokenByCode request found\",\n correlationId\n );\n atbcMeasurement.discard();\n }\n return await response;\n } else if (request.nativeAccountId) {\n if (\n this.canUsePlatformBroker(request, request.nativeAccountId)\n ) {\n atbcMeasurement.add({\n isPlatformBrokerRequest: true,\n });\n const result = await this.acquireTokenNative(\n {\n ...request,\n correlationId,\n },\n ApiId.acquireTokenByCode,\n request.nativeAccountId\n ).catch((e: AuthError) => {\n // If native token acquisition fails for availability reasons fallback to standard flow\n if (\n e instanceof NativeAuthError &&\n isFatalNativeAuthError(e)\n ) {\n this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt\n }\n atbcMeasurement.add({\n brokerErrorName: e.name,\n brokerErrorCode: e.errorCode,\n });\n throw e;\n });\n atbcMeasurement.end({\n accountType: getAccountType(result.account),\n success: true,\n });\n return result;\n } else {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.unableToAcquireTokenFromNativePlatform\n );\n }\n } else {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.authCodeOrNativeAccountIdRequired\n );\n }\n } catch (e) {\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_BY_CODE_FAILURE,\n InteractionType.Silent,\n null,\n e as EventError\n );\n atbcMeasurement.end(\n {\n success: false,\n },\n e\n );\n throw e;\n }\n }\n\n /**\n * Creates a SilentAuthCodeClient to redeem an authorization code.\n * @param request\n * @returns Result of the operation to redeem the authorization code\n */\n private async acquireTokenByCodeAsync(\n request: AuthorizationCodeRequest\n ): Promise {\n this.logger.trace(\n \"acquireTokenByCodeAsync called\",\n request.correlationId\n );\n this.acquireTokenByCodeAsyncMeasurement =\n this.performanceClient.startMeasurement(\n PerformanceEvents.AcquireTokenByCodeAsync,\n request.correlationId\n );\n this.acquireTokenByCodeAsyncMeasurement?.increment({\n visibilityChangeCount: 0,\n });\n document.addEventListener(\n \"visibilitychange\",\n this.trackPageVisibilityWithMeasurement\n );\n const silentAuthCodeClient = this.createSilentAuthCodeClient(\n request.correlationId\n );\n const silentTokenResult = await silentAuthCodeClient\n .acquireToken(request)\n .then((response) => {\n this.acquireTokenByCodeAsyncMeasurement?.end({\n success: true,\n fromCache: response.fromCache,\n });\n return response;\n })\n .catch((tokenRenewalError: Error) => {\n this.acquireTokenByCodeAsyncMeasurement?.end(\n {\n success: false,\n },\n tokenRenewalError\n );\n throw tokenRenewalError;\n })\n .finally(() => {\n document.removeEventListener(\n \"visibilitychange\",\n this.trackPageVisibilityWithMeasurement\n );\n });\n return silentTokenResult;\n }\n\n /**\n * Attempt to acquire an access token from the cache\n * @param silentCacheClient SilentCacheClient\n * @param commonRequest CommonSilentFlowRequest\n * @param silentRequest SilentRequest\n * @returns A promise that, when resolved, returns the access token\n */\n protected async acquireTokenFromCache(\n commonRequest: CommonSilentFlowRequest,\n cacheLookupPolicy: CacheLookupPolicy\n ): Promise {\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.AcquireTokenFromCache,\n commonRequest.correlationId\n );\n switch (cacheLookupPolicy) {\n case CacheLookupPolicy.Default:\n case CacheLookupPolicy.AccessToken:\n case CacheLookupPolicy.AccessTokenAndRefreshToken:\n const silentCacheClient = this.createSilentCacheClient(\n commonRequest.correlationId\n );\n return invokeAsync(\n silentCacheClient.acquireToken.bind(silentCacheClient),\n PerformanceEvents.SilentCacheClientAcquireToken,\n this.logger,\n this.performanceClient,\n commonRequest.correlationId\n )(commonRequest);\n default:\n throw createClientAuthError(\n ClientAuthErrorCodes.tokenRefreshRequired\n );\n }\n }\n\n /**\n * Attempt to acquire an access token via a refresh token\n * @param commonRequest CommonSilentFlowRequest\n * @param cacheLookupPolicy CacheLookupPolicy\n * @returns A promise that, when resolved, returns the access token\n */\n public async acquireTokenByRefreshToken(\n commonRequest: CommonSilentFlowRequest,\n cacheLookupPolicy: CacheLookupPolicy\n ): Promise {\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.AcquireTokenByRefreshToken,\n commonRequest.correlationId\n );\n switch (cacheLookupPolicy) {\n case CacheLookupPolicy.Default:\n case CacheLookupPolicy.AccessTokenAndRefreshToken:\n case CacheLookupPolicy.RefreshToken:\n case CacheLookupPolicy.RefreshTokenAndNetwork:\n const silentRefreshClient = this.createSilentRefreshClient(\n commonRequest.correlationId\n );\n\n return invokeAsync(\n silentRefreshClient.acquireToken.bind(silentRefreshClient),\n PerformanceEvents.SilentRefreshClientAcquireToken,\n this.logger,\n this.performanceClient,\n commonRequest.correlationId\n )(commonRequest);\n default:\n throw createClientAuthError(\n ClientAuthErrorCodes.tokenRefreshRequired\n );\n }\n }\n\n /**\n * Attempt to acquire an access token via an iframe\n * @param request CommonSilentFlowRequest\n * @returns A promise that, when resolved, returns the access token\n */\n protected async acquireTokenBySilentIframe(\n request: CommonSilentFlowRequest\n ): Promise {\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.AcquireTokenBySilentIframe,\n request.correlationId\n );\n\n const silentIframeClient = this.createSilentIframeClient(\n request.correlationId\n );\n\n return invokeAsync(\n silentIframeClient.acquireToken.bind(silentIframeClient),\n PerformanceEvents.SilentIframeClientAcquireToken,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request);\n }\n\n // #endregion\n\n // #region Logout\n\n /**\n * Deprecated logout function. Use logoutRedirect or logoutPopup instead\n * @param logoutRequest\n * @deprecated\n */\n async logout(logoutRequest?: EndSessionRequest): Promise {\n const correlationId = this.getRequestCorrelationId(logoutRequest);\n this.logger.warning(\n \"logout API is deprecated and will be removed in msal-browser v3.0.0. Use logoutRedirect instead.\",\n correlationId\n );\n return this.logoutRedirect({\n correlationId,\n ...logoutRequest,\n });\n }\n\n /**\n * Use to log out the current user, and redirect the user to the postLogoutRedirectUri.\n * Default behaviour is to redirect the user to `window.location.href`.\n * @param logoutRequest\n */\n async logoutRedirect(logoutRequest?: EndSessionRequest): Promise {\n const correlationId = this.getRequestCorrelationId(logoutRequest);\n BrowserUtils.redirectPreflightCheck(this.initialized, this.config);\n this.browserStorage.setInteractionInProgress(\n true,\n INTERACTION_TYPE.SIGNOUT\n );\n\n const redirectClient = this.createRedirectClient(correlationId);\n return redirectClient.logout(logoutRequest);\n }\n\n /**\n * Clears local cache for the current user then opens a popup window prompting the user to sign-out of the server\n * @param logoutRequest\n */\n logoutPopup(logoutRequest?: EndSessionPopupRequest): Promise {\n try {\n const correlationId = this.getRequestCorrelationId(logoutRequest);\n BrowserUtils.preflightCheck(this.initialized);\n this.browserStorage.setInteractionInProgress(\n true,\n INTERACTION_TYPE.SIGNOUT\n );\n\n const popupClient = this.createPopupClient(correlationId);\n return popupClient.logout(logoutRequest).finally(() => {\n this.browserStorage.setInteractionInProgress(false);\n });\n } catch (e) {\n // Since this function is syncronous we need to reject\n return Promise.reject(e);\n }\n }\n\n /**\n * Creates a cache interaction client to clear broswer cache.\n * @param logoutRequest\n */\n async clearCache(logoutRequest?: ClearCacheRequest): Promise {\n if (!this.isBrowserEnvironment) {\n this.logger.info(\"in non-browser environment, returning early.\");\n return;\n }\n const correlationId = this.getRequestCorrelationId(logoutRequest);\n const cacheClient = this.createSilentCacheClient(correlationId);\n return cacheClient.logout(logoutRequest);\n }\n\n // #endregion\n\n // #region Account APIs\n\n /**\n * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.\n * @param accountFilter - (Optional) filter to narrow down the accounts returned\n * @returns Array of AccountInfo objects in cache\n */\n getAllAccounts(accountFilter?: AccountFilter): AccountInfo[] {\n const correlationId = this.getRequestCorrelationId();\n return AccountManager.getAllAccounts(\n this.logger,\n this.browserStorage,\n this.isBrowserEnvironment,\n correlationId,\n accountFilter\n );\n }\n\n /**\n * Returns the first account found in the cache that matches the account filter passed in.\n * @param accountFilter\n * @returns The first account found in the cache matching the provided filter or null if no account could be found.\n */\n getAccount(accountFilter: AccountFilter): AccountInfo | null {\n const correlationId = this.getRequestCorrelationId();\n return AccountManager.getAccount(\n accountFilter,\n this.logger,\n this.browserStorage,\n correlationId\n );\n }\n\n /**\n * Returns the signed in account matching username.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found.\n * This API is provided for convenience but getAccountById should be used for best reliability\n * @param username\n * @returns The account object stored in MSAL\n */\n getAccountByUsername(username: string): AccountInfo | null {\n const correlationId = this.getRequestCorrelationId();\n return AccountManager.getAccountByUsername(\n username,\n this.logger,\n this.browserStorage,\n correlationId\n );\n }\n\n /**\n * Returns the signed in account matching homeAccountId.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found\n * @param homeAccountId\n * @returns The account object stored in MSAL\n */\n getAccountByHomeId(homeAccountId: string): AccountInfo | null {\n const correlationId = this.getRequestCorrelationId();\n return AccountManager.getAccountByHomeId(\n homeAccountId,\n this.logger,\n this.browserStorage,\n correlationId\n );\n }\n\n /**\n * Returns the signed in account matching localAccountId.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found\n * @param localAccountId\n * @returns The account object stored in MSAL\n */\n getAccountByLocalId(localAccountId: string): AccountInfo | null {\n const correlationId = this.getRequestCorrelationId();\n return AccountManager.getAccountByLocalId(\n localAccountId,\n this.logger,\n this.browserStorage,\n correlationId\n );\n }\n\n /**\n * Sets the account to use as the active account. If no account is passed to the acquireToken APIs, then MSAL will use this active account.\n * @param account\n */\n setActiveAccount(account: AccountInfo | null): void {\n const correlationId = this.getRequestCorrelationId();\n AccountManager.setActiveAccount(\n account,\n this.browserStorage,\n correlationId\n );\n }\n\n /**\n * Gets the currently active account\n */\n getActiveAccount(): AccountInfo | null {\n const correlationId = this.getRequestCorrelationId();\n return AccountManager.getActiveAccount(\n this.browserStorage,\n correlationId\n );\n }\n\n // #endregion\n\n /**\n * Hydrates the cache with the tokens from an AuthenticationResult\n * @param result\n * @param request\n * @returns\n */\n async hydrateCache(\n result: AuthenticationResult,\n request:\n | SilentRequest\n | SsoSilentRequest\n | RedirectRequest\n | PopupRequest\n ): Promise {\n this.logger.verbose(\"hydrateCache called\");\n\n // Account gets saved to browser storage regardless of native or not\n const accountEntity = AccountEntity.createFromAccountInfo(\n result.account,\n result.cloudGraphHostName,\n result.msGraphHost\n );\n await this.browserStorage.setAccount(\n accountEntity,\n result.correlationId\n );\n\n if (result.fromNativeBroker) {\n this.logger.verbose(\n \"Response was from native broker, storing in-memory\"\n );\n // Tokens from native broker are stored in-memory\n return this.nativeInternalStorage.hydrateCache(result, request);\n } else {\n return this.browserStorage.hydrateCache(result, request);\n }\n }\n\n // #region Helpers\n\n /**\n * Acquire a token from native device (e.g. WAM)\n * @param request\n */\n public async acquireTokenNative(\n request: PopupRequest | SilentRequest | SsoSilentRequest,\n apiId: ApiId,\n accountId?: string,\n cacheLookupPolicy?: CacheLookupPolicy\n ): Promise {\n this.logger.trace(\"acquireTokenNative called\");\n if (!this.platformAuthProvider) {\n throw createBrowserAuthError(\n BrowserAuthErrorCodes.nativeConnectionNotEstablished\n );\n }\n const nativeClient = new PlatformAuthInteractionClient(\n this.config,\n this.browserStorage,\n this.browserCrypto,\n this.logger,\n this.eventHandler,\n this.navigationClient,\n apiId,\n this.performanceClient,\n this.platformAuthProvider,\n accountId || this.getNativeAccountId(request),\n this.nativeInternalStorage,\n request.correlationId\n );\n\n return nativeClient.acquireToken(request, cacheLookupPolicy);\n }\n\n /**\n * Returns boolean indicating if this request can use the platform broker\n * @param request\n */\n public canUsePlatformBroker(\n request: RedirectRequest | PopupRequest | SsoSilentRequest,\n accountId?: string\n ): boolean {\n this.logger.trace(\"canUsePlatformBroker called\");\n if (!this.platformAuthProvider) {\n this.logger.trace(\n \"canUsePlatformBroker: platform broker unavilable, returning false\"\n );\n return false;\n }\n\n if (\n !isPlatformAuthAllowed(\n this.config,\n this.logger,\n this.platformAuthProvider,\n request.authenticationScheme\n )\n ) {\n this.logger.trace(\n \"canUsePlatformBroker: isBrokerAvailable returned false, returning false\"\n );\n return false;\n }\n\n if (request.prompt) {\n switch (request.prompt) {\n case PromptValue.NONE:\n case PromptValue.CONSENT:\n case PromptValue.LOGIN:\n this.logger.trace(\n \"canUsePlatformBroker: prompt is compatible with platform broker flow\"\n );\n break;\n default:\n this.logger.trace(\n `canUsePlatformBroker: prompt = ${request.prompt} is not compatible with platform broker flow, returning false`\n );\n return false;\n }\n }\n\n if (!accountId && !this.getNativeAccountId(request)) {\n this.logger.trace(\n \"canUsePlatformBroker: nativeAccountId is not available, returning false\"\n );\n return false;\n }\n\n return true;\n }\n\n /**\n * Get the native accountId from the account\n * @param request\n * @returns\n */\n public getNativeAccountId(\n request: RedirectRequest | PopupRequest | SsoSilentRequest\n ): string {\n const account =\n request.account ||\n this.getAccount({\n loginHint: request.loginHint,\n sid: request.sid,\n }) ||\n this.getActiveAccount();\n\n return (account && account.nativeAccountId) || \"\";\n }\n\n /**\n * Returns new instance of the Popup Interaction Client\n * @param correlationId\n */\n public createPopupClient(correlationId?: string): PopupClient {\n return new PopupClient(\n this.config,\n this.browserStorage,\n this.browserCrypto,\n this.logger,\n this.eventHandler,\n this.navigationClient,\n this.performanceClient,\n this.nativeInternalStorage,\n this.platformAuthProvider,\n correlationId\n );\n }\n\n /**\n * Returns new instance of the Redirect Interaction Client\n * @param correlationId\n */\n protected createRedirectClient(correlationId?: string): RedirectClient {\n return new RedirectClient(\n this.config,\n this.browserStorage,\n this.browserCrypto,\n this.logger,\n this.eventHandler,\n this.navigationClient,\n this.performanceClient,\n this.nativeInternalStorage,\n this.platformAuthProvider,\n correlationId\n );\n }\n\n /**\n * Returns new instance of the Silent Iframe Interaction Client\n * @param correlationId\n */\n public createSilentIframeClient(\n correlationId?: string\n ): SilentIframeClient {\n return new SilentIframeClient(\n this.config,\n this.browserStorage,\n this.browserCrypto,\n this.logger,\n this.eventHandler,\n this.navigationClient,\n ApiId.ssoSilent,\n this.performanceClient,\n this.nativeInternalStorage,\n this.platformAuthProvider,\n correlationId\n );\n }\n\n /**\n * Returns new instance of the Silent Cache Interaction Client\n */\n protected createSilentCacheClient(\n correlationId?: string\n ): SilentCacheClient {\n return new SilentCacheClient(\n this.config,\n this.browserStorage,\n this.browserCrypto,\n this.logger,\n this.eventHandler,\n this.navigationClient,\n this.performanceClient,\n this.platformAuthProvider,\n correlationId\n );\n }\n\n /**\n * Returns new instance of the Silent Refresh Interaction Client\n */\n protected createSilentRefreshClient(\n correlationId?: string\n ): SilentRefreshClient {\n return new SilentRefreshClient(\n this.config,\n this.browserStorage,\n this.browserCrypto,\n this.logger,\n this.eventHandler,\n this.navigationClient,\n this.performanceClient,\n this.platformAuthProvider,\n correlationId\n );\n }\n\n /**\n * Returns new instance of the Silent AuthCode Interaction Client\n */\n protected createSilentAuthCodeClient(\n correlationId?: string\n ): SilentAuthCodeClient {\n return new SilentAuthCodeClient(\n this.config,\n this.browserStorage,\n this.browserCrypto,\n this.logger,\n this.eventHandler,\n this.navigationClient,\n ApiId.acquireTokenByCode,\n this.performanceClient,\n this.platformAuthProvider,\n correlationId\n );\n }\n\n /**\n * Adds event callbacks to array\n * @param callback\n */\n addEventCallback(\n callback: EventCallbackFunction,\n eventTypes?: Array\n ): string | null {\n return this.eventHandler.addEventCallback(callback, eventTypes);\n }\n\n /**\n * Removes callback with provided id from callback array\n * @param callbackId\n */\n removeEventCallback(callbackId: string): void {\n this.eventHandler.removeEventCallback(callbackId);\n }\n\n /**\n * Registers a callback to receive performance events.\n *\n * @param {PerformanceCallbackFunction} callback\n * @returns {string}\n */\n addPerformanceCallback(callback: PerformanceCallbackFunction): string {\n BrowserUtils.blockNonBrowserEnvironment();\n return this.performanceClient.addPerformanceCallback(callback);\n }\n\n /**\n * Removes a callback registered with addPerformanceCallback.\n *\n * @param {string} callbackId\n * @returns {boolean}\n */\n removePerformanceCallback(callbackId: string): boolean {\n return this.performanceClient.removePerformanceCallback(callbackId);\n }\n\n /**\n * Adds event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\n * @deprecated These events will be raised by default and this method will be removed in a future major version.\n */\n enableAccountStorageEvents(): void {\n if (\n this.config.cache.cacheLocation !==\n BrowserCacheLocation.LocalStorage\n ) {\n this.logger.info(\n \"Account storage events are only available when cacheLocation is set to localStorage\"\n );\n return;\n }\n\n this.eventHandler.subscribeCrossTab();\n }\n\n /**\n * Removes event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\n * @deprecated These events will be raised by default and this method will be removed in a future major version.\n */\n disableAccountStorageEvents(): void {\n if (\n this.config.cache.cacheLocation !==\n BrowserCacheLocation.LocalStorage\n ) {\n this.logger.info(\n \"Account storage events are only available when cacheLocation is set to localStorage\"\n );\n return;\n }\n\n this.eventHandler.unsubscribeCrossTab();\n }\n\n /**\n * Gets the token cache for the application.\n */\n getTokenCache(): ITokenCache {\n return this.tokenCache;\n }\n\n /**\n * Returns the logger instance\n */\n public getLogger(): Logger {\n return this.logger;\n }\n\n /**\n * Replaces the default logger set in configurations with new Logger with new configurations\n * @param logger Logger instance\n */\n setLogger(logger: Logger): void {\n this.logger = logger;\n }\n\n /**\n * Called by wrapper libraries (Angular & React) to set SKU and Version passed down to telemetry, logger, etc.\n * @param sku\n * @param version\n */\n initializeWrapperLibrary(sku: WrapperSKU, version: string): void {\n // Validate the SKU passed in is one we expect\n this.browserStorage.setWrapperMetadata(sku, version);\n }\n\n /**\n * Sets navigation client\n * @param navigationClient\n */\n setNavigationClient(navigationClient: INavigationClient): void {\n this.navigationClient = navigationClient;\n }\n\n /**\n * Returns the configuration object\n */\n public getConfiguration(): BrowserConfiguration {\n return this.config;\n }\n\n /**\n * Returns the performance client\n */\n public getPerformanceClient(): IPerformanceClient {\n return this.performanceClient;\n }\n\n /**\n * Returns the browser env indicator\n */\n public isBrowserEnv(): boolean {\n return this.isBrowserEnvironment;\n }\n\n /**\n * Generates a correlation id for a request if none is provided.\n *\n * @protected\n * @param {?Partial} [request]\n * @returns {string}\n */\n protected getRequestCorrelationId(\n request?: Partial\n ): string {\n if (request?.correlationId) {\n return request.correlationId;\n }\n\n if (this.isBrowserEnvironment) {\n return createNewGuid();\n }\n\n /*\n * Included for fallback for non-browser environments,\n * and to ensure this method always returns a string.\n */\n return Constants.EMPTY_STRING;\n }\n\n // #endregion\n\n /**\n * Use when initiating the login process by redirecting the user's browser to the authorization endpoint. This function redirects the page, so\n * any code that follows this function will not execute.\n *\n * IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current\n * browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.\n *\n * @param request\n */\n async loginRedirect(request?: RedirectRequest): Promise {\n const correlationId: string = this.getRequestCorrelationId(request);\n this.logger.verbose(\"loginRedirect called\", correlationId);\n return this.acquireTokenRedirect({\n correlationId,\n ...(request || DEFAULT_REQUEST),\n });\n }\n\n /**\n * Use when initiating the login process via opening a popup window in the user's browser\n *\n * @param request\n *\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\n */\n loginPopup(request?: PopupRequest): Promise {\n const correlationId: string = this.getRequestCorrelationId(request);\n this.logger.verbose(\"loginPopup called\", correlationId);\n return this.acquireTokenPopup({\n correlationId,\n ...(request || DEFAULT_REQUEST),\n });\n }\n\n /**\n * Silently acquire an access token for a given set of scopes. Returns currently processing promise if parallel requests are made.\n *\n * @param {@link (SilentRequest:type)}\n * @returns {Promise.} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object\n */\n async acquireTokenSilent(\n request: SilentRequest\n ): Promise {\n const correlationId = this.getRequestCorrelationId(request);\n const atsMeasurement = this.performanceClient.startMeasurement(\n PerformanceEvents.AcquireTokenSilent,\n correlationId\n );\n atsMeasurement.add({\n cacheLookupPolicy: request.cacheLookupPolicy,\n scenarioId: request.scenarioId,\n });\n\n preflightCheck(this.initialized, atsMeasurement);\n this.logger.verbose(\"acquireTokenSilent called\", correlationId);\n\n const account = request.account || this.getActiveAccount();\n if (!account) {\n throw createBrowserAuthError(BrowserAuthErrorCodes.noAccountError);\n }\n atsMeasurement.add({ accountType: getAccountType(account) });\n\n return this.acquireTokenSilentDeduped(request, account, correlationId)\n .then((result) => {\n atsMeasurement.end({\n success: true,\n fromCache: result.fromCache,\n accessTokenSize: result.accessToken.length,\n idTokenSize: result.idToken.length,\n });\n return {\n ...result,\n state: request.state,\n correlationId: correlationId, // Ensures PWB scenarios can correctly match request to response\n };\n })\n .catch((error: Error) => {\n if (error instanceof AuthError) {\n // Ensures PWB scenarios can correctly match request to response\n error.setCorrelationId(correlationId);\n }\n\n atsMeasurement.end(\n {\n success: false,\n },\n error\n );\n throw error;\n });\n }\n\n /**\n * Checks if identical request is already in flight and returns reference to the existing promise or fires off a new one if this is the first\n * @param request\n * @param account\n * @param correlationId\n * @returns\n */\n private async acquireTokenSilentDeduped(\n request: SilentRequest,\n account: AccountInfo,\n correlationId: string\n ): Promise {\n const thumbprint = getRequestThumbprint(\n this.config.auth.clientId,\n {\n ...request,\n authority: request.authority || this.config.auth.authority,\n correlationId: correlationId,\n },\n account.homeAccountId\n );\n const silentRequestKey = JSON.stringify(thumbprint);\n\n const inProgressRequest =\n this.activeSilentTokenRequests.get(silentRequestKey);\n\n if (typeof inProgressRequest === \"undefined\") {\n this.logger.verbose(\n \"acquireTokenSilent called for the first time, storing active request\",\n correlationId\n );\n this.performanceClient.addFields({ deduped: false }, correlationId);\n\n const activeRequest = invokeAsync(\n this.acquireTokenSilentAsync.bind(this),\n PerformanceEvents.AcquireTokenSilentAsync,\n this.logger,\n this.performanceClient,\n correlationId\n )(\n {\n ...request,\n correlationId,\n },\n account\n );\n this.activeSilentTokenRequests.set(silentRequestKey, activeRequest);\n\n return activeRequest.finally(() => {\n this.activeSilentTokenRequests.delete(silentRequestKey);\n });\n } else {\n this.logger.verbose(\n \"acquireTokenSilent has been called previously, returning the result from the first call\",\n correlationId\n );\n this.performanceClient.addFields({ deduped: true }, correlationId);\n return inProgressRequest;\n }\n }\n\n /**\n * Silently acquire an access token for a given set of scopes. Will use cached token if available, otherwise will attempt to acquire a new token from the network via refresh token.\n * @param {@link (SilentRequest:type)}\n * @param {@link (AccountInfo:type)}\n * @returns {Promise.} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse}\n */\n protected async acquireTokenSilentAsync(\n request: SilentRequest & { correlationId: string },\n account: AccountInfo\n ): Promise {\n const trackPageVisibility = () =>\n this.trackPageVisibility(request.correlationId);\n this.performanceClient.addQueueMeasurement(\n PerformanceEvents.AcquireTokenSilentAsync,\n request.correlationId\n );\n\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_START,\n InteractionType.Silent,\n request\n );\n\n if (request.correlationId) {\n this.performanceClient.incrementFields(\n { visibilityChangeCount: 0 },\n request.correlationId\n );\n }\n\n document.addEventListener(\"visibilitychange\", trackPageVisibility);\n\n const silentRequest = await invokeAsync(\n initializeSilentRequest,\n PerformanceEvents.InitializeSilentRequest,\n this.logger,\n this.performanceClient,\n request.correlationId\n )(request, account, this.config, this.performanceClient, this.logger);\n const cacheLookupPolicy =\n request.cacheLookupPolicy || CacheLookupPolicy.Default;\n\n const result = this.acquireTokenSilentNoIframe(\n silentRequest,\n cacheLookupPolicy\n ).catch(async (refreshTokenError: AuthError) => {\n const shouldTryToResolveSilently =\n checkIfRefreshTokenErrorCanBeResolvedSilently(\n refreshTokenError,\n cacheLookupPolicy\n );\n\n if (shouldTryToResolveSilently) {\n if (!this.activeIframeRequest) {\n let _resolve: (result: boolean) => void;\n // Always set the active request tracker immediately after checking it to prevent races\n this.activeIframeRequest = [\n new Promise((resolve) => {\n _resolve = resolve;\n }),\n silentRequest.correlationId,\n ];\n this.logger.verbose(\n \"Refresh token expired/invalid or CacheLookupPolicy is set to Skip, attempting acquire token by iframe.\",\n silentRequest.correlationId\n );\n return invokeAsync(\n this.acquireTokenBySilentIframe.bind(this),\n PerformanceEvents.AcquireTokenBySilentIframe,\n this.logger,\n this.performanceClient,\n silentRequest.correlationId\n )(silentRequest)\n .then((iframeResult) => {\n _resolve(true);\n return iframeResult;\n })\n .catch((e) => {\n _resolve(false);\n throw e;\n })\n .finally(() => {\n this.activeIframeRequest = undefined;\n });\n } else if (cacheLookupPolicy !== CacheLookupPolicy.Skip) {\n const [activePromise, activeCorrelationId] =\n this.activeIframeRequest;\n this.logger.verbose(\n `Iframe request is already in progress, awaiting resolution for request with correlationId: ${activeCorrelationId}`,\n silentRequest.correlationId\n );\n const awaitConcurrentIframeMeasure =\n this.performanceClient.startMeasurement(\n PerformanceEvents.AwaitConcurrentIframe,\n silentRequest.correlationId\n );\n awaitConcurrentIframeMeasure.add({\n awaitIframeCorrelationId: activeCorrelationId,\n });\n\n const activePromiseResult = await activePromise;\n awaitConcurrentIframeMeasure.end({\n success: activePromiseResult,\n });\n if (activePromiseResult) {\n this.logger.verbose(\n `Parallel iframe request with correlationId: ${activeCorrelationId} succeeded. Retrying cache and/or RT redemption`,\n silentRequest.correlationId\n );\n // Retry cache lookup and/or RT exchange after iframe completes\n return this.acquireTokenSilentNoIframe(\n silentRequest,\n cacheLookupPolicy\n );\n } else {\n this.logger.info(\n `Iframe request with correlationId: ${activeCorrelationId} failed. Interaction is required.`\n );\n // If previous iframe request failed, it's unlikely to succeed this time. Throw original error.\n throw refreshTokenError;\n }\n } else {\n // Cache policy set to skip and another iframe request is already in progress\n this.logger.warning(\n \"Another iframe request is currently in progress and CacheLookupPolicy is set to Skip. This may result in degraded performance and/or reliability for both calls. Please consider changing the CacheLookupPolicy to take advantage of request queuing and token cache.\",\n silentRequest.correlationId\n );\n return invokeAsync(\n this.acquireTokenBySilentIframe.bind(this),\n PerformanceEvents.AcquireTokenBySilentIframe,\n this.logger,\n this.performanceClient,\n silentRequest.correlationId\n )(silentRequest);\n }\n } else {\n // Error cannot be silently resolved or iframe renewal is not allowed, interaction required\n throw refreshTokenError;\n }\n });\n\n return result\n .then((response) => {\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_SUCCESS,\n InteractionType.Silent,\n response\n );\n if (request.correlationId) {\n this.performanceClient.addFields(\n {\n fromCache: response.fromCache,\n },\n request.correlationId\n );\n }\n\n return response;\n })\n .catch((tokenRenewalError: Error) => {\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_FAILURE,\n InteractionType.Silent,\n null,\n tokenRenewalError\n );\n throw tokenRenewalError;\n })\n .finally(() => {\n document.removeEventListener(\n \"visibilitychange\",\n trackPageVisibility\n );\n });\n }\n\n /**\n * AcquireTokenSilent without the iframe fallback. This is used to enable the correct fallbacks in cases where there's a potential for multiple silent requests to be made in parallel and prevent those requests from making concurrent iframe requests.\n * @param silentRequest\n * @param cacheLookupPolicy\n * @returns\n */\n private async acquireTokenSilentNoIframe(\n silentRequest: CommonSilentFlowRequest,\n cacheLookupPolicy: CacheLookupPolicy\n ): Promise {\n // if the cache policy is set to access_token only, we should not be hitting the native layer yet\n if (\n isPlatformAuthAllowed(\n this.config,\n this.logger,\n this.platformAuthProvider,\n silentRequest.authenticationScheme\n ) &&\n silentRequest.account.nativeAccountId\n ) {\n this.logger.verbose(\n \"acquireTokenSilent - attempting to acquire token from native platform\"\n );\n this.performanceClient.addFields(\n { isPlatformBrokerRequest: true },\n silentRequest.correlationId\n );\n return this.acquireTokenNative(\n silentRequest,\n ApiId.acquireTokenSilent_silentFlow,\n silentRequest.account.nativeAccountId,\n cacheLookupPolicy\n ).catch(async (e: AuthError) => {\n this.performanceClient.addFields(\n {\n brokerErrorName: e.name,\n brokerErrorCode: e.errorCode,\n },\n silentRequest.correlationId\n );\n // If native token acquisition fails for availability reasons fallback to web flow\n if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {\n this.logger.verbose(\n \"acquireTokenSilent - native platform unavailable, falling back to web flow\"\n );\n this.platformAuthProvider = undefined; // Prevent future requests from continuing to attempt\n // Cache will not contain tokens, given that previous WAM requests succeeded. Skip cache and RT renewal and go straight to iframe renewal\n throw createClientAuthError(\n ClientAuthErrorCodes.tokenRefreshRequired\n );\n }\n throw e;\n });\n } else {\n this.logger.verbose(\n \"acquireTokenSilent - attempting to acquire token from web flow\"\n );\n // add logs to identify embedded cache retrieval\n if (cacheLookupPolicy === CacheLookupPolicy.AccessToken) {\n this.logger.verbose(\n \"acquireTokenSilent - cache lookup policy set to AccessToken, attempting to acquire token from local cache\"\n );\n }\n return invokeAsync(\n this.acquireTokenFromCache.bind(this),\n PerformanceEvents.AcquireTokenFromCache,\n this.logger,\n this.performanceClient,\n silentRequest.correlationId\n )(silentRequest, cacheLookupPolicy).catch(\n (cacheError: AuthError) => {\n if (cacheLookupPolicy === CacheLookupPolicy.AccessToken) {\n throw cacheError;\n }\n\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_NETWORK_START,\n InteractionType.Silent,\n silentRequest\n );\n\n return invokeAsync(\n this.acquireTokenByRefreshToken.bind(this),\n PerformanceEvents.AcquireTokenByRefreshToken,\n this.logger,\n this.performanceClient,\n silentRequest.correlationId\n )(silentRequest, cacheLookupPolicy);\n }\n );\n }\n }\n\n /**\n * Pre-generates PKCE codes and stores it in local variable\n * @param correlationId\n */\n private async preGeneratePkceCodes(correlationId: string): Promise {\n this.logger.verbose(\"Generating new PKCE codes\");\n this.pkceCode = await invokeAsync(\n generatePkceCodes,\n PerformanceEvents.GeneratePkceCodes,\n this.logger,\n this.performanceClient,\n correlationId\n )(this.performanceClient, this.logger, correlationId);\n return Promise.resolve();\n }\n\n /**\n * Provides pre-generated PKCE codes, if any\n * @param correlationId\n */\n private getPreGeneratedPkceCodes(\n correlationId: string\n ): PkceCodes | undefined {\n this.logger.verbose(\"Attempting to pick up pre-generated PKCE codes\");\n const res = this.pkceCode ? { ...this.pkceCode } : undefined;\n this.pkceCode = undefined;\n this.logger.verbose(\n `${res ? \"Found\" : \"Did not find\"} pre-generated PKCE codes`\n );\n this.performanceClient.addFields(\n { usePreGeneratedPkce: !!res },\n correlationId\n );\n return res;\n }\n\n private logMultipleInstances(\n performanceEvent: InProgressPerformanceEvent\n ): void {\n const clientId = this.config.auth.clientId;\n\n if (!window) return;\n // @ts-ignore\n window.msal = window.msal || {};\n // @ts-ignore\n window.msal.clientIds = window.msal.clientIds || [];\n\n // @ts-ignore\n const clientIds: string[] = window.msal.clientIds;\n\n if (clientIds.length > 0) {\n this.logger.verbose(\n \"There is already an instance of MSAL.js in the window.\"\n );\n }\n // @ts-ignore\n window.msal.clientIds.push(clientId);\n collectInstanceStats(clientId, performanceEvent, this.logger);\n }\n}\n\n/**\n * Determines whether an error thrown by the refresh token endpoint can be resolved without interaction\n * @param refreshTokenError\n * @param silentRequest\n * @param cacheLookupPolicy\n * @returns\n */\nfunction checkIfRefreshTokenErrorCanBeResolvedSilently(\n refreshTokenError: AuthError,\n cacheLookupPolicy: CacheLookupPolicy\n): boolean {\n const noInteractionRequired = !(\n refreshTokenError instanceof InteractionRequiredAuthError &&\n // For refresh token errors, bad_token does not always require interaction (silently resolvable)\n refreshTokenError.subError !==\n InteractionRequiredAuthErrorCodes.badToken\n );\n\n // Errors that result when the refresh token needs to be replaced\n const refreshTokenRefreshRequired =\n refreshTokenError.errorCode === BrowserConstants.INVALID_GRANT_ERROR ||\n refreshTokenError.errorCode ===\n ClientAuthErrorCodes.tokenRefreshRequired;\n\n // Errors that may be resolved before falling back to interaction (through iframe renewal)\n const isSilentlyResolvable =\n (noInteractionRequired && refreshTokenRefreshRequired) ||\n refreshTokenError.errorCode ===\n InteractionRequiredAuthErrorCodes.noTokensFound ||\n refreshTokenError.errorCode ===\n InteractionRequiredAuthErrorCodes.refreshTokenExpired;\n\n // Only these policies allow for an iframe renewal attempt\n const tryIframeRenewal = iFrameRenewalPolicies.includes(cacheLookupPolicy);\n\n return isSilentlyResolvable && tryIframeRenewal;\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { BridgeStatusCode } from \"./BridgeStatusCode.js\";\n\nexport type BridgeError = {\n status: BridgeStatusCode;\n code?: string; // auth_flow_last_error such as invalid_grant\n subError?: string; // server_suberror_code such as consent_required\n description?: string;\n properties?: object; // additional telemetry info\n};\n\nexport function isBridgeError(error: unknown): error is BridgeError {\n return (error as BridgeError).status !== undefined;\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TokenRequest } from \"../TokenRequest.js\";\nimport { AccountInfo as NaaAccountInfo } from \"../AccountInfo.js\";\nimport { RedirectRequest } from \"../../request/RedirectRequest.js\";\nimport { PopupRequest } from \"../../request/PopupRequest.js\";\nimport {\n AccountInfo as MsalAccountInfo,\n AuthError,\n ClientAuthError,\n ClientConfigurationError,\n InteractionRequiredAuthError,\n ServerError,\n ICrypto,\n Logger,\n AuthToken,\n TokenClaims,\n ClientAuthErrorCodes,\n AuthenticationScheme,\n RequestParameterBuilder,\n StringUtils,\n createClientAuthError,\n OIDC_DEFAULT_SCOPES,\n AccountInfo,\n IdTokenEntity,\n AccessTokenEntity,\n TenantProfile,\n buildTenantProfile,\n TimeUtils,\n} from \"@azure/msal-common/browser\";\nimport { isBridgeError } from \"../BridgeError.js\";\nimport { BridgeStatusCode } from \"../BridgeStatusCode.js\";\nimport { AuthenticationResult } from \"../../response/AuthenticationResult.js\";\nimport {} from \"../../error/BrowserAuthErrorCodes.js\";\nimport { AuthResult } from \"../AuthResult.js\";\nimport { SsoSilentRequest } from \"../../request/SsoSilentRequest.js\";\nimport { SilentRequest } from \"../../request/SilentRequest.js\";\n\nexport class NestedAppAuthAdapter {\n protected crypto: ICrypto;\n protected logger: Logger;\n protected clientId: string;\n protected clientCapabilities: string[];\n\n constructor(\n clientId: string,\n clientCapabilities: string[],\n crypto: ICrypto,\n logger: Logger\n ) {\n this.clientId = clientId;\n this.clientCapabilities = clientCapabilities;\n this.crypto = crypto;\n this.logger = logger;\n }\n\n public toNaaTokenRequest(\n request:\n | PopupRequest\n | RedirectRequest\n | SilentRequest\n | SsoSilentRequest\n ): TokenRequest {\n let extraParams: Map;\n if (request.extraQueryParameters === undefined) {\n extraParams = new Map();\n } else {\n extraParams = new Map(\n Object.entries(request.extraQueryParameters)\n );\n }\n\n const correlationId =\n request.correlationId || this.crypto.createNewGuid();\n const claims = RequestParameterBuilder.addClientCapabilitiesToClaims(\n request.claims,\n this.clientCapabilities\n );\n const scopes = request.scopes || OIDC_DEFAULT_SCOPES;\n const tokenRequest: TokenRequest = {\n platformBrokerId: request.account?.homeAccountId,\n clientId: this.clientId,\n authority: request.authority,\n scope: scopes.join(\" \"),\n correlationId,\n claims: !StringUtils.isEmptyObj(claims) ? claims : undefined,\n state: request.state,\n authenticationScheme:\n request.authenticationScheme || AuthenticationScheme.BEARER,\n extraParameters: extraParams,\n };\n\n return tokenRequest;\n }\n\n public fromNaaTokenResponse(\n request: TokenRequest,\n response: AuthResult,\n reqTimestamp: number\n ): AuthenticationResult {\n if (!response.token.id_token || !response.token.access_token) {\n throw createClientAuthError(ClientAuthErrorCodes.nullOrEmptyToken);\n }\n\n // Request timestamp and AuthResult expires_in are in seconds, converting to Date for AuthenticationResult\n const expiresOn = TimeUtils.toDateFromSeconds(\n reqTimestamp + (response.token.expires_in || 0)\n );\n const idTokenClaims = AuthToken.extractTokenClaims(\n response.token.id_token,\n this.crypto.base64Decode\n );\n const account = this.fromNaaAccountInfo(\n response.account,\n response.token.id_token,\n idTokenClaims\n );\n const scopes = response.token.scope || request.scope;\n\n const authenticationResult: AuthenticationResult = {\n authority: response.token.authority || account.environment,\n uniqueId: account.localAccountId,\n tenantId: account.tenantId,\n scopes: scopes.split(\" \"),\n account,\n idToken: response.token.id_token,\n idTokenClaims,\n accessToken: response.token.access_token,\n fromCache: false,\n expiresOn: expiresOn,\n tokenType:\n request.authenticationScheme || AuthenticationScheme.BEARER,\n correlationId: request.correlationId,\n extExpiresOn: expiresOn,\n state: request.state,\n };\n\n return authenticationResult;\n }\n\n /*\n * export type AccountInfo = {\n * homeAccountId: string;\n * environment: string;\n * tenantId: string;\n * username: string;\n * localAccountId: string;\n * name?: string;\n * idToken?: string;\n * idTokenClaims?: TokenClaims & {\n * [key: string]:\n * | string\n * | number\n * | string[]\n * | object\n * | undefined\n * | unknown;\n * };\n * nativeAccountId?: string;\n * authorityType?: string;\n * };\n */\n public fromNaaAccountInfo(\n fromAccount: NaaAccountInfo,\n idToken?: string,\n idTokenClaims?: TokenClaims\n ): MsalAccountInfo {\n const effectiveIdTokenClaims =\n idTokenClaims || (fromAccount.idTokenClaims as TokenClaims);\n\n const localAccountId =\n fromAccount.localAccountId ||\n effectiveIdTokenClaims?.oid ||\n effectiveIdTokenClaims?.sub ||\n \"\";\n\n const tenantId =\n fromAccount.tenantId || effectiveIdTokenClaims?.tid || \"\";\n\n const homeAccountId =\n fromAccount.homeAccountId || `${localAccountId}.${tenantId}`;\n\n const username =\n fromAccount.username ||\n effectiveIdTokenClaims?.preferred_username ||\n \"\";\n\n const name = fromAccount.name || effectiveIdTokenClaims?.name;\n\n const loginHint =\n fromAccount.loginHint || effectiveIdTokenClaims?.login_hint;\n\n const tenantProfiles = new Map();\n\n const tenantProfile = buildTenantProfile(\n homeAccountId,\n localAccountId,\n tenantId,\n effectiveIdTokenClaims\n );\n tenantProfiles.set(tenantId, tenantProfile);\n\n const account: MsalAccountInfo = {\n homeAccountId,\n environment: fromAccount.environment,\n tenantId,\n username,\n localAccountId,\n name,\n loginHint,\n idToken: idToken,\n idTokenClaims: effectiveIdTokenClaims,\n tenantProfiles,\n };\n\n return account;\n }\n\n /**\n *\n * @param error BridgeError\n * @returns AuthError, ClientAuthError, ClientConfigurationError, ServerError, InteractionRequiredError\n */\n public fromBridgeError(\n error: unknown\n ):\n | AuthError\n | ClientAuthError\n | ClientConfigurationError\n | ServerError\n | InteractionRequiredAuthError {\n if (isBridgeError(error)) {\n switch (error.status) {\n case BridgeStatusCode.UserCancel:\n return new ClientAuthError(\n ClientAuthErrorCodes.userCanceled\n );\n case BridgeStatusCode.NoNetwork:\n return new ClientAuthError(\n ClientAuthErrorCodes.noNetworkConnectivity\n );\n case BridgeStatusCode.AccountUnavailable:\n return new ClientAuthError(\n ClientAuthErrorCodes.noAccountFound\n );\n case BridgeStatusCode.Disabled:\n return new ClientAuthError(\n ClientAuthErrorCodes.nestedAppAuthBridgeDisabled\n );\n case BridgeStatusCode.NestedAppAuthUnavailable:\n return new ClientAuthError(\n error.code ||\n ClientAuthErrorCodes.nestedAppAuthBridgeDisabled,\n error.description\n );\n case BridgeStatusCode.TransientError:\n case BridgeStatusCode.PersistentError:\n return new ServerError(error.code, error.description);\n case BridgeStatusCode.UserInteractionRequired:\n return new InteractionRequiredAuthError(\n error.code,\n error.description\n );\n default:\n return new AuthError(error.code, error.description);\n }\n } else {\n return new AuthError(\"unknown_error\", \"An unknown error occurred\");\n }\n }\n\n /**\n * Returns an AuthenticationResult from the given cache items\n *\n * @param account\n * @param idToken\n * @param accessToken\n * @param reqTimestamp\n * @returns\n */\n public toAuthenticationResultFromCache(\n account: AccountInfo,\n idToken: IdTokenEntity,\n accessToken: AccessTokenEntity,\n request: SilentRequest,\n correlationId: string\n ): AuthenticationResult {\n if (!idToken || !accessToken) {\n throw createClientAuthError(ClientAuthErrorCodes.nullOrEmptyToken);\n }\n\n const idTokenClaims = AuthToken.extractTokenClaims(\n idToken.secret,\n this.crypto.base64Decode\n );\n\n const scopes = accessToken.target || request.scopes.join(\" \");\n\n const authenticationResult: AuthenticationResult = {\n authority: accessToken.environment || account.environment,\n uniqueId: account.localAccountId,\n tenantId: account.tenantId,\n scopes: scopes.split(\" \"),\n account,\n idToken: idToken.secret,\n idTokenClaims: idTokenClaims || {},\n accessToken: accessToken.secret,\n fromCache: true,\n expiresOn: TimeUtils.toDateFromSeconds(accessToken.expiresOn),\n extExpiresOn: TimeUtils.toDateFromSeconds(\n accessToken.extendedExpiresOn\n ),\n tokenType:\n request.authenticationScheme || AuthenticationScheme.BEARER,\n correlationId,\n state: request.state,\n };\n\n return authenticationResult;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthError } from \"@azure/msal-common/browser\";\n\n/**\n * NestedAppAuthErrorMessage class containing string constants used by error codes and messages.\n */\nexport const NestedAppAuthErrorMessage = {\n unsupportedMethod: {\n code: \"unsupported_method\",\n desc: \"This method is not supported in nested app environment.\",\n },\n};\n\nexport class NestedAppAuthError extends AuthError {\n constructor(errorCode: string, errorMessage?: string) {\n super(errorCode, errorMessage);\n\n Object.setPrototypeOf(this, NestedAppAuthError.prototype);\n this.name = \"NestedAppAuthError\";\n }\n\n public static createUnsupportedError(): NestedAppAuthError {\n return new NestedAppAuthError(\n NestedAppAuthErrorMessage.unsupportedMethod.code,\n NestedAppAuthErrorMessage.unsupportedMethod.desc\n );\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n CommonAuthorizationUrlRequest,\n CommonSilentFlowRequest,\n PerformanceCallbackFunction,\n AccountInfo,\n Logger,\n ICrypto,\n IPerformanceClient,\n DEFAULT_CRYPTO_IMPLEMENTATION,\n PerformanceEvents,\n TimeUtils,\n buildStaticAuthorityOptions,\n AccountEntity,\n OIDC_DEFAULT_SCOPES,\n BaseAuthRequest,\n AccountFilter,\n AuthError,\n} from \"@azure/msal-common/browser\";\nimport { ITokenCache } from \"../cache/ITokenCache.js\";\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\nimport { EndSessionPopupRequest } from \"../request/EndSessionPopupRequest.js\";\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\nimport { PopupRequest } from \"../request/PopupRequest.js\";\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\nimport { SilentRequest } from \"../request/SilentRequest.js\";\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\nimport {\n ApiId,\n WrapperSKU,\n InteractionType,\n DEFAULT_REQUEST,\n CacheLookupPolicy,\n} from \"../utils/BrowserConstants.js\";\nimport { IController } from \"./IController.js\";\nimport { NestedAppOperatingContext } from \"../operatingcontext/NestedAppOperatingContext.js\";\nimport { IBridgeProxy } from \"../naa/IBridgeProxy.js\";\nimport { CryptoOps } from \"../crypto/CryptoOps.js\";\nimport { NestedAppAuthAdapter } from \"../naa/mapping/NestedAppAuthAdapter.js\";\nimport { NestedAppAuthError } from \"../error/NestedAppAuthError.js\";\nimport { EventHandler } from \"../event/EventHandler.js\";\nimport { EventType } from \"../event/EventType.js\";\nimport { EventCallbackFunction, EventError } from \"../event/EventMessage.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport {\n BrowserCacheManager,\n DEFAULT_BROWSER_CACHE_MANAGER,\n} from \"../cache/BrowserCacheManager.js\";\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\nimport * as AccountManager from \"../cache/AccountManager.js\";\nimport { AccountContext } from \"../naa/BridgeAccountContext.js\";\nimport { InitializeApplicationRequest } from \"../request/InitializeApplicationRequest.js\";\nimport { createNewGuid } from \"../crypto/BrowserCrypto.js\";\n\nexport class NestedAppAuthController implements IController {\n // OperatingContext\n protected readonly operatingContext: NestedAppOperatingContext;\n\n // BridgeProxy\n protected readonly bridgeProxy: IBridgeProxy;\n\n // Crypto interface implementation\n protected readonly browserCrypto: ICrypto;\n\n // Input configuration by developer/user\n protected readonly config: BrowserConfiguration;\n\n // Storage interface implementation\n protected readonly browserStorage!: BrowserCacheManager;\n\n // Logger\n protected logger: Logger;\n\n // Performance telemetry client\n protected readonly performanceClient: IPerformanceClient;\n\n // EventHandler\n protected readonly eventHandler: EventHandler;\n\n // NestedAppAuthAdapter\n protected readonly nestedAppAuthAdapter: NestedAppAuthAdapter;\n\n // currentAccount for NAA apps\n protected currentAccountContext: AccountContext | null;\n\n constructor(operatingContext: NestedAppOperatingContext) {\n this.operatingContext = operatingContext;\n const proxy = this.operatingContext.getBridgeProxy();\n if (proxy !== undefined) {\n this.bridgeProxy = proxy;\n } else {\n throw new Error(\"unexpected: bridgeProxy is undefined\");\n }\n\n // Set the configuration.\n this.config = operatingContext.getConfig();\n\n // Initialize logger\n this.logger = this.operatingContext.getLogger();\n\n // Initialize performance client\n this.performanceClient = this.config.telemetry.client;\n\n // Initialize the crypto class.\n this.browserCrypto = operatingContext.isBrowserEnvironment()\n ? new CryptoOps(this.logger, this.performanceClient, true)\n : DEFAULT_CRYPTO_IMPLEMENTATION;\n\n this.eventHandler = new EventHandler(this.logger);\n // Initialize the browser storage class.\n this.browserStorage = this.operatingContext.isBrowserEnvironment()\n ? new BrowserCacheManager(\n this.config.auth.clientId,\n this.config.cache,\n this.browserCrypto,\n this.logger,\n this.performanceClient,\n this.eventHandler,\n buildStaticAuthorityOptions(this.config.auth)\n )\n : DEFAULT_BROWSER_CACHE_MANAGER(\n this.config.auth.clientId,\n this.logger,\n this.performanceClient,\n this.eventHandler\n );\n\n this.nestedAppAuthAdapter = new NestedAppAuthAdapter(\n this.config.auth.clientId,\n this.config.auth.clientCapabilities,\n this.browserCrypto,\n this.logger\n );\n\n // Set the active account if available\n const accountContext = this.bridgeProxy.getAccountContext();\n this.currentAccountContext = accountContext ? accountContext : null;\n }\n\n /**\n * Factory function to create a new instance of NestedAppAuthController\n * @param operatingContext\n * @returns Promise\n */\n static async createController(\n operatingContext: NestedAppOperatingContext\n ): Promise {\n const controller = new NestedAppAuthController(operatingContext);\n return Promise.resolve(controller);\n }\n\n /**\n * Specific implementation of initialize function for NestedAppAuthController\n * @returns\n */\n async initialize(\n request?: InitializeApplicationRequest,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n isBroker?: boolean\n ): Promise {\n const initCorrelationId = request?.correlationId || createNewGuid();\n await this.browserStorage.initialize(initCorrelationId);\n return Promise.resolve();\n }\n\n /**\n * Validate the incoming request and add correlationId if not present\n * @param request\n * @returns\n */\n private ensureValidRequest<\n T extends\n | SsoSilentRequest\n | SilentRequest\n | PopupRequest\n | RedirectRequest\n >(request: T): T {\n if (request?.correlationId) {\n return request;\n }\n return {\n ...request,\n correlationId: this.browserCrypto.createNewGuid(),\n };\n }\n\n /**\n * Internal implementation of acquireTokenInteractive flow\n * @param request\n * @returns\n */\n private async acquireTokenInteractive(\n request: PopupRequest | RedirectRequest\n ): Promise {\n const validRequest = this.ensureValidRequest(request);\n\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_START,\n InteractionType.Popup,\n validRequest\n );\n\n const atPopupMeasurement = this.performanceClient.startMeasurement(\n PerformanceEvents.AcquireTokenPopup,\n validRequest.correlationId\n );\n\n atPopupMeasurement?.add({ nestedAppAuthRequest: true });\n\n try {\n const naaRequest =\n this.nestedAppAuthAdapter.toNaaTokenRequest(validRequest);\n const reqTimestamp = TimeUtils.nowSeconds();\n const response = await this.bridgeProxy.getTokenInteractive(\n naaRequest\n );\n const result: AuthenticationResult = {\n ...this.nestedAppAuthAdapter.fromNaaTokenResponse(\n naaRequest,\n response,\n reqTimestamp\n ),\n };\n\n // cache the tokens in the response\n try {\n // cache hydration can fail in JS Runtime scenario that doesn't support full crypto API\n await this.hydrateCache(result, request);\n } catch (error) {\n this.logger.warningPii(\n `Failed to hydrate cache. Error: ${error}`,\n validRequest.correlationId\n );\n }\n\n // cache the account context in memory after successful token fetch\n this.currentAccountContext = {\n homeAccountId: result.account.homeAccountId,\n environment: result.account.environment,\n tenantId: result.account.tenantId,\n };\n\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_SUCCESS,\n InteractionType.Popup,\n result\n );\n\n atPopupMeasurement.add({\n accessTokenSize: result.accessToken.length,\n idTokenSize: result.idToken.length,\n });\n\n atPopupMeasurement.end({\n success: true,\n requestId: result.requestId,\n });\n\n return result;\n } catch (e) {\n const error =\n e instanceof AuthError\n ? e\n : this.nestedAppAuthAdapter.fromBridgeError(e);\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_FAILURE,\n InteractionType.Popup,\n null,\n e as EventError\n );\n\n atPopupMeasurement.end(\n {\n success: false,\n },\n e\n );\n\n throw error;\n }\n }\n\n /**\n * Internal implementation of acquireTokenSilent flow\n * @param request\n * @returns\n */\n private async acquireTokenSilentInternal(\n request: SilentRequest\n ): Promise {\n const validRequest = this.ensureValidRequest(request);\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_START,\n InteractionType.Silent,\n validRequest\n );\n\n // Look for tokens in the cache first\n const result = await this.acquireTokenFromCache(validRequest);\n if (result) {\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_SUCCESS,\n InteractionType.Silent,\n result\n );\n return result;\n }\n\n // proceed with acquiring tokens via the host\n const ssoSilentMeasurement = this.performanceClient.startMeasurement(\n PerformanceEvents.SsoSilent,\n validRequest.correlationId\n );\n\n ssoSilentMeasurement?.increment({\n visibilityChangeCount: 0,\n });\n\n ssoSilentMeasurement?.add({\n nestedAppAuthRequest: true,\n });\n\n try {\n const naaRequest =\n this.nestedAppAuthAdapter.toNaaTokenRequest(validRequest);\n const reqTimestamp = TimeUtils.nowSeconds();\n const response = await this.bridgeProxy.getTokenSilent(naaRequest);\n\n const result: AuthenticationResult =\n this.nestedAppAuthAdapter.fromNaaTokenResponse(\n naaRequest,\n response,\n reqTimestamp\n );\n\n // cache the tokens in the response\n try {\n // cache hydration can fail in JS Runtime scenario that doesn't support full crypto API\n await this.hydrateCache(result, request);\n } catch (error) {\n this.logger.warningPii(\n `Failed to hydrate cache. Error: ${error}`,\n validRequest.correlationId\n );\n }\n\n // cache the account context in memory after successful token fetch\n this.currentAccountContext = {\n homeAccountId: result.account.homeAccountId,\n environment: result.account.environment,\n tenantId: result.account.tenantId,\n };\n\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_SUCCESS,\n InteractionType.Silent,\n result\n );\n ssoSilentMeasurement?.add({\n accessTokenSize: result.accessToken.length,\n idTokenSize: result.idToken.length,\n });\n ssoSilentMeasurement?.end({\n success: true,\n requestId: result.requestId,\n });\n return result;\n } catch (e) {\n const error =\n e instanceof AuthError\n ? e\n : this.nestedAppAuthAdapter.fromBridgeError(e);\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_FAILURE,\n InteractionType.Silent,\n null,\n e as EventError\n );\n ssoSilentMeasurement?.end(\n {\n success: false,\n },\n e\n );\n throw error;\n }\n }\n\n /**\n * acquires tokens from cache\n * @param request\n * @returns\n */\n private async acquireTokenFromCache(\n request: SilentRequest\n ): Promise {\n const atsMeasurement = this.performanceClient.startMeasurement(\n PerformanceEvents.AcquireTokenSilent,\n request.correlationId\n );\n\n atsMeasurement?.add({\n nestedAppAuthRequest: true,\n });\n\n // if the request has claims, we cannot look up in the cache\n if (request.claims) {\n this.logger.verbose(\n \"Claims are present in the request, skipping cache lookup\"\n );\n return null;\n }\n\n // if the request has forceRefresh, we cannot look up in the cache\n if (request.forceRefresh) {\n this.logger.verbose(\n \"forceRefresh is set to true, skipping cache lookup\"\n );\n return null;\n }\n\n // respect cache lookup policy\n let result: AuthenticationResult | null = null;\n if (!request.cacheLookupPolicy) {\n request.cacheLookupPolicy = CacheLookupPolicy.Default;\n }\n\n switch (request.cacheLookupPolicy) {\n case CacheLookupPolicy.Default:\n case CacheLookupPolicy.AccessToken:\n case CacheLookupPolicy.AccessTokenAndRefreshToken:\n result = await this.acquireTokenFromCacheInternal(request);\n break;\n default:\n return null;\n }\n\n if (result) {\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_SUCCESS,\n InteractionType.Silent,\n result\n );\n atsMeasurement?.add({\n accessTokenSize: result?.accessToken.length,\n idTokenSize: result?.idToken.length,\n });\n atsMeasurement?.end({\n success: true,\n });\n return result;\n }\n\n this.logger.warning(\n \"Cached tokens are not found for the account, proceeding with silent token request.\"\n );\n\n this.eventHandler.emitEvent(\n EventType.ACQUIRE_TOKEN_FAILURE,\n InteractionType.Silent,\n null\n );\n atsMeasurement?.end({\n success: false,\n });\n\n return null;\n }\n\n /**\n *\n * @param request\n * @returns\n */\n private async acquireTokenFromCacheInternal(\n request: SilentRequest\n ): Promise {\n // always prioritize the account context from the bridge\n const accountContext =\n this.bridgeProxy.getAccountContext() || this.currentAccountContext;\n let currentAccount: AccountInfo | null = null;\n const correlationId =\n request.correlationId || this.browserCrypto.createNewGuid();\n if (accountContext) {\n currentAccount = AccountManager.getAccount(\n accountContext,\n this.logger,\n this.browserStorage,\n correlationId\n );\n }\n\n // fall back to brokering if no cached account is found\n if (!currentAccount) {\n this.logger.verbose(\n \"No active account found, falling back to the host\"\n );\n return Promise.resolve(null);\n }\n\n this.logger.verbose(\n \"active account found, attempting to acquire token silently\"\n );\n\n const authRequest: BaseAuthRequest = {\n ...request,\n correlationId:\n request.correlationId || this.browserCrypto.createNewGuid(),\n authority: request.authority || currentAccount.environment,\n scopes: request.scopes?.length\n ? request.scopes\n : [...OIDC_DEFAULT_SCOPES],\n };\n\n // fetch access token and check for expiry\n const tokenKeys = this.browserStorage.getTokenKeys();\n const cachedAccessToken = this.browserStorage.getAccessToken(\n currentAccount,\n authRequest,\n tokenKeys,\n currentAccount.tenantId\n );\n\n // If there is no access token, log it and return null\n if (!cachedAccessToken) {\n this.logger.verbose(\"No cached access token found\");\n return Promise.resolve(null);\n } else if (\n TimeUtils.wasClockTurnedBack(cachedAccessToken.cachedAt) ||\n TimeUtils.isTokenExpired(\n cachedAccessToken.expiresOn,\n this.config.system.tokenRenewalOffsetSeconds\n )\n ) {\n this.logger.verbose(\"Cached access token has expired\");\n return Promise.resolve(null);\n }\n\n const cachedIdToken = this.browserStorage.getIdToken(\n currentAccount,\n authRequest.correlationId,\n tokenKeys,\n currentAccount.tenantId,\n this.performanceClient\n );\n\n if (!cachedIdToken) {\n this.logger.verbose(\"No cached id token found\");\n return Promise.resolve(null);\n }\n\n return this.nestedAppAuthAdapter.toAuthenticationResultFromCache(\n currentAccount,\n cachedIdToken,\n cachedAccessToken,\n authRequest,\n authRequest.correlationId\n );\n }\n\n /**\n * acquireTokenPopup flow implementation\n * @param request\n * @returns\n */\n async acquireTokenPopup(\n request: PopupRequest\n ): Promise {\n return this.acquireTokenInteractive(request);\n }\n\n /**\n * acquireTokenRedirect flow is not supported in nested app auth\n * @param request\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n acquireTokenRedirect(request: RedirectRequest): Promise {\n throw NestedAppAuthError.createUnsupportedError();\n }\n\n /**\n * acquireTokenSilent flow implementation\n * @param silentRequest\n * @returns\n */\n async acquireTokenSilent(\n silentRequest: SilentRequest\n ): Promise {\n return this.acquireTokenSilentInternal(silentRequest);\n }\n\n /**\n * Hybrid flow is not currently supported in nested app auth\n * @param request\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n acquireTokenByCode(\n request: AuthorizationCodeRequest // eslint-disable-line @typescript-eslint/no-unused-vars\n ): Promise {\n throw NestedAppAuthError.createUnsupportedError();\n }\n\n /**\n * acquireTokenNative flow is not currently supported in nested app auth\n * @param request\n * @param apiId\n * @param accountId\n */\n acquireTokenNative(\n request: // eslint-disable-line @typescript-eslint/no-unused-vars\n | SilentRequest\n | Partial<\n Omit<\n CommonAuthorizationUrlRequest,\n | \"requestedClaimsHash\"\n | \"responseMode\"\n | \"earJwk\"\n | \"codeChallenge\"\n | \"codeChallengeMethod\"\n | \"platformBroker\"\n >\n >\n | PopupRequest,\n apiId: ApiId, // eslint-disable-line @typescript-eslint/no-unused-vars\n accountId?: string | undefined // eslint-disable-line @typescript-eslint/no-unused-vars\n ): Promise {\n throw NestedAppAuthError.createUnsupportedError();\n }\n\n /**\n * acquireTokenByRefreshToken flow is not currently supported in nested app auth\n * @param commonRequest\n * @param silentRequest\n */\n acquireTokenByRefreshToken(\n commonRequest: CommonSilentFlowRequest, // eslint-disable-line @typescript-eslint/no-unused-vars\n silentRequest: SilentRequest // eslint-disable-line @typescript-eslint/no-unused-vars\n ): Promise {\n throw NestedAppAuthError.createUnsupportedError();\n }\n\n /**\n * Adds event callbacks to array\n * @param callback\n * @param eventTypes\n */\n addEventCallback(\n callback: EventCallbackFunction,\n eventTypes?: Array\n ): string | null {\n return this.eventHandler.addEventCallback(callback, eventTypes);\n }\n\n /**\n * Removes callback with provided id from callback array\n * @param callbackId\n */\n removeEventCallback(callbackId: string): void {\n this.eventHandler.removeEventCallback(callbackId);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n addPerformanceCallback(callback: PerformanceCallbackFunction): string {\n throw NestedAppAuthError.createUnsupportedError();\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n removePerformanceCallback(callbackId: string): boolean {\n throw NestedAppAuthError.createUnsupportedError();\n }\n\n enableAccountStorageEvents(): void {\n throw NestedAppAuthError.createUnsupportedError();\n }\n\n disableAccountStorageEvents(): void {\n throw NestedAppAuthError.createUnsupportedError();\n }\n\n // #region Account APIs\n\n /**\n * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.\n * @param accountFilter - (Optional) filter to narrow down the accounts returned\n * @returns Array of AccountInfo objects in cache\n */\n getAllAccounts(accountFilter?: AccountFilter): AccountInfo[] {\n const correlationId = this.browserCrypto.createNewGuid();\n return AccountManager.getAllAccounts(\n this.logger,\n this.browserStorage,\n this.isBrowserEnv(),\n correlationId,\n accountFilter\n );\n }\n\n /**\n * Returns the first account found in the cache that matches the account filter passed in.\n * @param accountFilter\n * @returns The first account found in the cache matching the provided filter or null if no account could be found.\n */\n getAccount(accountFilter: AccountFilter): AccountInfo | null {\n const correlationId = this.browserCrypto.createNewGuid();\n return AccountManager.getAccount(\n accountFilter,\n this.logger,\n this.browserStorage,\n correlationId\n );\n }\n\n /**\n * Returns the signed in account matching username.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found.\n * This API is provided for convenience but getAccountById should be used for best reliability\n * @param username\n * @returns The account object stored in MSAL\n */\n getAccountByUsername(username: string): AccountInfo | null {\n const correlationId = this.browserCrypto.createNewGuid();\n return AccountManager.getAccountByUsername(\n username,\n this.logger,\n this.browserStorage,\n correlationId\n );\n }\n\n /**\n * Returns the signed in account matching homeAccountId.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found\n * @param homeAccountId\n * @returns The account object stored in MSAL\n */\n getAccountByHomeId(homeAccountId: string): AccountInfo | null {\n const correlationId = this.browserCrypto.createNewGuid();\n return AccountManager.getAccountByHomeId(\n homeAccountId,\n this.logger,\n this.browserStorage,\n correlationId\n );\n }\n\n /**\n * Returns the signed in account matching localAccountId.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found\n * @param localAccountId\n * @returns The account object stored in MSAL\n */\n getAccountByLocalId(localAccountId: string): AccountInfo | null {\n const correlationId = this.browserCrypto.createNewGuid();\n return AccountManager.getAccountByLocalId(\n localAccountId,\n this.logger,\n this.browserStorage,\n correlationId\n );\n }\n\n /**\n * Sets the account to use as the active account. If no account is passed to the acquireToken APIs, then MSAL will use this active account.\n * @param account\n */\n setActiveAccount(account: AccountInfo | null): void {\n /*\n * StandardController uses this to allow the developer to set the active account\n * in the nested app auth scenario the active account is controlled by the app hosting the nested app\n */\n const correlationId = this.browserCrypto.createNewGuid();\n return AccountManager.setActiveAccount(\n account,\n this.browserStorage,\n correlationId\n );\n }\n\n /**\n * Gets the currently active account\n */\n getActiveAccount(): AccountInfo | null {\n const correlationId = this.browserCrypto.createNewGuid();\n return AccountManager.getActiveAccount(\n this.browserStorage,\n correlationId\n );\n }\n\n // #endregion\n\n handleRedirectPromise(\n hash?: string | undefined // eslint-disable-line @typescript-eslint/no-unused-vars\n ): Promise {\n return Promise.resolve(null);\n }\n loginPopup(\n request?: PopupRequest | undefined // eslint-disable-line @typescript-eslint/no-unused-vars\n ): Promise {\n return this.acquireTokenInteractive(request || DEFAULT_REQUEST);\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n loginRedirect(request?: RedirectRequest | undefined): Promise {\n throw NestedAppAuthError.createUnsupportedError();\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n logout(logoutRequest?: EndSessionRequest | undefined): Promise {\n throw NestedAppAuthError.createUnsupportedError();\n }\n logoutRedirect(\n logoutRequest?: EndSessionRequest | undefined // eslint-disable-line @typescript-eslint/no-unused-vars\n ): Promise {\n throw NestedAppAuthError.createUnsupportedError();\n }\n logoutPopup(\n logoutRequest?: EndSessionPopupRequest | undefined // eslint-disable-line @typescript-eslint/no-unused-vars\n ): Promise {\n throw NestedAppAuthError.createUnsupportedError();\n }\n ssoSilent(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n request: Partial<\n Omit<\n CommonAuthorizationUrlRequest,\n | \"requestedClaimsHash\"\n | \"responseMode\"\n | \"earJwk\"\n | \"codeChallenge\"\n | \"codeChallengeMethod\"\n | \"platformBroker\"\n >\n >\n ): Promise {\n return this.acquireTokenSilentInternal(request as SilentRequest);\n }\n getTokenCache(): ITokenCache {\n throw NestedAppAuthError.createUnsupportedError();\n }\n\n /**\n * Returns the logger instance\n */\n public getLogger(): Logger {\n return this.logger;\n }\n\n /**\n * Replaces the default logger set in configurations with new Logger with new configurations\n * @param logger Logger instance\n */\n setLogger(logger: Logger): void {\n this.logger = logger;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n initializeWrapperLibrary(sku: WrapperSKU, version: string): void {\n /*\n * Standard controller uses this to set the sku and version of the wrapper library in the storage\n * we do nothing here\n */\n return;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n setNavigationClient(navigationClient: INavigationClient): void {\n this.logger.warning(\n \"setNavigationClient is not supported in nested app auth\"\n );\n }\n\n getConfiguration(): BrowserConfiguration {\n return this.config;\n }\n\n isBrowserEnv(): boolean {\n return this.operatingContext.isBrowserEnvironment();\n }\n\n getBrowserCrypto(): ICrypto {\n return this.browserCrypto;\n }\n\n getPerformanceClient(): IPerformanceClient {\n throw NestedAppAuthError.createUnsupportedError();\n }\n\n getRedirectResponse(): Map> {\n throw NestedAppAuthError.createUnsupportedError();\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async clearCache(logoutRequest?: ClearCacheRequest): Promise {\n throw NestedAppAuthError.createUnsupportedError();\n }\n\n async hydrateCache(\n result: AuthenticationResult,\n request:\n | SilentRequest\n | SsoSilentRequest\n | RedirectRequest\n | PopupRequest\n ): Promise {\n this.logger.verbose(\"hydrateCache called\");\n\n const accountEntity = AccountEntity.createFromAccountInfo(\n result.account,\n result.cloudGraphHostName,\n result.msGraphHost\n );\n await this.browserStorage.setAccount(\n accountEntity,\n result.correlationId\n );\n return this.browserStorage.hydrateCache(result, request);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { NestedAppOperatingContext } from \"../operatingcontext/NestedAppOperatingContext.js\";\nimport { StandardOperatingContext } from \"../operatingcontext/StandardOperatingContext.js\";\nimport { IController } from \"./IController.js\";\nimport { Configuration } from \"../config/Configuration.js\";\nimport { StandardController } from \"./StandardController.js\";\nimport { NestedAppAuthController } from \"./NestedAppAuthController.js\";\nimport { InitializeApplicationRequest } from \"../request/InitializeApplicationRequest.js\";\n\nexport async function createV3Controller(\n config: Configuration,\n request?: InitializeApplicationRequest\n): Promise {\n const standard = new StandardOperatingContext(config);\n\n await standard.initialize();\n return StandardController.createController(standard, request);\n}\n\nexport async function createController(\n config: Configuration\n): Promise {\n const standard = new StandardOperatingContext(config);\n const nestedApp = new NestedAppOperatingContext(config);\n\n const operatingContexts = [standard.initialize(), nestedApp.initialize()];\n\n await Promise.all(operatingContexts);\n\n if (nestedApp.isAvailable() && config.auth.supportsNestedAppAuth) {\n return NestedAppAuthController.createController(nestedApp);\n } else if (standard.isAvailable()) {\n return StandardController.createController(standard);\n } else {\n // Since neither of the actual operating contexts are available keep the UnknownOperatingContextController\n return null;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITokenCache } from \"../cache/ITokenCache.js\";\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\nimport { PopupRequest } from \"../request/PopupRequest.js\";\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\nimport { SilentRequest } from \"../request/SilentRequest.js\";\nimport { WrapperSKU } from \"../utils/BrowserConstants.js\";\nimport { IPublicClientApplication } from \"./IPublicClientApplication.js\";\nimport { IController } from \"../controllers/IController.js\";\nimport {\n PerformanceCallbackFunction,\n AccountInfo,\n AccountFilter,\n Logger,\n} from \"@azure/msal-common/browser\";\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\nimport * as ControllerFactory from \"../controllers/ControllerFactory.js\";\nimport { StandardController } from \"../controllers/StandardController.js\";\nimport {\n BrowserConfiguration,\n Configuration,\n} from \"../config/Configuration.js\";\nimport { StandardOperatingContext } from \"../operatingcontext/StandardOperatingContext.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { EventCallbackFunction } from \"../event/EventMessage.js\";\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\nimport { EndSessionPopupRequest } from \"../request/EndSessionPopupRequest.js\";\nimport { NestedAppAuthController } from \"../controllers/NestedAppAuthController.js\";\nimport { NestedAppOperatingContext } from \"../operatingcontext/NestedAppOperatingContext.js\";\nimport { InitializeApplicationRequest } from \"../request/InitializeApplicationRequest.js\";\nimport { EventType } from \"../event/EventType.js\";\n\n/**\n * The PublicClientApplication class is the object exposed by the library to perform authentication and authorization functions in Single Page Applications\n * to obtain JWT tokens as described in the OAuth 2.0 Authorization Code Flow with PKCE specification.\n */\nexport class PublicClientApplication implements IPublicClientApplication {\n protected controller: IController;\n protected isBroker: boolean = false;\n\n /**\n * Creates StandardController and passes it to the PublicClientApplication\n *\n * @param configuration {Configuration}\n */\n public static async createPublicClientApplication(\n configuration: Configuration\n ): Promise {\n const controller = await ControllerFactory.createV3Controller(\n configuration\n );\n const pca = new PublicClientApplication(configuration, controller);\n\n return pca;\n }\n\n /**\n * @constructor\n * Constructor for the PublicClientApplication used to instantiate the PublicClientApplication object\n *\n * Important attributes in the Configuration object for auth are:\n * - clientID: the application ID of your application. You can obtain one by registering your application with our Application registration portal : https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredAppsPreview\n * - authority: the authority URL for your application.\n * - redirect_uri: the uri of your application registered in the portal.\n *\n * In Azure AD, authority is a URL indicating the Azure active directory that MSAL uses to obtain tokens.\n * It is of the form https://login.microsoftonline.com/{Enter_the_Tenant_Info_Here}\n * If your application supports Accounts in one organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with the Tenant Id or Tenant name (for example, contoso.microsoft.com).\n * If your application supports Accounts in any organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with organizations.\n * If your application supports Accounts in any organizational directory and personal Microsoft accounts, replace \"Enter_the_Tenant_Info_Here\" value with common.\n * To restrict support to Personal Microsoft accounts only, replace \"Enter_the_Tenant_Info_Here\" value with consumers.\n *\n * In Azure B2C, authority is of the form https://{instance}/tfp/{tenant}/{policyName}/\n * Full B2C functionality will be available in this library in future versions.\n *\n * @param configuration Object for the MSAL PublicClientApplication instance\n * @param IController Optional parameter to explictly set the controller. (Will be removed when we remove public constructor)\n */\n public constructor(configuration: Configuration, controller?: IController) {\n this.controller =\n controller ||\n new StandardController(new StandardOperatingContext(configuration));\n }\n\n /**\n * Initializer function to perform async startup tasks such as connecting to WAM extension\n * @param request {?InitializeApplicationRequest}\n */\n async initialize(request?: InitializeApplicationRequest): Promise {\n return this.controller.initialize(request, this.isBroker);\n }\n\n /**\n * Use when you want to obtain an access_token for your API via opening a popup window in the user's browser\n *\n * @param request\n *\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\n */\n async acquireTokenPopup(\n request: PopupRequest\n ): Promise {\n return this.controller.acquireTokenPopup(request);\n }\n\n /**\n * Use when you want to obtain an access_token for your API by redirecting the user's browser window to the authorization endpoint. This function redirects\n * the page, so any code that follows this function will not execute.\n *\n * IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current\n * browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.\n *\n * @param request\n */\n acquireTokenRedirect(request: RedirectRequest): Promise {\n return this.controller.acquireTokenRedirect(request);\n }\n\n /**\n * Silently acquire an access token for a given set of scopes. Returns currently processing promise if parallel requests are made.\n *\n * @param {@link (SilentRequest:type)}\n * @returns {Promise.} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthenticationResult} object\n */\n acquireTokenSilent(\n silentRequest: SilentRequest\n ): Promise {\n return this.controller.acquireTokenSilent(silentRequest);\n }\n\n /**\n * This function redeems an authorization code (passed as code) from the eSTS token endpoint.\n * This authorization code should be acquired server-side using a confidential client to acquire a spa_code.\n * This API is not indended for normal authorization code acquisition and redemption.\n *\n * Redemption of this authorization code will not require PKCE, as it was acquired by a confidential client.\n *\n * @param request {@link AuthorizationCodeRequest}\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\n */\n acquireTokenByCode(\n request: AuthorizationCodeRequest\n ): Promise {\n return this.controller.acquireTokenByCode(request);\n }\n\n /**\n * Adds event callbacks to array\n * @param callback\n * @param eventTypes\n */\n addEventCallback(\n callback: EventCallbackFunction,\n eventTypes?: Array\n ): string | null {\n return this.controller.addEventCallback(callback, eventTypes);\n }\n\n /**\n * Removes callback with provided id from callback array\n * @param callbackId\n */\n removeEventCallback(callbackId: string): void {\n return this.controller.removeEventCallback(callbackId);\n }\n\n /**\n * Registers a callback to receive performance events.\n *\n * @param {PerformanceCallbackFunction} callback\n * @returns {string}\n */\n addPerformanceCallback(callback: PerformanceCallbackFunction): string {\n return this.controller.addPerformanceCallback(callback);\n }\n\n /**\n * Removes a callback registered with addPerformanceCallback.\n *\n * @param {string} callbackId\n * @returns {boolean}\n */\n removePerformanceCallback(callbackId: string): boolean {\n return this.controller.removePerformanceCallback(callbackId);\n }\n\n /**\n * Adds event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\n */\n enableAccountStorageEvents(): void {\n this.controller.enableAccountStorageEvents();\n }\n\n /**\n * Removes event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\n */\n disableAccountStorageEvents(): void {\n this.controller.disableAccountStorageEvents();\n }\n\n /**\n * Returns the first account found in the cache that matches the account filter passed in.\n * @param accountFilter\n * @returns The first account found in the cache matching the provided filter or null if no account could be found.\n */\n getAccount(accountFilter: AccountFilter): AccountInfo | null {\n return this.controller.getAccount(accountFilter);\n }\n\n /**\n * Returns the signed in account matching homeAccountId.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found\n * @param homeAccountId\n * @returns The account object stored in MSAL\n * @deprecated - Use getAccount instead\n */\n getAccountByHomeId(homeAccountId: string): AccountInfo | null {\n return this.controller.getAccountByHomeId(homeAccountId);\n }\n\n /**\n * Returns the signed in account matching localAccountId.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found\n * @param localAccountId\n * @returns The account object stored in MSAL\n * @deprecated - Use getAccount instead\n */\n getAccountByLocalId(localId: string): AccountInfo | null {\n return this.controller.getAccountByLocalId(localId);\n }\n\n /**\n * Returns the signed in account matching username.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found.\n * This API is provided for convenience but getAccountById should be used for best reliability\n * @param userName\n * @returns The account object stored in MSAL\n * @deprecated - Use getAccount instead\n */\n getAccountByUsername(userName: string): AccountInfo | null {\n return this.controller.getAccountByUsername(userName);\n }\n\n /**\n * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.\n * @param accountFilter - (Optional) filter to narrow down the accounts returned\n * @returns Array of AccountInfo objects in cache\n */\n getAllAccounts(accountFilter?: AccountFilter): AccountInfo[] {\n return this.controller.getAllAccounts(accountFilter);\n }\n\n /**\n * Event handler function which allows users to fire events after the PublicClientApplication object\n * has loaded during redirect flows. This should be invoked on all page loads involved in redirect\n * auth flows.\n * @param hash Hash to process. Defaults to the current value of window.location.hash. Only needs to be provided explicitly if the response to be handled is not contained in the current value.\n * @returns Token response or null. If the return value is null, then no auth redirect was detected.\n */\n handleRedirectPromise(\n hash?: string | undefined\n ): Promise {\n return this.controller.handleRedirectPromise(hash);\n }\n\n /**\n * Use when initiating the login process via opening a popup window in the user's browser\n *\n * @param request\n *\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\n */\n loginPopup(\n request?: PopupRequest | undefined\n ): Promise {\n return this.controller.loginPopup(request);\n }\n\n /**\n * Use when initiating the login process by redirecting the user's browser to the authorization endpoint. This function redirects the page, so\n * any code that follows this function will not execute.\n *\n * IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current\n * browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.\n *\n * @param request\n */\n loginRedirect(request?: RedirectRequest | undefined): Promise {\n return this.controller.loginRedirect(request);\n }\n\n /**\n * Deprecated logout function. Use logoutRedirect or logoutPopup instead\n * @param logoutRequest\n * @deprecated\n */\n logout(logoutRequest?: EndSessionRequest): Promise {\n return this.controller.logout(logoutRequest);\n }\n\n /**\n * Use to log out the current user, and redirect the user to the postLogoutRedirectUri.\n * Default behaviour is to redirect the user to `window.location.href`.\n * @param logoutRequest\n */\n logoutRedirect(logoutRequest?: EndSessionRequest): Promise {\n return this.controller.logoutRedirect(logoutRequest);\n }\n\n /**\n * Clears local cache for the current user then opens a popup window prompting the user to sign-out of the server\n * @param logoutRequest\n */\n logoutPopup(logoutRequest?: EndSessionPopupRequest): Promise {\n return this.controller.logoutPopup(logoutRequest);\n }\n\n /**\n * This function uses a hidden iframe to fetch an authorization code from the eSTS. There are cases where this may not work:\n * - Any browser using a form of Intelligent Tracking Prevention\n * - If there is not an established session with the service\n *\n * In these cases, the request must be done inside a popup or full frame redirect.\n *\n * For the cases where interaction is required, you cannot send a request with prompt=none.\n *\n * If your refresh token has expired, you can use this function to fetch a new set of tokens silently as long as\n * you session on the server still exists.\n * @param request {@link SsoSilentRequest}\n *\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\n */\n ssoSilent(request: SsoSilentRequest): Promise {\n return this.controller.ssoSilent(request);\n }\n\n /**\n * Gets the token cache for the application.\n */\n getTokenCache(): ITokenCache {\n return this.controller.getTokenCache();\n }\n\n /**\n * Returns the logger instance\n */\n getLogger(): Logger {\n return this.controller.getLogger();\n }\n\n /**\n * Replaces the default logger set in configurations with new Logger with new configurations\n * @param logger Logger instance\n */\n setLogger(logger: Logger): void {\n this.controller.setLogger(logger);\n }\n\n /**\n * Sets the account to use as the active account. If no account is passed to the acquireToken APIs, then MSAL will use this active account.\n * @param account\n */\n setActiveAccount(account: AccountInfo | null): void {\n this.controller.setActiveAccount(account);\n }\n\n /**\n * Gets the currently active account\n */\n getActiveAccount(): AccountInfo | null {\n return this.controller.getActiveAccount();\n }\n\n /**\n * Called by wrapper libraries (Angular & React) to set SKU and Version passed down to telemetry, logger, etc.\n * @param sku\n * @param version\n */\n initializeWrapperLibrary(sku: WrapperSKU, version: string): void {\n return this.controller.initializeWrapperLibrary(sku, version);\n }\n\n /**\n * Sets navigation client\n * @param navigationClient\n */\n setNavigationClient(navigationClient: INavigationClient): void {\n this.controller.setNavigationClient(navigationClient);\n }\n\n /**\n * Returns the configuration object\n * @internal\n */\n getConfiguration(): BrowserConfiguration {\n return this.controller.getConfiguration();\n }\n\n /**\n * Hydrates cache with the tokens and account in the AuthenticationResult object\n * @param result\n * @param request - The request object that was used to obtain the AuthenticationResult\n * @returns\n */\n async hydrateCache(\n result: AuthenticationResult,\n request:\n | SilentRequest\n | SsoSilentRequest\n | RedirectRequest\n | PopupRequest\n ): Promise {\n return this.controller.hydrateCache(result, request);\n }\n\n /**\n * Clears tokens and account from the browser cache.\n * @param logoutRequest\n */\n clearCache(logoutRequest?: ClearCacheRequest): Promise {\n return this.controller.clearCache(logoutRequest);\n }\n}\n\n/**\n * creates NestedAppAuthController and passes it to the PublicClientApplication,\n * falls back to StandardController if NestedAppAuthController is not available\n *\n * @param configuration\n * @returns IPublicClientApplication\n *\n */\nexport async function createNestablePublicClientApplication(\n configuration: Configuration\n): Promise {\n const nestedAppAuth = new NestedAppOperatingContext(configuration);\n await nestedAppAuth.initialize();\n\n if (nestedAppAuth.isAvailable()) {\n const controller = new NestedAppAuthController(nestedAppAuth);\n const nestablePCA = new PublicClientApplication(\n configuration,\n controller\n );\n await nestablePCA.initialize();\n return nestablePCA;\n }\n\n return createStandardPublicClientApplication(configuration);\n}\n\n/**\n * creates PublicClientApplication using StandardController\n *\n * @param configuration\n * @returns IPublicClientApplication\n *\n */\nexport async function createStandardPublicClientApplication(\n configuration: Configuration\n): Promise {\n const pca = new PublicClientApplication(configuration);\n await pca.initialize();\n return pca;\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n CommonAuthorizationUrlRequest,\n CommonSilentFlowRequest,\n PerformanceCallbackFunction,\n AccountInfo,\n Logger,\n ICrypto,\n IPerformanceClient,\n DEFAULT_CRYPTO_IMPLEMENTATION,\n AccountFilter,\n} from \"@azure/msal-common/browser\";\nimport { ITokenCache } from \"../cache/ITokenCache.js\";\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\nimport {\n BrowserCacheManager,\n DEFAULT_BROWSER_CACHE_MANAGER,\n} from \"../cache/BrowserCacheManager.js\";\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\nimport { EndSessionPopupRequest } from \"../request/EndSessionPopupRequest.js\";\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\nimport { PopupRequest } from \"../request/PopupRequest.js\";\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\nimport { SilentRequest } from \"../request/SilentRequest.js\";\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { ApiId, WrapperSKU } from \"../utils/BrowserConstants.js\";\nimport { IController } from \"./IController.js\";\nimport { UnknownOperatingContext } from \"../operatingcontext/UnknownOperatingContext.js\";\nimport { CryptoOps } from \"../crypto/CryptoOps.js\";\nimport {\n blockAPICallsBeforeInitialize,\n blockNonBrowserEnvironment,\n} from \"../utils/BrowserUtils.js\";\nimport { EventCallbackFunction } from \"../event/EventMessage.js\";\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\nimport { EventType } from \"../event/EventType.js\";\nimport { EventHandler } from \"../event/EventHandler.js\";\n\n/**\n * UnknownOperatingContextController class\n *\n * - Until initialize method is called, this controller is the default\n * - AFter initialize method is called, this controller will be swapped out for the appropriate controller\n * if the operating context can be determined; otherwise this controller will continued be used\n *\n * - Why do we have this? We don't want to dynamically import (download) all of the code in StandardController if we don't need to.\n *\n * - Only includes implementation for getAccounts and handleRedirectPromise\n * - All other methods are will throw initialization error (because either initialize method or the factory method were not used)\n * - This controller is necessary for React Native wrapper, server side rendering and any other scenario where we don't have a DOM\n *\n */\nexport class UnknownOperatingContextController implements IController {\n // OperatingContext\n protected readonly operatingContext: UnknownOperatingContext;\n\n // Logger\n protected logger: Logger;\n\n // Storage interface implementation\n protected readonly browserStorage: BrowserCacheManager;\n\n // Input configuration by developer/user\n protected readonly config: BrowserConfiguration;\n\n // Performance telemetry client\n protected readonly performanceClient: IPerformanceClient;\n\n // Event handler\n private readonly eventHandler: EventHandler;\n\n // Crypto interface implementation\n protected readonly browserCrypto: ICrypto;\n\n // Flag to indicate if in browser environment\n protected isBrowserEnvironment: boolean;\n\n // Flag representing whether or not the initialize API has been called and completed\n protected initialized: boolean = false;\n\n constructor(operatingContext: UnknownOperatingContext) {\n this.operatingContext = operatingContext;\n\n this.isBrowserEnvironment =\n this.operatingContext.isBrowserEnvironment();\n\n this.config = operatingContext.getConfig();\n\n this.logger = operatingContext.getLogger();\n\n // Initialize performance client\n this.performanceClient = this.config.telemetry.client;\n\n // Initialize the crypto class.\n this.browserCrypto = this.isBrowserEnvironment\n ? new CryptoOps(this.logger, this.performanceClient)\n : DEFAULT_CRYPTO_IMPLEMENTATION;\n\n this.eventHandler = new EventHandler(this.logger);\n\n // Initialize the browser storage class.\n this.browserStorage = this.isBrowserEnvironment\n ? new BrowserCacheManager(\n this.config.auth.clientId,\n this.config.cache,\n this.browserCrypto,\n this.logger,\n this.performanceClient,\n this.eventHandler,\n undefined\n )\n : DEFAULT_BROWSER_CACHE_MANAGER(\n this.config.auth.clientId,\n this.logger,\n this.performanceClient,\n this.eventHandler\n );\n }\n getBrowserStorage(): BrowserCacheManager {\n return this.browserStorage;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n getAccount(accountFilter: AccountFilter): AccountInfo | null {\n return null;\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n getAccountByHomeId(homeAccountId: string): AccountInfo | null {\n return null;\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n getAccountByLocalId(localAccountId: string): AccountInfo | null {\n return null;\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n getAccountByUsername(username: string): AccountInfo | null {\n return null;\n }\n getAllAccounts(): AccountInfo[] {\n return [];\n }\n initialize(): Promise {\n this.initialized = true;\n return Promise.resolve();\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n acquireTokenPopup(request: PopupRequest): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as Promise;\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n acquireTokenRedirect(request: RedirectRequest): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return Promise.resolve();\n }\n acquireTokenSilent(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n silentRequest: SilentRequest\n ): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as Promise;\n }\n acquireTokenByCode(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n request: AuthorizationCodeRequest\n ): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as Promise;\n }\n acquireTokenNative(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n request:\n | PopupRequest\n | SilentRequest\n | Partial<\n Omit<\n CommonAuthorizationUrlRequest,\n | \"responseMode\"\n | \"earJwk\"\n | \"codeChallenge\"\n | \"codeChallengeMethod\"\n | \"requestedClaimsHash\"\n | \"platformBroker\"\n >\n >,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n apiId: ApiId,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n accountId?: string | undefined\n ): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as Promise;\n }\n acquireTokenByRefreshToken(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n commonRequest: CommonSilentFlowRequest,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n silentRequest: SilentRequest\n ): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as Promise;\n }\n addEventCallback(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n callback: EventCallbackFunction,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n eventTypes?: Array\n ): string | null {\n return null;\n }\n removeEventCallback(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n callbackId: string\n ): void {}\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n addPerformanceCallback(callback: PerformanceCallbackFunction): string {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return \"\";\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n removePerformanceCallback(callbackId: string): boolean {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return true;\n }\n enableAccountStorageEvents(): void {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n }\n disableAccountStorageEvents(): void {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n }\n\n handleRedirectPromise(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n hash?: string | undefined\n ): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n return Promise.resolve(null);\n }\n loginPopup(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n request?: PopupRequest | undefined\n ): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as Promise;\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n loginRedirect(request?: RedirectRequest | undefined): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as Promise;\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n logout(logoutRequest?: EndSessionRequest | undefined): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as Promise;\n }\n logoutRedirect(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n logoutRequest?: EndSessionRequest | undefined\n ): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as Promise;\n }\n logoutPopup(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n logoutRequest?: EndSessionPopupRequest | undefined\n ): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as Promise;\n }\n ssoSilent(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n request: Partial<\n Omit<\n CommonAuthorizationUrlRequest,\n | \"responseMode\"\n | \"earJwk\"\n | \"codeChallenge\"\n | \"codeChallengeMethod\"\n | \"requestedClaimsHash\"\n | \"platformBroker\"\n >\n >\n ): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as Promise;\n }\n getTokenCache(): ITokenCache {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as ITokenCache;\n }\n getLogger(): Logger {\n return this.logger;\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n setLogger(logger: Logger): void {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n setActiveAccount(account: AccountInfo | null): void {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n }\n getActiveAccount(): AccountInfo | null {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return null;\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n initializeWrapperLibrary(sku: WrapperSKU, version: string): void {\n this.browserStorage.setWrapperMetadata(sku, version);\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n setNavigationClient(navigationClient: INavigationClient): void {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n }\n getConfiguration(): BrowserConfiguration {\n return this.config;\n }\n isBrowserEnv(): boolean {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return true;\n }\n getBrowserCrypto(): ICrypto {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as ICrypto;\n }\n getPerformanceClient(): IPerformanceClient {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as IPerformanceClient;\n }\n getRedirectResponse(): Map> {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n return {} as Map>;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async clearCache(logoutRequest?: ClearCacheRequest): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async hydrateCache(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n result: AuthenticationResult,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n request:\n | SilentRequest\n | SsoSilentRequest\n | RedirectRequest\n | PopupRequest\n ): Promise {\n blockAPICallsBeforeInitialize(this.initialized);\n blockNonBrowserEnvironment();\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { BaseOperatingContext } from \"./BaseOperatingContext.js\";\n\nexport class UnknownOperatingContext extends BaseOperatingContext {\n /*\n * TODO: Once we have determine the bundling code return here to specify the name of the bundle\n * containing the implementation for this operating context\n */\n static readonly MODULE_NAME: string = \"\";\n\n /**\n * Unique identifier for the operating context\n */\n static readonly ID: string = \"UnknownOperatingContext\";\n\n /**\n * Returns the unique identifier for this operating context\n * @returns string\n */\n getId(): string {\n return UnknownOperatingContext.ID;\n }\n\n /**\n * Return the module name. Intended for use with import() to enable dynamic import\n * of the implementation associated with this operating context\n * @returns\n */\n getModuleName(): string {\n return UnknownOperatingContext.MODULE_NAME;\n }\n\n /**\n * Checks whether the operating context is available.\n * Confirms that the code is running a browser rather. This is required.\n * @returns Promise indicating whether this operating context is currently available.\n */\n async initialize(): Promise {\n /**\n * This operating context is in use when we have not checked for what the operating context is.\n * The context is unknown until we check it.\n */\n return true;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITokenCache } from \"../cache/ITokenCache.js\";\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\nimport { PopupRequest } from \"../request/PopupRequest.js\";\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\nimport { SilentRequest } from \"../request/SilentRequest.js\";\nimport { WrapperSKU } from \"../utils/BrowserConstants.js\";\nimport { IPublicClientApplication } from \"./IPublicClientApplication.js\";\nimport { IController } from \"../controllers/IController.js\";\nimport {\n PerformanceCallbackFunction,\n AccountInfo,\n AccountFilter,\n Logger,\n} from \"@azure/msal-common/browser\";\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\nimport * as ControllerFactory from \"../controllers/ControllerFactory.js\";\nimport {\n BrowserConfiguration,\n Configuration,\n} from \"../config/Configuration.js\";\nimport { EventCallbackFunction } from \"../event/EventMessage.js\";\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { UnknownOperatingContextController } from \"../controllers/UnknownOperatingContextController.js\";\nimport { UnknownOperatingContext } from \"../operatingcontext/UnknownOperatingContext.js\";\nimport { EventType } from \"../event/EventType.js\";\n\n/**\n * PublicClientNext is an early look at the planned implementation of PublicClientApplication in the next major version of MSAL.js.\n * It contains support for multiple API implementations based on the runtime environment that it is running in.\n *\n * The goals of these changes are to provide a clean separation of behavior between different operating contexts (Nested App Auth, Platform Brokers, Plain old Browser, etc.)\n * while still providing a consistent API surface for developers.\n *\n * Please use PublicClientApplication for any prod/real-world scenarios.\n * Note: PublicClientNext is experimental and subject to breaking changes without following semver\n *\n */\nexport class PublicClientNext implements IPublicClientApplication {\n /*\n * Definite assignment assertion used below\n * https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions\n */\n protected controller!: IController;\n protected configuration: Configuration;\n\n public static async createPublicClientApplication(\n configuration: Configuration\n ): Promise {\n const controller = await ControllerFactory.createController(\n configuration\n );\n let pca;\n if (controller !== null) {\n pca = new PublicClientNext(configuration, controller);\n } else {\n pca = new PublicClientNext(configuration);\n }\n return pca;\n }\n\n /**\n * @constructor\n * Constructor for the PublicClientNext used to instantiate the PublicClientNext object\n *\n * Important attributes in the Configuration object for auth are:\n * - clientID: the application ID of your application. You can obtain one by registering your application with our Application registration portal : https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredAppsPreview\n * - authority: the authority URL for your application.\n * - redirect_uri: the uri of your application registered in the portal.\n *\n * In Azure AD, authority is a URL indicating the Azure active directory that MSAL uses to obtain tokens.\n * It is of the form https://login.microsoftonline.com/{Enter_the_Tenant_Info_Here}\n * If your application supports Accounts in one organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with the Tenant Id or Tenant name (for example, contoso.microsoft.com).\n * If your application supports Accounts in any organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with organizations.\n * If your application supports Accounts in any organizational directory and personal Microsoft accounts, replace \"Enter_the_Tenant_Info_Here\" value with common.\n * To restrict support to Personal Microsoft accounts only, replace \"Enter_the_Tenant_Info_Here\" value with consumers.\n *\n * In Azure B2C, authority is of the form https://{instance}/tfp/{tenant}/{policyName}/\n * Full B2C functionality will be available in this library in future versions.\n *\n * @param configuration Object for the MSAL PublicClientApplication instance\n * @param IController Optional parameter to explictly set the controller. (Will be removed when we remove public constructor)\n */\n private constructor(\n configuration: Configuration,\n controller?: IController\n ) {\n this.configuration = configuration;\n if (controller) {\n this.controller = controller;\n } else {\n const operatingContext = new UnknownOperatingContext(configuration);\n this.controller = new UnknownOperatingContextController(\n operatingContext\n );\n }\n }\n\n /**\n * Initializer function to perform async startup tasks such as connecting to WAM extension\n */\n async initialize(): Promise {\n if (this.controller instanceof UnknownOperatingContextController) {\n const result = await ControllerFactory.createController(\n this.configuration\n );\n if (result !== null) {\n this.controller = result;\n }\n return this.controller.initialize();\n }\n return Promise.resolve();\n }\n\n /**\n * Use when you want to obtain an access_token for your API via opening a popup window in the user's browser\n *\n * @param request\n *\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\n */\n async acquireTokenPopup(\n request: PopupRequest\n ): Promise {\n return this.controller.acquireTokenPopup(request);\n }\n\n /**\n * Use when you want to obtain an access_token for your API by redirecting the user's browser window to the authorization endpoint. This function redirects\n * the page, so any code that follows this function will not execute.\n *\n * IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current\n * browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.\n *\n * @param request\n */\n acquireTokenRedirect(request: RedirectRequest): Promise {\n return this.controller.acquireTokenRedirect(request);\n }\n\n /**\n * Silently acquire an access token for a given set of scopes. Returns currently processing promise if parallel requests are made.\n *\n * @param {@link (SilentRequest:type)}\n * @returns {Promise.} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthenticationResult} object\n */\n acquireTokenSilent(\n silentRequest: SilentRequest\n ): Promise {\n return this.controller.acquireTokenSilent(silentRequest);\n }\n\n /**\n * This function redeems an authorization code (passed as code) from the eSTS token endpoint.\n * This authorization code should be acquired server-side using a confidential client to acquire a spa_code.\n * This API is not indended for normal authorization code acquisition and redemption.\n *\n * Redemption of this authorization code will not require PKCE, as it was acquired by a confidential client.\n *\n * @param request {@link AuthorizationCodeRequest}\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\n */\n acquireTokenByCode(\n request: AuthorizationCodeRequest\n ): Promise {\n return this.controller.acquireTokenByCode(request);\n }\n\n /**\n * Adds event callbacks to array\n * @param callback\n */\n addEventCallback(\n callback: EventCallbackFunction,\n eventTypes?: Array\n ): string | null {\n return this.controller.addEventCallback(callback, eventTypes);\n }\n\n /**\n * Removes callback with provided id from callback array\n * @param callbackId\n */\n removeEventCallback(callbackId: string): void {\n return this.controller.removeEventCallback(callbackId);\n }\n\n /**\n * Registers a callback to receive performance events.\n *\n * @param {PerformanceCallbackFunction} callback\n * @returns {string}\n */\n addPerformanceCallback(callback: PerformanceCallbackFunction): string {\n return this.controller.addPerformanceCallback(callback);\n }\n\n /**\n * Removes a callback registered with addPerformanceCallback.\n *\n * @param {string} callbackId\n * @returns {boolean}\n */\n removePerformanceCallback(callbackId: string): boolean {\n return this.controller.removePerformanceCallback(callbackId);\n }\n\n /**\n * Adds event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\n */\n enableAccountStorageEvents(): void {\n this.controller.enableAccountStorageEvents();\n }\n\n /**\n * Removes event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\n */\n disableAccountStorageEvents(): void {\n this.controller.disableAccountStorageEvents();\n }\n\n /**\n * Returns the first account found in the cache that matches the account filter passed in.\n * @param accountFilter\n * @returns The first account found in the cache matching the provided filter or null if no account could be found.\n */\n getAccount(accountFilter: AccountFilter): AccountInfo | null {\n return this.controller.getAccount(accountFilter);\n }\n\n /**\n * Returns the signed in account matching homeAccountId.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found\n * @param homeAccountId\n * @returns The account object stored in MSAL\n * @deprecated - Use getAccount instead\n */\n getAccountByHomeId(homeAccountId: string): AccountInfo | null {\n return this.controller.getAccountByHomeId(homeAccountId);\n }\n\n /**\n * Returns the signed in account matching localAccountId.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found\n * @param localAccountId\n * @returns The account object stored in MSAL\n * @deprecated - Use getAccount instead\n */\n getAccountByLocalId(localId: string): AccountInfo | null {\n return this.controller.getAccountByLocalId(localId);\n }\n\n /**\n * Returns the signed in account matching username.\n * (the account object is created at the time of successful login)\n * or null when no matching account is found.\n * This API is provided for convenience but getAccountById should be used for best reliability\n * @param userName\n * @returns The account object stored in MSAL\n * @deprecated - Use getAccount instead\n */\n getAccountByUsername(userName: string): AccountInfo | null {\n return this.controller.getAccountByUsername(userName);\n }\n\n /**\n * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.\n * @param accountFilter - (Optional) filter to narrow down the accounts returned\n * @returns Array of AccountInfo objects in cache\n */\n getAllAccounts(accountFilter?: AccountFilter): AccountInfo[] {\n return this.controller.getAllAccounts(accountFilter);\n }\n\n /**\n * Event handler function which allows users to fire events after the PublicClientApplication object\n * has loaded during redirect flows. This should be invoked on all page loads involved in redirect\n * auth flows.\n * @param hash Hash to process. Defaults to the current value of window.location.hash. Only needs to be provided explicitly if the response to be handled is not contained in the current value.\n * @returns Token response or null. If the return value is null, then no auth redirect was detected.\n */\n handleRedirectPromise(\n hash?: string | undefined\n ): Promise {\n return this.controller.handleRedirectPromise(hash);\n }\n\n /**\n * Use when initiating the login process via opening a popup window in the user's browser\n *\n * @param request\n *\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\n */\n loginPopup(\n request?: PopupRequest | undefined\n ): Promise {\n return this.controller.loginPopup(request);\n }\n\n /**\n * Use when initiating the login process by redirecting the user's browser to the authorization endpoint. This function redirects the page, so\n * any code that follows this function will not execute.\n *\n * IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current\n * browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.\n *\n * @param request\n */\n loginRedirect(request?: RedirectRequest | undefined): Promise {\n return this.controller.loginRedirect(request);\n }\n\n /**\n * Deprecated logout function. Use logoutRedirect or logoutPopup instead\n * @param logoutRequest\n * @deprecated\n */\n logout(logoutRequest?: EndSessionRequest): Promise {\n return this.controller.logout(logoutRequest);\n }\n\n /**\n * Use to log out the current user, and redirect the user to the postLogoutRedirectUri.\n * Default behaviour is to redirect the user to `window.location.href`.\n * @param logoutRequest\n */\n logoutRedirect(logoutRequest?: EndSessionRequest): Promise {\n return this.controller.logoutRedirect(logoutRequest);\n }\n\n /**\n * Clears local cache for the current user then opens a popup window prompting the user to sign-out of the server\n * @param logoutRequest\n */\n logoutPopup(logoutRequest?: EndSessionRequest): Promise {\n return this.controller.logoutPopup(logoutRequest);\n }\n\n /**\n * This function uses a hidden iframe to fetch an authorization code from the eSTS. There are cases where this may not work:\n * - Any browser using a form of Intelligent Tracking Prevention\n * - If there is not an established session with the service\n *\n * In these cases, the request must be done inside a popup or full frame redirect.\n *\n * For the cases where interaction is required, you cannot send a request with prompt=none.\n *\n * If your refresh token has expired, you can use this function to fetch a new set of tokens silently as long as\n * you session on the server still exists.\n * @param request {@link SsoSilentRequest}\n *\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\n */\n ssoSilent(request: SsoSilentRequest): Promise {\n return this.controller.ssoSilent(request);\n }\n\n /**\n * Gets the token cache for the application.\n */\n getTokenCache(): ITokenCache {\n return this.controller.getTokenCache();\n }\n\n /**\n * Returns the logger instance\n */\n getLogger(): Logger {\n return this.controller.getLogger();\n }\n\n /**\n * Replaces the default logger set in configurations with new Logger with new configurations\n * @param logger Logger instance\n */\n setLogger(logger: Logger): void {\n this.controller.setLogger(logger);\n }\n\n /**\n * Sets the account to use as the active account. If no account is passed to the acquireToken APIs, then MSAL will use this active account.\n * @param account\n */\n setActiveAccount(account: AccountInfo | null): void {\n this.controller.setActiveAccount(account);\n }\n\n /**\n * Gets the currently active account\n */\n getActiveAccount(): AccountInfo | null {\n return this.controller.getActiveAccount();\n }\n\n /**\n * Called by wrapper libraries (Angular & React) to set SKU and Version passed down to telemetry, logger, etc.\n * @param sku\n * @param version\n */\n initializeWrapperLibrary(sku: WrapperSKU, version: string): void {\n return this.controller.initializeWrapperLibrary(sku, version);\n }\n\n /**\n * Sets navigation client\n * @param navigationClient\n */\n setNavigationClient(navigationClient: INavigationClient): void {\n this.controller.setNavigationClient(navigationClient);\n }\n\n /**\n * Returns the configuration object\n * @internal\n */\n getConfiguration(): BrowserConfiguration {\n return this.controller.getConfiguration();\n }\n\n /**\n * Hydrates cache with the tokens and account in the AuthenticationResult object\n * @param result\n * @param request - The request object that was used to obtain the AuthenticationResult\n * @returns\n */\n async hydrateCache(\n result: AuthenticationResult,\n request:\n | SilentRequest\n | SsoSilentRequest\n | RedirectRequest\n | PopupRequest\n ): Promise {\n return this.controller.hydrateCache(result, request);\n }\n\n /**\n * Clears tokens and account from the browser cache.\n * @param logoutRequest\n */\n clearCache(logoutRequest?: ClearCacheRequest): Promise {\n return this.controller.clearCache(logoutRequest);\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n AccountFilter,\n AccountInfo,\n Logger,\n PerformanceCallbackFunction,\n} from \"@azure/msal-common/browser\";\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\nimport { PopupRequest } from \"../request/PopupRequest.js\";\nimport { SilentRequest } from \"../request/SilentRequest.js\";\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\nimport {\n BrowserConfigurationAuthErrorCodes,\n createBrowserConfigurationAuthError,\n} from \"../error/BrowserConfigurationAuthError.js\";\nimport { WrapperSKU } from \"../utils/BrowserConstants.js\";\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\nimport { EndSessionPopupRequest } from \"../request/EndSessionPopupRequest.js\";\nimport { ITokenCache } from \"../cache/ITokenCache.js\";\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\nimport { EventCallbackFunction } from \"../event/EventMessage.js\";\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\nimport { InitializeApplicationRequest } from \"../request/InitializeApplicationRequest.js\";\nimport { EventType } from \"../event/EventType.js\";\n\nexport interface IPublicClientApplication {\n // TODO: Make request mandatory in the next major version?\n initialize(request?: InitializeApplicationRequest): Promise;\n acquireTokenPopup(request: PopupRequest): Promise;\n acquireTokenRedirect(request: RedirectRequest): Promise;\n acquireTokenSilent(\n silentRequest: SilentRequest\n ): Promise;\n acquireTokenByCode(\n request: AuthorizationCodeRequest\n ): Promise;\n addEventCallback(\n callback: EventCallbackFunction,\n eventTypes?: Array\n ): string | null;\n removeEventCallback(callbackId: string): void;\n addPerformanceCallback(callback: PerformanceCallbackFunction): string;\n removePerformanceCallback(callbackId: string): boolean;\n enableAccountStorageEvents(): void;\n disableAccountStorageEvents(): void;\n getAccount(accountFilter: AccountFilter): AccountInfo | null;\n getAccountByHomeId(homeAccountId: string): AccountInfo | null;\n getAccountByLocalId(localId: string): AccountInfo | null;\n getAccountByUsername(userName: string): AccountInfo | null;\n getAllAccounts(): AccountInfo[];\n handleRedirectPromise(hash?: string): Promise;\n loginPopup(request?: PopupRequest): Promise;\n loginRedirect(request?: RedirectRequest): Promise;\n logout(logoutRequest?: EndSessionRequest): Promise;\n logoutRedirect(logoutRequest?: EndSessionRequest): Promise;\n logoutPopup(logoutRequest?: EndSessionPopupRequest): Promise;\n ssoSilent(request: SsoSilentRequest): Promise;\n getTokenCache(): ITokenCache;\n getLogger(): Logger;\n setLogger(logger: Logger): void;\n setActiveAccount(account: AccountInfo | null): void;\n getActiveAccount(): AccountInfo | null;\n initializeWrapperLibrary(sku: WrapperSKU, version: string): void;\n setNavigationClient(navigationClient: INavigationClient): void;\n /** @internal */\n getConfiguration(): BrowserConfiguration;\n hydrateCache(\n result: AuthenticationResult,\n request:\n | SilentRequest\n | SsoSilentRequest\n | RedirectRequest\n | PopupRequest\n ): Promise;\n clearCache(logoutRequest?: ClearCacheRequest): Promise;\n}\n\nexport const stubbedPublicClientApplication: IPublicClientApplication = {\n initialize: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n acquireTokenPopup: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n acquireTokenRedirect: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n acquireTokenSilent: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n acquireTokenByCode: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n getAllAccounts: () => {\n return [];\n },\n getAccount: () => {\n return null;\n },\n getAccountByHomeId: () => {\n return null;\n },\n getAccountByUsername: () => {\n return null;\n },\n getAccountByLocalId: () => {\n return null;\n },\n handleRedirectPromise: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n loginPopup: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n loginRedirect: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n logout: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n logoutRedirect: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n logoutPopup: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n ssoSilent: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n addEventCallback: () => {\n return null;\n },\n removeEventCallback: () => {\n return;\n },\n addPerformanceCallback: () => {\n return \"\";\n },\n removePerformanceCallback: () => {\n return false;\n },\n enableAccountStorageEvents: () => {\n return;\n },\n disableAccountStorageEvents: () => {\n return;\n },\n getTokenCache: () => {\n throw createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n );\n },\n getLogger: () => {\n throw createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n );\n },\n setLogger: () => {\n return;\n },\n setActiveAccount: () => {\n return;\n },\n getActiveAccount: () => {\n return null;\n },\n initializeWrapperLibrary: () => {\n return;\n },\n setNavigationClient: () => {\n return;\n },\n getConfiguration: () => {\n throw createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n );\n },\n hydrateCache: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n clearCache: () => {\n return Promise.reject(\n createBrowserConfigurationAuthError(\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\n )\n );\n },\n};\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AuthError, AccountInfo } from \"@azure/msal-common/browser\";\nimport { EventType } from \"./EventType.js\";\nimport {\n InteractionStatus,\n InteractionType,\n} from \"../utils/BrowserConstants.js\";\nimport { PopupRequest } from \"../request/PopupRequest.js\";\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\nimport { SilentRequest } from \"../request/SilentRequest.js\";\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\n\nexport type EventMessage = {\n eventType: EventType;\n interactionType: InteractionType | null;\n payload: EventPayload;\n error: EventError;\n timestamp: number;\n};\n\nexport type PopupEvent = {\n popupWindow: Window;\n};\n\n/**\n * Payload for the BrokerConnectionEstablished event\n */\nexport type BrokerConnectionEvent = {\n /**\n * The origin of the broker that is connected to the client\n */\n pairwiseBrokerOrigin: string;\n};\n\nexport type EventPayload =\n | AccountInfo\n | PopupRequest\n | RedirectRequest\n | SilentRequest\n | SsoSilentRequest\n | EndSessionRequest\n | AuthenticationResult\n | PopupEvent\n | BrokerConnectionEvent\n | null;\n\nexport type EventError = AuthError | Error | null;\n\nexport type EventCallbackFunction = (message: EventMessage) => void;\n\nexport class EventMessageUtils {\n /**\n * Gets interaction status from event message\n * @param message\n * @param currentStatus\n */\n static getInteractionStatusFromEvent(\n message: EventMessage,\n currentStatus?: InteractionStatus\n ): InteractionStatus | null {\n switch (message.eventType) {\n case EventType.LOGIN_START:\n return InteractionStatus.Login;\n case EventType.SSO_SILENT_START:\n return InteractionStatus.SsoSilent;\n case EventType.ACQUIRE_TOKEN_START:\n if (\n message.interactionType === InteractionType.Redirect ||\n message.interactionType === InteractionType.Popup\n ) {\n return InteractionStatus.AcquireToken;\n }\n break;\n case EventType.HANDLE_REDIRECT_START:\n return InteractionStatus.HandleRedirect;\n case EventType.LOGOUT_START:\n return InteractionStatus.Logout;\n case EventType.SSO_SILENT_SUCCESS:\n case EventType.SSO_SILENT_FAILURE:\n if (\n currentStatus &&\n currentStatus !== InteractionStatus.SsoSilent\n ) {\n // Prevent this event from clearing any status other than ssoSilent\n break;\n }\n return InteractionStatus.None;\n case EventType.LOGOUT_END:\n if (\n currentStatus &&\n currentStatus !== InteractionStatus.Logout\n ) {\n // Prevent this event from clearing any status other than logout\n break;\n }\n return InteractionStatus.None;\n case EventType.HANDLE_REDIRECT_END:\n if (\n currentStatus &&\n currentStatus !== InteractionStatus.HandleRedirect\n ) {\n // Prevent this event from clearing any status other than handleRedirect\n break;\n }\n return InteractionStatus.None;\n case EventType.LOGIN_SUCCESS:\n case EventType.LOGIN_FAILURE:\n case EventType.ACQUIRE_TOKEN_SUCCESS:\n case EventType.ACQUIRE_TOKEN_FAILURE:\n case EventType.RESTORE_FROM_BFCACHE:\n if (\n message.interactionType === InteractionType.Redirect ||\n message.interactionType === InteractionType.Popup\n ) {\n if (\n currentStatus &&\n currentStatus !== InteractionStatus.Login &&\n currentStatus !== InteractionStatus.AcquireToken\n ) {\n // Prevent this event from clearing any status other than login or acquireToken\n break;\n }\n return InteractionStatus.None;\n }\n break;\n default:\n break;\n }\n return null;\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { CryptoOps } from \"./CryptoOps.js\";\nimport {\n ClientAuthError,\n ClientAuthErrorCodes,\n Logger,\n LoggerOptions,\n PopTokenGenerator,\n SignedHttpRequestParameters,\n} from \"@azure/msal-common/browser\";\nimport { version, name } from \"../packageMetadata.js\";\n\nexport type SignedHttpRequestOptions = {\n loggerOptions: LoggerOptions;\n};\n\nexport class SignedHttpRequest {\n private popTokenGenerator: PopTokenGenerator;\n private cryptoOps: CryptoOps;\n private shrParameters: SignedHttpRequestParameters;\n private logger: Logger;\n\n constructor(\n shrParameters: SignedHttpRequestParameters,\n shrOptions?: SignedHttpRequestOptions\n ) {\n const loggerOptions = (shrOptions && shrOptions.loggerOptions) || {};\n this.logger = new Logger(loggerOptions, name, version);\n this.cryptoOps = new CryptoOps(this.logger);\n this.popTokenGenerator = new PopTokenGenerator(this.cryptoOps);\n this.shrParameters = shrParameters;\n }\n\n /**\n * Generates and caches a keypair for the given request options.\n * @returns Public key digest, which should be sent to the token issuer.\n */\n async generatePublicKeyThumbprint(): Promise {\n const { kid } = await this.popTokenGenerator.generateKid(\n this.shrParameters\n );\n\n return kid;\n }\n\n /**\n * Generates a signed http request for the given payload with the given key.\n * @param payload Payload to sign (e.g. access token)\n * @param publicKeyThumbprint Public key digest (from generatePublicKeyThumbprint API)\n * @param claims Additional claims to include/override in the signed JWT\n * @returns Pop token signed with the corresponding private key\n */\n async signRequest(\n payload: string,\n publicKeyThumbprint: string,\n claims?: object\n ): Promise {\n return this.popTokenGenerator.signPayload(\n payload,\n publicKeyThumbprint,\n this.shrParameters,\n claims\n );\n }\n\n /**\n * Removes cached keys from browser for given public key thumbprint\n * @param publicKeyThumbprint Public key digest (from generatePublicKeyThumbprint API)\n * @returns If keys are properly deleted\n */\n async removeKeys(publicKeyThumbprint: string): Promise {\n return this.cryptoOps\n .removeTokenBindingKey(publicKeyThumbprint)\n .then(() => true)\n .catch((error) => {\n /*\n * @deprecated - To maintain public API signature, we return false if the error is due to the key still being present in indexedDB.\n */\n if (\n error instanceof ClientAuthError &&\n error.errorCode ===\n ClientAuthErrorCodes.bindingKeyNotRemoved\n ) {\n return false;\n }\n\n throw error;\n });\n }\n}\n", "/*\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n Constants,\n InProgressPerformanceEvent,\n IPerformanceClient,\n Logger,\n PerformanceClient,\n PerformanceEvent,\n PerformanceEvents,\n PreQueueEvent,\n SubMeasurement,\n} from \"@azure/msal-common/browser\";\nimport { Configuration } from \"../config/Configuration.js\";\nimport { name, version } from \"../packageMetadata.js\";\nimport { BrowserCacheLocation } from \"../utils/BrowserConstants.js\";\nimport * as BrowserCrypto from \"../crypto/BrowserCrypto.js\";\nimport { BROWSER_PERF_ENABLED_KEY } from \"../cache/CacheKeys.js\";\n\n/**\n * Returns browser performance measurement module if session flag is enabled. Returns undefined otherwise.\n */\nfunction getPerfMeasurementModule() {\n let sessionStorage: Storage | undefined;\n try {\n sessionStorage = window[BrowserCacheLocation.SessionStorage];\n const perfEnabled = sessionStorage?.getItem(BROWSER_PERF_ENABLED_KEY);\n if (Number(perfEnabled) === 1) {\n return import(\"./BrowserPerformanceMeasurement.js\");\n }\n // Mute errors if it's a non-browser environment or cookies are blocked.\n } catch (e) {}\n\n return undefined;\n}\n\n/**\n * Returns boolean, indicating whether browser supports window.performance.now() function.\n */\nfunction supportsBrowserPerformanceNow(): boolean {\n return (\n typeof window !== \"undefined\" &&\n typeof window.performance !== \"undefined\" &&\n typeof window.performance.now === \"function\"\n );\n}\n\n/**\n * Returns event duration in milliseconds using window performance API if available. Returns undefined otherwise.\n * @param startTime {DOMHighResTimeStamp | undefined}\n * @returns {number | undefined}\n */\nfunction getPerfDurationMs(\n startTime: DOMHighResTimeStamp | undefined\n): number | undefined {\n if (!startTime || !supportsBrowserPerformanceNow()) {\n return undefined;\n }\n\n return Math.round(window.performance.now() - startTime);\n}\n\nexport class BrowserPerformanceClient\n extends PerformanceClient\n implements IPerformanceClient\n{\n constructor(\n configuration: Configuration,\n intFields?: Set,\n abbreviations?: Map\n ) {\n super(\n configuration.auth.clientId,\n configuration.auth.authority || `${Constants.DEFAULT_AUTHORITY}`,\n new Logger(\n configuration.system?.loggerOptions || {},\n name,\n version\n ),\n name,\n version,\n configuration.telemetry?.application || {\n appName: \"\",\n appVersion: \"\",\n },\n intFields,\n abbreviations\n );\n }\n\n generateId(): string {\n return BrowserCrypto.createNewGuid();\n }\n\n private getPageVisibility(): string | null {\n return document.visibilityState?.toString() || null;\n }\n\n private deleteIncompleteSubMeasurements(\n inProgressEvent: InProgressPerformanceEvent\n ): void {\n void getPerfMeasurementModule()?.then((module) => {\n const rootEvent = this.eventsByCorrelationId.get(\n inProgressEvent.event.correlationId\n );\n const isRootEvent =\n rootEvent &&\n rootEvent.eventId === inProgressEvent.event.eventId;\n const incompleteMeasurements: SubMeasurement[] = [];\n if (isRootEvent && rootEvent?.incompleteSubMeasurements) {\n rootEvent.incompleteSubMeasurements.forEach(\n (subMeasurement: SubMeasurement) => {\n incompleteMeasurements.push({ ...subMeasurement });\n }\n );\n }\n // Clean up remaining marks for incomplete sub-measurements\n module.BrowserPerformanceMeasurement.flushMeasurements(\n inProgressEvent.event.correlationId,\n incompleteMeasurements\n );\n });\n }\n\n /**\n * Starts measuring performance for a given operation. Returns a function that should be used to end the measurement.\n * Also captures browser page visibilityState.\n *\n * @param {PerformanceEvents} measureName\n * @param {?string} [correlationId]\n * @returns {((event?: Partial) => PerformanceEvent| null)}\n */\n startMeasurement(\n measureName: string,\n correlationId?: string\n ): InProgressPerformanceEvent {\n // Capture page visibilityState and then invoke start/end measurement\n const startPageVisibility = this.getPageVisibility();\n const inProgressEvent = super.startMeasurement(\n measureName,\n correlationId\n );\n const startTime: number | undefined = supportsBrowserPerformanceNow()\n ? window.performance.now()\n : undefined;\n\n const browserMeasurement = getPerfMeasurementModule()?.then(\n (module) => {\n return new module.BrowserPerformanceMeasurement(\n measureName,\n inProgressEvent.event.correlationId\n );\n }\n );\n void browserMeasurement?.then((measurement) =>\n measurement.startMeasurement()\n );\n\n return {\n ...inProgressEvent,\n end: (\n event?: Partial,\n error?: unknown\n ): PerformanceEvent | null => {\n const res = inProgressEvent.end(\n {\n ...event,\n startPageVisibility,\n endPageVisibility: this.getPageVisibility(),\n durationMs: getPerfDurationMs(startTime),\n },\n error\n );\n void browserMeasurement?.then((measurement) =>\n measurement.endMeasurement()\n );\n this.deleteIncompleteSubMeasurements(inProgressEvent);\n\n return res;\n },\n discard: () => {\n inProgressEvent.discard();\n void browserMeasurement?.then((measurement) =>\n measurement.flushMeasurement()\n );\n this.deleteIncompleteSubMeasurements(inProgressEvent);\n },\n };\n }\n\n /**\n * Adds pre-queue time to preQueueTimeByCorrelationId map.\n * @param {PerformanceEvents} eventName\n * @param {?string} correlationId\n * @returns\n */\n setPreQueueTime(\n eventName: PerformanceEvents,\n correlationId?: string\n ): void {\n if (!supportsBrowserPerformanceNow()) {\n this.logger.trace(\n `BrowserPerformanceClient: window performance API not available, unable to set telemetry queue time for ${eventName}`\n );\n return;\n }\n\n if (!correlationId) {\n this.logger.trace(\n `BrowserPerformanceClient: correlationId for ${eventName} not provided, unable to set telemetry queue time`\n );\n return;\n }\n\n const preQueueEvent: PreQueueEvent | undefined =\n this.preQueueTimeByCorrelationId.get(correlationId);\n /**\n * Manually complete queue measurement if there is an incomplete pre-queue event.\n * Incomplete pre-queue events are instrumentation bugs that should be fixed.\n */\n if (preQueueEvent) {\n this.logger.trace(\n `BrowserPerformanceClient: Incomplete pre-queue ${preQueueEvent.name} found`,\n correlationId\n );\n this.addQueueMeasurement(\n preQueueEvent.name,\n correlationId,\n undefined,\n true\n );\n }\n this.preQueueTimeByCorrelationId.set(correlationId, {\n name: eventName,\n time: window.performance.now(),\n });\n }\n\n /**\n * Calculates and adds queue time measurement for given performance event.\n *\n * @param {PerformanceEvents} eventName\n * @param {?string} correlationId\n * @param {?number} queueTime\n * @param {?boolean} manuallyCompleted - indicator for manually completed queue measurements\n * @returns\n */\n addQueueMeasurement(\n eventName: string,\n correlationId?: string,\n queueTime?: number,\n manuallyCompleted?: boolean\n ): void {\n if (!supportsBrowserPerformanceNow()) {\n this.logger.trace(\n `BrowserPerformanceClient: window performance API not available, unable to add queue measurement for ${eventName}`\n );\n return;\n }\n\n if (!correlationId) {\n this.logger.trace(\n `BrowserPerformanceClient: correlationId for ${eventName} not provided, unable to add queue measurement`\n );\n return;\n }\n\n const preQueueTime = super.getPreQueueTime(eventName, correlationId);\n if (!preQueueTime) {\n return;\n }\n\n const currentTime = window.performance.now();\n const resQueueTime =\n queueTime || super.calculateQueuedTime(preQueueTime, currentTime);\n\n return super.addQueueMeasurement(\n eventName,\n correlationId,\n resQueueTime,\n manuallyCompleted\n );\n }\n}\n"], + "sourcesContent": ["/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport const Constants = {\r\n LIBRARY_NAME: \"MSAL.JS\",\r\n SKU: \"msal.js.common\",\r\n // default authority\r\n DEFAULT_AUTHORITY: \"https://login.microsoftonline.com/common/\",\r\n DEFAULT_AUTHORITY_HOST: \"login.microsoftonline.com\",\r\n DEFAULT_COMMON_TENANT: \"common\",\r\n // ADFS String\r\n ADFS: \"adfs\",\r\n DSTS: \"dstsv2\",\r\n // Default AAD Instance Discovery Endpoint\r\n AAD_INSTANCE_DISCOVERY_ENDPT:\r\n \"https://login.microsoftonline.com/common/discovery/instance?api-version=1.1&authorization_endpoint=\",\r\n // CIAM URL\r\n CIAM_AUTH_URL: \".ciamlogin.com\",\r\n AAD_TENANT_DOMAIN_SUFFIX: \".onmicrosoft.com\",\r\n // Resource delimiter - used for certain cache entries\r\n RESOURCE_DELIM: \"|\",\r\n // Placeholder for non-existent account ids/objects\r\n NO_ACCOUNT: \"NO_ACCOUNT\",\r\n // Claims\r\n CLAIMS: \"claims\",\r\n // Consumer UTID\r\n CONSUMER_UTID: \"9188040d-6c67-4c5b-b112-36a304b66dad\",\r\n // Default scopes\r\n OPENID_SCOPE: \"openid\",\r\n PROFILE_SCOPE: \"profile\",\r\n OFFLINE_ACCESS_SCOPE: \"offline_access\",\r\n EMAIL_SCOPE: \"email\",\r\n CODE_GRANT_TYPE: \"authorization_code\",\r\n RT_GRANT_TYPE: \"refresh_token\",\r\n S256_CODE_CHALLENGE_METHOD: \"S256\",\r\n URL_FORM_CONTENT_TYPE: \"application/x-www-form-urlencoded;charset=utf-8\",\r\n AUTHORIZATION_PENDING: \"authorization_pending\",\r\n NOT_DEFINED: \"not_defined\",\r\n EMPTY_STRING: \"\",\r\n NOT_APPLICABLE: \"N/A\",\r\n NOT_AVAILABLE: \"Not Available\",\r\n FORWARD_SLASH: \"/\",\r\n IMDS_ENDPOINT: \"http://169.254.169.254/metadata/instance/compute/location\",\r\n IMDS_VERSION: \"2020-06-01\",\r\n IMDS_TIMEOUT: 2000,\r\n AZURE_REGION_AUTO_DISCOVER_FLAG: \"TryAutoDetect\",\r\n REGIONAL_AUTH_PUBLIC_CLOUD_SUFFIX: \"login.microsoft.com\",\r\n KNOWN_PUBLIC_CLOUDS: [\r\n \"login.microsoftonline.com\",\r\n \"login.windows.net\",\r\n \"login.microsoft.com\",\r\n \"sts.windows.net\",\r\n ],\r\n SHR_NONCE_VALIDITY: 240,\r\n INVALID_INSTANCE: \"invalid_instance\",\r\n};\r\n\r\nexport const HttpStatus = {\r\n SUCCESS: 200,\r\n SUCCESS_RANGE_START: 200,\r\n SUCCESS_RANGE_END: 299,\r\n REDIRECT: 302,\r\n CLIENT_ERROR: 400,\r\n CLIENT_ERROR_RANGE_START: 400,\r\n BAD_REQUEST: 400,\r\n UNAUTHORIZED: 401,\r\n NOT_FOUND: 404,\r\n REQUEST_TIMEOUT: 408,\r\n GONE: 410,\r\n TOO_MANY_REQUESTS: 429,\r\n CLIENT_ERROR_RANGE_END: 499,\r\n SERVER_ERROR: 500,\r\n SERVER_ERROR_RANGE_START: 500,\r\n SERVICE_UNAVAILABLE: 503,\r\n GATEWAY_TIMEOUT: 504,\r\n SERVER_ERROR_RANGE_END: 599,\r\n MULTI_SIDED_ERROR: 600,\r\n} as const;\r\nexport type HttpStatus = (typeof HttpStatus)[keyof typeof HttpStatus];\r\n\r\nexport const HttpMethod = {\r\n GET: \"GET\",\r\n POST: \"POST\",\r\n} as const;\r\nexport type HttpMethod = (typeof HttpMethod)[keyof typeof HttpMethod];\r\n\r\nexport const OIDC_DEFAULT_SCOPES = [\r\n Constants.OPENID_SCOPE,\r\n Constants.PROFILE_SCOPE,\r\n Constants.OFFLINE_ACCESS_SCOPE,\r\n];\r\n\r\nexport const OIDC_SCOPES = [...OIDC_DEFAULT_SCOPES, Constants.EMAIL_SCOPE];\r\n\r\n/**\r\n * Request header names\r\n */\r\nexport const HeaderNames = {\r\n CONTENT_TYPE: \"Content-Type\",\r\n CONTENT_LENGTH: \"Content-Length\",\r\n RETRY_AFTER: \"Retry-After\",\r\n CCS_HEADER: \"X-AnchorMailbox\",\r\n WWWAuthenticate: \"WWW-Authenticate\",\r\n AuthenticationInfo: \"Authentication-Info\",\r\n X_MS_REQUEST_ID: \"x-ms-request-id\",\r\n X_MS_HTTP_VERSION: \"x-ms-httpver\",\r\n} as const;\r\nexport type HeaderNames = (typeof HeaderNames)[keyof typeof HeaderNames];\r\n\r\n/**\r\n * Persistent cache keys MSAL which stay while user is logged in.\r\n */\r\nexport const PersistentCacheKeys = {\r\n ACTIVE_ACCOUNT_FILTERS: \"active-account-filters\", // new cache entry for active_account for a more robust version for browser\r\n} as const;\r\nexport type PersistentCacheKeys =\r\n (typeof PersistentCacheKeys)[keyof typeof PersistentCacheKeys];\r\n\r\n/**\r\n * String constants related to AAD Authority\r\n */\r\nexport const AADAuthorityConstants = {\r\n COMMON: \"common\",\r\n ORGANIZATIONS: \"organizations\",\r\n CONSUMERS: \"consumers\",\r\n} as const;\r\nexport type AADAuthorityConstants =\r\n (typeof AADAuthorityConstants)[keyof typeof AADAuthorityConstants];\r\n\r\n/**\r\n * Claims request keys\r\n */\r\nexport const ClaimsRequestKeys = {\r\n ACCESS_TOKEN: \"access_token\",\r\n XMS_CC: \"xms_cc\",\r\n} as const;\r\nexport type ClaimsRequestKeys =\r\n (typeof ClaimsRequestKeys)[keyof typeof ClaimsRequestKeys];\r\n\r\n/**\r\n * we considered making this \"enum\" in the request instead of string, however it looks like the allowed list of\r\n * prompt values kept changing over past couple of years. There are some undocumented prompt values for some\r\n * internal partners too, hence the choice of generic \"string\" type instead of the \"enum\"\r\n */\r\nexport const PromptValue = {\r\n LOGIN: \"login\",\r\n SELECT_ACCOUNT: \"select_account\",\r\n CONSENT: \"consent\",\r\n NONE: \"none\",\r\n CREATE: \"create\",\r\n NO_SESSION: \"no_session\",\r\n};\r\n\r\n/**\r\n * allowed values for codeVerifier\r\n */\r\nexport const CodeChallengeMethodValues = {\r\n PLAIN: \"plain\",\r\n S256: \"S256\",\r\n};\r\n\r\n/**\r\n * Allowed values for response_type\r\n */\r\nexport const OAuthResponseType = {\r\n CODE: \"code\",\r\n IDTOKEN_TOKEN: \"id_token token\",\r\n IDTOKEN_TOKEN_REFRESHTOKEN: \"id_token token refresh_token\",\r\n} as const;\r\nexport type OAuthResponseType =\r\n (typeof OAuthResponseType)[keyof typeof OAuthResponseType];\r\n\r\n/**\r\n * allowed values for server response type\r\n * @deprecated Use ResponseMode instead\r\n */\r\nexport const ServerResponseType = {\r\n QUERY: \"query\",\r\n FRAGMENT: \"fragment\",\r\n} as const;\r\nexport type ServerResponseType =\r\n (typeof ServerResponseType)[keyof typeof ServerResponseType];\r\n\r\n/**\r\n * allowed values for response_mode\r\n */\r\nexport const ResponseMode = {\r\n QUERY: \"query\",\r\n FRAGMENT: \"fragment\",\r\n FORM_POST: \"form_post\",\r\n} as const;\r\nexport type ResponseMode = (typeof ResponseMode)[keyof typeof ResponseMode];\r\n\r\n/**\r\n * allowed grant_type\r\n */\r\nexport const GrantType = {\r\n IMPLICIT_GRANT: \"implicit\",\r\n AUTHORIZATION_CODE_GRANT: \"authorization_code\",\r\n CLIENT_CREDENTIALS_GRANT: \"client_credentials\",\r\n RESOURCE_OWNER_PASSWORD_GRANT: \"password\",\r\n REFRESH_TOKEN_GRANT: \"refresh_token\",\r\n DEVICE_CODE_GRANT: \"device_code\",\r\n JWT_BEARER: \"urn:ietf:params:oauth:grant-type:jwt-bearer\",\r\n} as const;\r\nexport type GrantType = (typeof GrantType)[keyof typeof GrantType];\r\n\r\n/**\r\n * Account types in Cache\r\n */\r\nexport const CacheAccountType = {\r\n MSSTS_ACCOUNT_TYPE: \"MSSTS\",\r\n ADFS_ACCOUNT_TYPE: \"ADFS\",\r\n MSAV1_ACCOUNT_TYPE: \"MSA\",\r\n GENERIC_ACCOUNT_TYPE: \"Generic\", // NTLM, Kerberos, FBA, Basic etc\r\n} as const;\r\nexport type CacheAccountType =\r\n (typeof CacheAccountType)[keyof typeof CacheAccountType];\r\n\r\n/**\r\n * Separators used in cache\r\n */\r\nexport const Separators = {\r\n CACHE_KEY_SEPARATOR: \"-\",\r\n CLIENT_INFO_SEPARATOR: \".\",\r\n} as const;\r\nexport type Separators = (typeof Separators)[keyof typeof Separators];\r\n\r\n/**\r\n * Credential Type stored in the cache\r\n */\r\nexport const CredentialType = {\r\n ID_TOKEN: \"IdToken\",\r\n ACCESS_TOKEN: \"AccessToken\",\r\n ACCESS_TOKEN_WITH_AUTH_SCHEME: \"AccessToken_With_AuthScheme\",\r\n REFRESH_TOKEN: \"RefreshToken\",\r\n} as const;\r\nexport type CredentialType =\r\n (typeof CredentialType)[keyof typeof CredentialType];\r\n\r\n/**\r\n * Combine all cache types\r\n */\r\nexport const CacheType = {\r\n ADFS: 1001,\r\n MSA: 1002,\r\n MSSTS: 1003,\r\n GENERIC: 1004,\r\n ACCESS_TOKEN: 2001,\r\n REFRESH_TOKEN: 2002,\r\n ID_TOKEN: 2003,\r\n APP_METADATA: 3001,\r\n UNDEFINED: 9999,\r\n} as const;\r\nexport type CacheType = (typeof CacheType)[keyof typeof CacheType];\r\n\r\n/**\r\n * More Cache related constants\r\n */\r\nexport const APP_METADATA = \"appmetadata\";\r\nexport const CLIENT_INFO = \"client_info\";\r\nexport const THE_FAMILY_ID = \"1\";\r\n\r\nexport const AUTHORITY_METADATA_CONSTANTS = {\r\n CACHE_KEY: \"authority-metadata\",\r\n REFRESH_TIME_SECONDS: 3600 * 24, // 24 Hours\r\n};\r\n\r\nexport const AuthorityMetadataSource = {\r\n CONFIG: \"config\",\r\n CACHE: \"cache\",\r\n NETWORK: \"network\",\r\n HARDCODED_VALUES: \"hardcoded_values\",\r\n} as const;\r\nexport type AuthorityMetadataSource =\r\n (typeof AuthorityMetadataSource)[keyof typeof AuthorityMetadataSource];\r\n\r\nexport const SERVER_TELEM_CONSTANTS = {\r\n SCHEMA_VERSION: 5,\r\n MAX_CUR_HEADER_BYTES: 80, // ESTS limit is 100B, set to 80 to provide a 20B buffer\r\n MAX_LAST_HEADER_BYTES: 330, // ESTS limit is 350B, set to 330 to provide a 20B buffer,\r\n MAX_CACHED_ERRORS: 50, // Limit the number of errors that can be stored to prevent uncontrolled size gains\r\n CACHE_KEY: \"server-telemetry\",\r\n CATEGORY_SEPARATOR: \"|\",\r\n VALUE_SEPARATOR: \",\",\r\n OVERFLOW_TRUE: \"1\",\r\n OVERFLOW_FALSE: \"0\",\r\n UNKNOWN_ERROR: \"unknown_error\",\r\n};\r\n\r\n/**\r\n * Type of the authentication request\r\n */\r\nexport const AuthenticationScheme = {\r\n BEARER: \"Bearer\",\r\n POP: \"pop\",\r\n SSH: \"ssh-cert\",\r\n} as const;\r\nexport type AuthenticationScheme =\r\n (typeof AuthenticationScheme)[keyof typeof AuthenticationScheme];\r\n\r\n/**\r\n * Constants related to throttling\r\n */\r\nexport const ThrottlingConstants = {\r\n // Default time to throttle RequestThumbprint in seconds\r\n DEFAULT_THROTTLE_TIME_SECONDS: 60,\r\n // Default maximum time to throttle in seconds, overrides what the server sends back\r\n DEFAULT_MAX_THROTTLE_TIME_SECONDS: 3600,\r\n // Prefix for storing throttling entries\r\n THROTTLING_PREFIX: \"throttling\",\r\n // Value assigned to the x-ms-lib-capability header to indicate to the server the library supports throttling\r\n X_MS_LIB_CAPABILITY_VALUE: \"retry-after, h429\",\r\n};\r\n\r\nexport const Errors = {\r\n INVALID_GRANT_ERROR: \"invalid_grant\",\r\n CLIENT_MISMATCH_ERROR: \"client_mismatch\",\r\n};\r\n\r\n/**\r\n * Password grant parameters\r\n */\r\nexport const PasswordGrantConstants = {\r\n username: \"username\",\r\n password: \"password\",\r\n} as const;\r\nexport type PasswordGrantConstants =\r\n (typeof PasswordGrantConstants)[keyof typeof PasswordGrantConstants];\r\n\r\n/**\r\n * Region Discovery Sources\r\n */\r\nexport const RegionDiscoverySources = {\r\n FAILED_AUTO_DETECTION: \"1\",\r\n INTERNAL_CACHE: \"2\",\r\n ENVIRONMENT_VARIABLE: \"3\",\r\n IMDS: \"4\",\r\n} as const;\r\nexport type RegionDiscoverySources =\r\n (typeof RegionDiscoverySources)[keyof typeof RegionDiscoverySources];\r\n\r\n/**\r\n * Region Discovery Outcomes\r\n */\r\nexport const RegionDiscoveryOutcomes = {\r\n CONFIGURED_MATCHES_DETECTED: \"1\",\r\n CONFIGURED_NO_AUTO_DETECTION: \"2\",\r\n CONFIGURED_NOT_DETECTED: \"3\",\r\n AUTO_DETECTION_REQUESTED_SUCCESSFUL: \"4\",\r\n AUTO_DETECTION_REQUESTED_FAILED: \"5\",\r\n} as const;\r\nexport type RegionDiscoveryOutcomes =\r\n (typeof RegionDiscoveryOutcomes)[keyof typeof RegionDiscoveryOutcomes];\r\n\r\n/**\r\n * Specifies the reason for fetching the access token from the identity provider\r\n */\r\nexport const CacheOutcome = {\r\n // When a token is found in the cache or the cache is not supposed to be hit when making the request\r\n NOT_APPLICABLE: \"0\",\r\n // When the token request goes to the identity provider because force_refresh was set to true. Also occurs if claims were requested\r\n FORCE_REFRESH_OR_CLAIMS: \"1\",\r\n // When the token request goes to the identity provider because no cached access token exists\r\n NO_CACHED_ACCESS_TOKEN: \"2\",\r\n // When the token request goes to the identity provider because cached access token expired\r\n CACHED_ACCESS_TOKEN_EXPIRED: \"3\",\r\n // When the token request goes to the identity provider because refresh_in was used and the existing token needs to be refreshed\r\n PROACTIVELY_REFRESHED: \"4\",\r\n} as const;\r\nexport type CacheOutcome = (typeof CacheOutcome)[keyof typeof CacheOutcome];\r\n\r\nexport const JsonWebTokenTypes = {\r\n Jwt: \"JWT\",\r\n Jwk: \"JWK\",\r\n Pop: \"pop\",\r\n} as const;\r\nexport type JsonWebTokenTypes =\r\n (typeof JsonWebTokenTypes)[keyof typeof JsonWebTokenTypes];\r\n\r\nexport const ONE_DAY_IN_MS = 86400000;\r\n\r\n// Token renewal offset default in seconds\r\nexport const DEFAULT_TOKEN_RENEWAL_OFFSET_SEC = 300;\r\n\r\nexport const EncodingTypes = {\r\n BASE64: \"base64\",\r\n HEX: \"hex\",\r\n UTF8: \"utf-8\",\r\n} as const;\r\nexport type EncodingTypes = (typeof EncodingTypes)[keyof typeof EncodingTypes];\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n/**\r\n * AuthErrorMessage class containing string constants used by error codes and messages.\r\n */\r\nexport const unexpectedError = \"unexpected_error\";\r\nexport const postRequestFailed = \"post_request_failed\";\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { Constants } from \"../utils/Constants.js\";\r\nimport * as AuthErrorCodes from \"./AuthErrorCodes.js\";\r\nexport { AuthErrorCodes };\r\n\r\nexport const AuthErrorMessages = {\r\n [AuthErrorCodes.unexpectedError]: \"Unexpected error in authentication.\",\r\n [AuthErrorCodes.postRequestFailed]:\r\n \"Post request failed from the network, could be a 4xx/5xx or a network unavailability. Please check the exact error code for details.\",\r\n};\r\n\r\n/**\r\n * AuthErrorMessage class containing string constants used by error codes and messages.\r\n * @deprecated Use AuthErrorCodes instead\r\n */\r\nexport const AuthErrorMessage = {\r\n unexpectedError: {\r\n code: AuthErrorCodes.unexpectedError,\r\n desc: AuthErrorMessages[AuthErrorCodes.unexpectedError],\r\n },\r\n postRequestFailed: {\r\n code: AuthErrorCodes.postRequestFailed,\r\n desc: AuthErrorMessages[AuthErrorCodes.postRequestFailed],\r\n },\r\n};\r\n\r\n/**\r\n * General error class thrown by the MSAL.js library.\r\n */\r\nexport class AuthError extends Error {\r\n /**\r\n * Short string denoting error\r\n */\r\n errorCode: string;\r\n\r\n /**\r\n * Detailed description of error\r\n */\r\n errorMessage: string;\r\n\r\n /**\r\n * Describes the subclass of an error\r\n */\r\n subError: string;\r\n\r\n /**\r\n * CorrelationId associated with the error\r\n */\r\n correlationId: string;\r\n\r\n constructor(errorCode?: string, errorMessage?: string, suberror?: string) {\r\n const errorString = errorMessage\r\n ? `${errorCode}: ${errorMessage}`\r\n : errorCode;\r\n super(errorString);\r\n Object.setPrototypeOf(this, AuthError.prototype);\r\n\r\n this.errorCode = errorCode || Constants.EMPTY_STRING;\r\n this.errorMessage = errorMessage || Constants.EMPTY_STRING;\r\n this.subError = suberror || Constants.EMPTY_STRING;\r\n this.name = \"AuthError\";\r\n }\r\n\r\n setCorrelationId(correlationId: string): void {\r\n this.correlationId = correlationId;\r\n }\r\n}\r\n\r\nexport function createAuthError(\r\n code: string,\r\n additionalMessage?: string\r\n): AuthError {\r\n return new AuthError(\r\n code,\r\n additionalMessage\r\n ? `${AuthErrorMessages[code]} ${additionalMessage}`\r\n : AuthErrorMessages[code]\r\n );\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport const clientInfoDecodingError = \"client_info_decoding_error\";\r\nexport const clientInfoEmptyError = \"client_info_empty_error\";\r\nexport const tokenParsingError = \"token_parsing_error\";\r\nexport const nullOrEmptyToken = \"null_or_empty_token\";\r\nexport const endpointResolutionError = \"endpoints_resolution_error\";\r\nexport const networkError = \"network_error\";\r\nexport const openIdConfigError = \"openid_config_error\";\r\nexport const hashNotDeserialized = \"hash_not_deserialized\";\r\nexport const invalidState = \"invalid_state\";\r\nexport const stateMismatch = \"state_mismatch\";\r\nexport const stateNotFound = \"state_not_found\";\r\nexport const nonceMismatch = \"nonce_mismatch\";\r\nexport const authTimeNotFound = \"auth_time_not_found\";\r\nexport const maxAgeTranspired = \"max_age_transpired\";\r\nexport const multipleMatchingTokens = \"multiple_matching_tokens\";\r\nexport const multipleMatchingAccounts = \"multiple_matching_accounts\";\r\nexport const multipleMatchingAppMetadata = \"multiple_matching_appMetadata\";\r\nexport const requestCannotBeMade = \"request_cannot_be_made\";\r\nexport const cannotRemoveEmptyScope = \"cannot_remove_empty_scope\";\r\nexport const cannotAppendScopeSet = \"cannot_append_scopeset\";\r\nexport const emptyInputScopeSet = \"empty_input_scopeset\";\r\nexport const deviceCodePollingCancelled = \"device_code_polling_cancelled\";\r\nexport const deviceCodeExpired = \"device_code_expired\";\r\nexport const deviceCodeUnknownError = \"device_code_unknown_error\";\r\nexport const noAccountInSilentRequest = \"no_account_in_silent_request\";\r\nexport const invalidCacheRecord = \"invalid_cache_record\";\r\nexport const invalidCacheEnvironment = \"invalid_cache_environment\";\r\nexport const noAccountFound = \"no_account_found\";\r\nexport const noCryptoObject = \"no_crypto_object\";\r\nexport const unexpectedCredentialType = \"unexpected_credential_type\";\r\nexport const invalidAssertion = \"invalid_assertion\";\r\nexport const invalidClientCredential = \"invalid_client_credential\";\r\nexport const tokenRefreshRequired = \"token_refresh_required\";\r\nexport const userTimeoutReached = \"user_timeout_reached\";\r\nexport const tokenClaimsCnfRequiredForSignedJwt =\r\n \"token_claims_cnf_required_for_signedjwt\";\r\nexport const authorizationCodeMissingFromServerResponse =\r\n \"authorization_code_missing_from_server_response\";\r\nexport const bindingKeyNotRemoved = \"binding_key_not_removed\";\r\nexport const endSessionEndpointNotSupported =\r\n \"end_session_endpoint_not_supported\";\r\nexport const keyIdMissing = \"key_id_missing\";\r\nexport const noNetworkConnectivity = \"no_network_connectivity\";\r\nexport const userCanceled = \"user_canceled\";\r\nexport const missingTenantIdError = \"missing_tenant_id_error\";\r\nexport const methodNotImplemented = \"method_not_implemented\";\r\nexport const nestedAppAuthBridgeDisabled = \"nested_app_auth_bridge_disabled\";\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthError } from \"./AuthError.js\";\r\nimport * as ClientAuthErrorCodes from \"./ClientAuthErrorCodes.js\";\r\nexport { ClientAuthErrorCodes }; // Allow importing as \"ClientAuthErrorCodes\";\r\n\r\n/**\r\n * ClientAuthErrorMessage class containing string constants used by error codes and messages.\r\n */\r\n\r\nexport const ClientAuthErrorMessages = {\r\n [ClientAuthErrorCodes.clientInfoDecodingError]:\r\n \"The client info could not be parsed/decoded correctly\",\r\n [ClientAuthErrorCodes.clientInfoEmptyError]: \"The client info was empty\",\r\n [ClientAuthErrorCodes.tokenParsingError]: \"Token cannot be parsed\",\r\n [ClientAuthErrorCodes.nullOrEmptyToken]: \"The token is null or empty\",\r\n [ClientAuthErrorCodes.endpointResolutionError]:\r\n \"Endpoints cannot be resolved\",\r\n [ClientAuthErrorCodes.networkError]: \"Network request failed\",\r\n [ClientAuthErrorCodes.openIdConfigError]:\r\n \"Could not retrieve endpoints. Check your authority and verify the .well-known/openid-configuration endpoint returns the required endpoints.\",\r\n [ClientAuthErrorCodes.hashNotDeserialized]:\r\n \"The hash parameters could not be deserialized\",\r\n [ClientAuthErrorCodes.invalidState]: \"State was not the expected format\",\r\n [ClientAuthErrorCodes.stateMismatch]: \"State mismatch error\",\r\n [ClientAuthErrorCodes.stateNotFound]: \"State not found\",\r\n [ClientAuthErrorCodes.nonceMismatch]: \"Nonce mismatch error\",\r\n [ClientAuthErrorCodes.authTimeNotFound]:\r\n \"Max Age was requested and the ID token is missing the auth_time variable.\" +\r\n \" auth_time is an optional claim and is not enabled by default - it must be enabled.\" +\r\n \" See https://aka.ms/msaljs/optional-claims for more information.\",\r\n [ClientAuthErrorCodes.maxAgeTranspired]:\r\n \"Max Age is set to 0, or too much time has elapsed since the last end-user authentication.\",\r\n [ClientAuthErrorCodes.multipleMatchingTokens]:\r\n \"The cache contains multiple tokens satisfying the requirements. \" +\r\n \"Call AcquireToken again providing more requirements such as authority or account.\",\r\n [ClientAuthErrorCodes.multipleMatchingAccounts]:\r\n \"The cache contains multiple accounts satisfying the given parameters. Please pass more info to obtain the correct account\",\r\n [ClientAuthErrorCodes.multipleMatchingAppMetadata]:\r\n \"The cache contains multiple appMetadata satisfying the given parameters. Please pass more info to obtain the correct appMetadata\",\r\n [ClientAuthErrorCodes.requestCannotBeMade]:\r\n \"Token request cannot be made without authorization code or refresh token.\",\r\n [ClientAuthErrorCodes.cannotRemoveEmptyScope]:\r\n \"Cannot remove null or empty scope from ScopeSet\",\r\n [ClientAuthErrorCodes.cannotAppendScopeSet]: \"Cannot append ScopeSet\",\r\n [ClientAuthErrorCodes.emptyInputScopeSet]:\r\n \"Empty input ScopeSet cannot be processed\",\r\n [ClientAuthErrorCodes.deviceCodePollingCancelled]:\r\n \"Caller has cancelled token endpoint polling during device code flow by setting DeviceCodeRequest.cancel = true.\",\r\n [ClientAuthErrorCodes.deviceCodeExpired]: \"Device code is expired.\",\r\n [ClientAuthErrorCodes.deviceCodeUnknownError]:\r\n \"Device code stopped polling for unknown reasons.\",\r\n [ClientAuthErrorCodes.noAccountInSilentRequest]:\r\n \"Please pass an account object, silent flow is not supported without account information\",\r\n [ClientAuthErrorCodes.invalidCacheRecord]:\r\n \"Cache record object was null or undefined.\",\r\n [ClientAuthErrorCodes.invalidCacheEnvironment]:\r\n \"Invalid environment when attempting to create cache entry\",\r\n [ClientAuthErrorCodes.noAccountFound]:\r\n \"No account found in cache for given key.\",\r\n [ClientAuthErrorCodes.noCryptoObject]: \"No crypto object detected.\",\r\n [ClientAuthErrorCodes.unexpectedCredentialType]:\r\n \"Unexpected credential type.\",\r\n [ClientAuthErrorCodes.invalidAssertion]:\r\n \"Client assertion must meet requirements described in https://tools.ietf.org/html/rfc7515\",\r\n [ClientAuthErrorCodes.invalidClientCredential]:\r\n \"Client credential (secret, certificate, or assertion) must not be empty when creating a confidential client. An application should at most have one credential\",\r\n [ClientAuthErrorCodes.tokenRefreshRequired]:\r\n \"Cannot return token from cache because it must be refreshed. This may be due to one of the following reasons: forceRefresh parameter is set to true, claims have been requested, there is no cached access token or it is expired.\",\r\n [ClientAuthErrorCodes.userTimeoutReached]:\r\n \"User defined timeout for device code polling reached\",\r\n [ClientAuthErrorCodes.tokenClaimsCnfRequiredForSignedJwt]:\r\n \"Cannot generate a POP jwt if the token_claims are not populated\",\r\n [ClientAuthErrorCodes.authorizationCodeMissingFromServerResponse]:\r\n \"Server response does not contain an authorization code to proceed\",\r\n [ClientAuthErrorCodes.bindingKeyNotRemoved]:\r\n \"Could not remove the credential's binding key from storage.\",\r\n [ClientAuthErrorCodes.endSessionEndpointNotSupported]:\r\n \"The provided authority does not support logout\",\r\n [ClientAuthErrorCodes.keyIdMissing]:\r\n \"A keyId value is missing from the requested bound token's cache record and is required to match the token to it's stored binding key.\",\r\n [ClientAuthErrorCodes.noNetworkConnectivity]:\r\n \"No network connectivity. Check your internet connection.\",\r\n [ClientAuthErrorCodes.userCanceled]: \"User cancelled the flow.\",\r\n [ClientAuthErrorCodes.missingTenantIdError]:\r\n \"A tenant id - not common, organizations, or consumers - must be specified when using the client_credentials flow.\",\r\n [ClientAuthErrorCodes.methodNotImplemented]:\r\n \"This method has not been implemented\",\r\n [ClientAuthErrorCodes.nestedAppAuthBridgeDisabled]:\r\n \"The nested app auth bridge is disabled\",\r\n};\r\n\r\n/**\r\n * String constants used by error codes and messages.\r\n * @deprecated Use ClientAuthErrorCodes instead\r\n */\r\nexport const ClientAuthErrorMessage = {\r\n clientInfoDecodingError: {\r\n code: ClientAuthErrorCodes.clientInfoDecodingError,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.clientInfoDecodingError\r\n ],\r\n },\r\n clientInfoEmptyError: {\r\n code: ClientAuthErrorCodes.clientInfoEmptyError,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.clientInfoEmptyError\r\n ],\r\n },\r\n tokenParsingError: {\r\n code: ClientAuthErrorCodes.tokenParsingError,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.tokenParsingError],\r\n },\r\n nullOrEmptyToken: {\r\n code: ClientAuthErrorCodes.nullOrEmptyToken,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.nullOrEmptyToken],\r\n },\r\n endpointResolutionError: {\r\n code: ClientAuthErrorCodes.endpointResolutionError,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.endpointResolutionError\r\n ],\r\n },\r\n networkError: {\r\n code: ClientAuthErrorCodes.networkError,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.networkError],\r\n },\r\n unableToGetOpenidConfigError: {\r\n code: ClientAuthErrorCodes.openIdConfigError,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.openIdConfigError],\r\n },\r\n hashNotDeserialized: {\r\n code: ClientAuthErrorCodes.hashNotDeserialized,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.hashNotDeserialized],\r\n },\r\n invalidStateError: {\r\n code: ClientAuthErrorCodes.invalidState,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.invalidState],\r\n },\r\n stateMismatchError: {\r\n code: ClientAuthErrorCodes.stateMismatch,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.stateMismatch],\r\n },\r\n stateNotFoundError: {\r\n code: ClientAuthErrorCodes.stateNotFound,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.stateNotFound],\r\n },\r\n nonceMismatchError: {\r\n code: ClientAuthErrorCodes.nonceMismatch,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.nonceMismatch],\r\n },\r\n authTimeNotFoundError: {\r\n code: ClientAuthErrorCodes.authTimeNotFound,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.authTimeNotFound],\r\n },\r\n maxAgeTranspired: {\r\n code: ClientAuthErrorCodes.maxAgeTranspired,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.maxAgeTranspired],\r\n },\r\n multipleMatchingTokens: {\r\n code: ClientAuthErrorCodes.multipleMatchingTokens,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.multipleMatchingTokens\r\n ],\r\n },\r\n multipleMatchingAccounts: {\r\n code: ClientAuthErrorCodes.multipleMatchingAccounts,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.multipleMatchingAccounts\r\n ],\r\n },\r\n multipleMatchingAppMetadata: {\r\n code: ClientAuthErrorCodes.multipleMatchingAppMetadata,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.multipleMatchingAppMetadata\r\n ],\r\n },\r\n tokenRequestCannotBeMade: {\r\n code: ClientAuthErrorCodes.requestCannotBeMade,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.requestCannotBeMade],\r\n },\r\n removeEmptyScopeError: {\r\n code: ClientAuthErrorCodes.cannotRemoveEmptyScope,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.cannotRemoveEmptyScope\r\n ],\r\n },\r\n appendScopeSetError: {\r\n code: ClientAuthErrorCodes.cannotAppendScopeSet,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.cannotAppendScopeSet\r\n ],\r\n },\r\n emptyInputScopeSetError: {\r\n code: ClientAuthErrorCodes.emptyInputScopeSet,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.emptyInputScopeSet],\r\n },\r\n DeviceCodePollingCancelled: {\r\n code: ClientAuthErrorCodes.deviceCodePollingCancelled,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.deviceCodePollingCancelled\r\n ],\r\n },\r\n DeviceCodeExpired: {\r\n code: ClientAuthErrorCodes.deviceCodeExpired,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.deviceCodeExpired],\r\n },\r\n DeviceCodeUnknownError: {\r\n code: ClientAuthErrorCodes.deviceCodeUnknownError,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.deviceCodeUnknownError\r\n ],\r\n },\r\n NoAccountInSilentRequest: {\r\n code: ClientAuthErrorCodes.noAccountInSilentRequest,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.noAccountInSilentRequest\r\n ],\r\n },\r\n invalidCacheRecord: {\r\n code: ClientAuthErrorCodes.invalidCacheRecord,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.invalidCacheRecord],\r\n },\r\n invalidCacheEnvironment: {\r\n code: ClientAuthErrorCodes.invalidCacheEnvironment,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.invalidCacheEnvironment\r\n ],\r\n },\r\n noAccountFound: {\r\n code: ClientAuthErrorCodes.noAccountFound,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.noAccountFound],\r\n },\r\n noCryptoObj: {\r\n code: ClientAuthErrorCodes.noCryptoObject,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.noCryptoObject],\r\n },\r\n unexpectedCredentialType: {\r\n code: ClientAuthErrorCodes.unexpectedCredentialType,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.unexpectedCredentialType\r\n ],\r\n },\r\n invalidAssertion: {\r\n code: ClientAuthErrorCodes.invalidAssertion,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.invalidAssertion],\r\n },\r\n invalidClientCredential: {\r\n code: ClientAuthErrorCodes.invalidClientCredential,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.invalidClientCredential\r\n ],\r\n },\r\n tokenRefreshRequired: {\r\n code: ClientAuthErrorCodes.tokenRefreshRequired,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.tokenRefreshRequired\r\n ],\r\n },\r\n userTimeoutReached: {\r\n code: ClientAuthErrorCodes.userTimeoutReached,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.userTimeoutReached],\r\n },\r\n tokenClaimsRequired: {\r\n code: ClientAuthErrorCodes.tokenClaimsCnfRequiredForSignedJwt,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.tokenClaimsCnfRequiredForSignedJwt\r\n ],\r\n },\r\n noAuthorizationCodeFromServer: {\r\n code: ClientAuthErrorCodes.authorizationCodeMissingFromServerResponse,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.authorizationCodeMissingFromServerResponse\r\n ],\r\n },\r\n bindingKeyNotRemovedError: {\r\n code: ClientAuthErrorCodes.bindingKeyNotRemoved,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.bindingKeyNotRemoved\r\n ],\r\n },\r\n logoutNotSupported: {\r\n code: ClientAuthErrorCodes.endSessionEndpointNotSupported,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.endSessionEndpointNotSupported\r\n ],\r\n },\r\n keyIdMissing: {\r\n code: ClientAuthErrorCodes.keyIdMissing,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.keyIdMissing],\r\n },\r\n noNetworkConnectivity: {\r\n code: ClientAuthErrorCodes.noNetworkConnectivity,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.noNetworkConnectivity\r\n ],\r\n },\r\n userCanceledError: {\r\n code: ClientAuthErrorCodes.userCanceled,\r\n desc: ClientAuthErrorMessages[ClientAuthErrorCodes.userCanceled],\r\n },\r\n missingTenantIdError: {\r\n code: ClientAuthErrorCodes.missingTenantIdError,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.missingTenantIdError\r\n ],\r\n },\r\n nestedAppAuthBridgeDisabled: {\r\n code: ClientAuthErrorCodes.nestedAppAuthBridgeDisabled,\r\n desc: ClientAuthErrorMessages[\r\n ClientAuthErrorCodes.nestedAppAuthBridgeDisabled\r\n ],\r\n },\r\n};\r\n\r\n/**\r\n * Error thrown when there is an error in the client code running on the browser.\r\n */\r\nexport class ClientAuthError extends AuthError {\r\n constructor(errorCode: string, additionalMessage?: string) {\r\n super(\r\n errorCode,\r\n additionalMessage\r\n ? `${ClientAuthErrorMessages[errorCode]}: ${additionalMessage}`\r\n : ClientAuthErrorMessages[errorCode]\r\n );\r\n this.name = \"ClientAuthError\";\r\n\r\n Object.setPrototypeOf(this, ClientAuthError.prototype);\r\n }\r\n}\r\n\r\nexport function createClientAuthError(\r\n errorCode: string,\r\n additionalMessage?: string\r\n): ClientAuthError {\r\n return new ClientAuthError(errorCode, additionalMessage);\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n} from \"../error/ClientAuthError.js\";\r\nimport type { BaseAuthRequest } from \"../request/BaseAuthRequest.js\";\r\nimport type { ShrOptions, SignedHttpRequest } from \"./SignedHttpRequest.js\";\r\n\r\n/**\r\n * The PkceCodes type describes the structure\r\n * of objects that contain PKCE code\r\n * challenge and verifier pairs\r\n */\r\nexport type PkceCodes = {\r\n verifier: string;\r\n challenge: string;\r\n};\r\n\r\nexport type SignedHttpRequestParameters = Pick<\r\n BaseAuthRequest,\r\n | \"resourceRequestMethod\"\r\n | \"resourceRequestUri\"\r\n | \"shrClaims\"\r\n | \"shrNonce\"\r\n | \"shrOptions\"\r\n> & {\r\n correlationId?: string;\r\n};\r\n\r\n/**\r\n * Interface for crypto functions used by library\r\n */\r\nexport interface ICrypto {\r\n /**\r\n * Creates a guid randomly.\r\n */\r\n createNewGuid(): string;\r\n /**\r\n * base64 Encode string\r\n * @param input\r\n */\r\n base64Encode(input: string): string;\r\n /**\r\n * base64 decode string\r\n * @param input\r\n */\r\n base64Decode(input: string): string;\r\n /**\r\n * base64 URL safe encoded string\r\n */\r\n base64UrlEncode(input: string): string;\r\n /**\r\n * Stringifies and base64Url encodes input public key\r\n * @param inputKid\r\n * @returns Base64Url encoded public key\r\n */\r\n encodeKid(inputKid: string): string;\r\n /**\r\n * Generates an JWK RSA S256 Thumbprint\r\n * @param request\r\n */\r\n getPublicKeyThumbprint(\r\n request: SignedHttpRequestParameters\r\n ): Promise;\r\n /**\r\n * Removes cryptographic keypair from key store matching the keyId passed in\r\n * @param kid\r\n */\r\n removeTokenBindingKey(kid: string): Promise;\r\n /**\r\n * Removes all cryptographic keys from IndexedDB storage\r\n */\r\n clearKeystore(): Promise;\r\n /**\r\n * Returns a signed proof-of-possession token with a given acces token that contains a cnf claim with the required kid.\r\n * @param accessToken\r\n */\r\n signJwt(\r\n payload: SignedHttpRequest,\r\n kid: string,\r\n shrOptions?: ShrOptions,\r\n correlationId?: string\r\n ): Promise;\r\n /**\r\n * Returns the SHA-256 hash of an input string\r\n * @param plainText\r\n */\r\n hashString(plainText: string): Promise;\r\n}\r\n\r\nexport const DEFAULT_CRYPTO_IMPLEMENTATION: ICrypto = {\r\n createNewGuid: (): string => {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n },\r\n base64Decode: (): string => {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n },\r\n base64Encode: (): string => {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n },\r\n base64UrlEncode: (): string => {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n },\r\n encodeKid: (): string => {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n },\r\n async getPublicKeyThumbprint(): Promise {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n },\r\n async removeTokenBindingKey(): Promise {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n },\r\n async clearKeystore(): Promise {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n },\r\n async signJwt(): Promise {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n },\r\n async hashString(): Promise {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n },\r\n};\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport type { LoggerOptions } from \"../config/ClientConfiguration.js\";\r\nimport { Constants } from \"../utils/Constants.js\";\r\n\r\n/**\r\n * Options for logger messages.\r\n */\r\nexport type LoggerMessageOptions = {\r\n logLevel: LogLevel;\r\n containsPii?: boolean;\r\n context?: string;\r\n correlationId?: string;\r\n};\r\n\r\n/**\r\n * Log message level.\r\n */\r\nexport enum LogLevel {\r\n Error,\r\n Warning,\r\n Info,\r\n Verbose,\r\n Trace,\r\n}\r\n\r\n/**\r\n * Callback to send the messages to.\r\n */\r\nexport interface ILoggerCallback {\r\n (level: LogLevel, message: string, containsPii: boolean): void;\r\n}\r\n\r\n/**\r\n * Class which facilitates logging of messages to a specific place.\r\n */\r\nexport class Logger {\r\n // Correlation ID for request, usually set by user.\r\n private correlationId: string;\r\n\r\n // Current log level, defaults to info.\r\n private level: LogLevel = LogLevel.Info;\r\n\r\n // Boolean describing whether PII logging is allowed.\r\n private piiLoggingEnabled: boolean;\r\n\r\n // Callback to send messages to.\r\n private localCallback: ILoggerCallback;\r\n\r\n // Package name implementing this logger\r\n private packageName: string;\r\n\r\n // Package version implementing this logger\r\n private packageVersion: string;\r\n\r\n constructor(\r\n loggerOptions: LoggerOptions,\r\n packageName?: string,\r\n packageVersion?: string\r\n ) {\r\n const defaultLoggerCallback = () => {\r\n return;\r\n };\r\n const setLoggerOptions =\r\n loggerOptions || Logger.createDefaultLoggerOptions();\r\n this.localCallback =\r\n setLoggerOptions.loggerCallback || defaultLoggerCallback;\r\n this.piiLoggingEnabled = setLoggerOptions.piiLoggingEnabled || false;\r\n this.level =\r\n typeof setLoggerOptions.logLevel === \"number\"\r\n ? setLoggerOptions.logLevel\r\n : LogLevel.Info;\r\n this.correlationId =\r\n setLoggerOptions.correlationId || Constants.EMPTY_STRING;\r\n this.packageName = packageName || Constants.EMPTY_STRING;\r\n this.packageVersion = packageVersion || Constants.EMPTY_STRING;\r\n }\r\n\r\n private static createDefaultLoggerOptions(): LoggerOptions {\r\n return {\r\n loggerCallback: () => {\r\n // allow users to not set loggerCallback\r\n },\r\n piiLoggingEnabled: false,\r\n logLevel: LogLevel.Info,\r\n };\r\n }\r\n\r\n /**\r\n * Create new Logger with existing configurations.\r\n */\r\n public clone(\r\n packageName: string,\r\n packageVersion: string,\r\n correlationId?: string\r\n ): Logger {\r\n return new Logger(\r\n {\r\n loggerCallback: this.localCallback,\r\n piiLoggingEnabled: this.piiLoggingEnabled,\r\n logLevel: this.level,\r\n correlationId: correlationId || this.correlationId,\r\n },\r\n packageName,\r\n packageVersion\r\n );\r\n }\r\n\r\n /**\r\n * Log message with required options.\r\n */\r\n private logMessage(\r\n logMessage: string,\r\n options: LoggerMessageOptions\r\n ): void {\r\n if (\r\n options.logLevel > this.level ||\r\n (!this.piiLoggingEnabled && options.containsPii)\r\n ) {\r\n return;\r\n }\r\n const timestamp = new Date().toUTCString();\r\n\r\n // Add correlationId to logs if set, correlationId provided on log messages take precedence\r\n const logHeader = `[${timestamp}] : [${\r\n options.correlationId || this.correlationId || \"\"\r\n }]`;\r\n\r\n const log = `${logHeader} : ${this.packageName}@${\r\n this.packageVersion\r\n } : ${LogLevel[options.logLevel]} - ${logMessage}`;\r\n // debug(`msal:${LogLevel[options.logLevel]}${options.containsPii ? \"-Pii\": Constants.EMPTY_STRING}${options.context ? `:${options.context}` : Constants.EMPTY_STRING}`)(logMessage);\r\n this.executeCallback(\r\n options.logLevel,\r\n log,\r\n options.containsPii || false\r\n );\r\n }\r\n\r\n /**\r\n * Execute callback with message.\r\n */\r\n executeCallback(\r\n level: LogLevel,\r\n message: string,\r\n containsPii: boolean\r\n ): void {\r\n if (this.localCallback) {\r\n this.localCallback(level, message, containsPii);\r\n }\r\n }\r\n\r\n /**\r\n * Logs error messages.\r\n */\r\n error(message: string, correlationId?: string): void {\r\n this.logMessage(message, {\r\n logLevel: LogLevel.Error,\r\n containsPii: false,\r\n correlationId: correlationId || Constants.EMPTY_STRING,\r\n });\r\n }\r\n\r\n /**\r\n * Logs error messages with PII.\r\n */\r\n errorPii(message: string, correlationId?: string): void {\r\n this.logMessage(message, {\r\n logLevel: LogLevel.Error,\r\n containsPii: true,\r\n correlationId: correlationId || Constants.EMPTY_STRING,\r\n });\r\n }\r\n\r\n /**\r\n * Logs warning messages.\r\n */\r\n warning(message: string, correlationId?: string): void {\r\n this.logMessage(message, {\r\n logLevel: LogLevel.Warning,\r\n containsPii: false,\r\n correlationId: correlationId || Constants.EMPTY_STRING,\r\n });\r\n }\r\n\r\n /**\r\n * Logs warning messages with PII.\r\n */\r\n warningPii(message: string, correlationId?: string): void {\r\n this.logMessage(message, {\r\n logLevel: LogLevel.Warning,\r\n containsPii: true,\r\n correlationId: correlationId || Constants.EMPTY_STRING,\r\n });\r\n }\r\n\r\n /**\r\n * Logs info messages.\r\n */\r\n info(message: string, correlationId?: string): void {\r\n this.logMessage(message, {\r\n logLevel: LogLevel.Info,\r\n containsPii: false,\r\n correlationId: correlationId || Constants.EMPTY_STRING,\r\n });\r\n }\r\n\r\n /**\r\n * Logs info messages with PII.\r\n */\r\n infoPii(message: string, correlationId?: string): void {\r\n this.logMessage(message, {\r\n logLevel: LogLevel.Info,\r\n containsPii: true,\r\n correlationId: correlationId || Constants.EMPTY_STRING,\r\n });\r\n }\r\n\r\n /**\r\n * Logs verbose messages.\r\n */\r\n verbose(message: string, correlationId?: string): void {\r\n this.logMessage(message, {\r\n logLevel: LogLevel.Verbose,\r\n containsPii: false,\r\n correlationId: correlationId || Constants.EMPTY_STRING,\r\n });\r\n }\r\n\r\n /**\r\n * Logs verbose messages with PII.\r\n */\r\n verbosePii(message: string, correlationId?: string): void {\r\n this.logMessage(message, {\r\n logLevel: LogLevel.Verbose,\r\n containsPii: true,\r\n correlationId: correlationId || Constants.EMPTY_STRING,\r\n });\r\n }\r\n\r\n /**\r\n * Logs trace messages.\r\n */\r\n trace(message: string, correlationId?: string): void {\r\n this.logMessage(message, {\r\n logLevel: LogLevel.Trace,\r\n containsPii: false,\r\n correlationId: correlationId || Constants.EMPTY_STRING,\r\n });\r\n }\r\n\r\n /**\r\n * Logs trace messages with PII.\r\n */\r\n tracePii(message: string, correlationId?: string): void {\r\n this.logMessage(message, {\r\n logLevel: LogLevel.Trace,\r\n containsPii: true,\r\n correlationId: correlationId || Constants.EMPTY_STRING,\r\n });\r\n }\r\n\r\n /**\r\n * Returns whether PII Logging is enabled or not.\r\n */\r\n isPiiLoggingEnabled(): boolean {\r\n return this.piiLoggingEnabled || false;\r\n }\r\n}\r\n", "/* eslint-disable header/header */\r\nexport const name = \"@azure/msal-common\";\r\nexport const version = \"15.12.0\";\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { ProtocolMode } from \"./ProtocolMode.js\";\r\nimport { OIDCOptions } from \"./OIDCOptions.js\";\r\nimport { AzureRegionConfiguration } from \"./AzureRegionConfiguration.js\";\r\nimport { CloudInstanceDiscoveryResponse } from \"./CloudInstanceDiscoveryResponse.js\";\r\n\r\nexport type AuthorityOptions = {\r\n protocolMode: ProtocolMode;\r\n OIDCOptions?: OIDCOptions | null;\r\n knownAuthorities: Array;\r\n cloudDiscoveryMetadata: string;\r\n authorityMetadata: string;\r\n skipAuthorityMetadataCache?: boolean;\r\n azureRegionConfiguration?: AzureRegionConfiguration;\r\n authority?: string;\r\n};\r\n\r\nexport type StaticAuthorityOptions = Partial<\r\n Pick\r\n> & {\r\n canonicalAuthority?: string;\r\n cloudDiscoveryMetadata?: CloudInstanceDiscoveryResponse;\r\n};\r\n\r\nexport const AzureCloudInstance = {\r\n // AzureCloudInstance is not specified.\r\n None: \"none\",\r\n\r\n // Microsoft Azure public cloud\r\n AzurePublic: \"https://login.microsoftonline.com\",\r\n\r\n // Microsoft PPE\r\n AzurePpe: \"https://login.windows-ppe.net\",\r\n\r\n // Microsoft Chinese national/regional cloud\r\n AzureChina: \"https://login.chinacloudapi.cn\",\r\n\r\n // Microsoft German national/regional cloud (\"Black Forest\")\r\n AzureGermany: \"https://login.microsoftonline.de\",\r\n\r\n // US Government cloud\r\n AzureUsGovernment: \"https://login.microsoftonline.us\",\r\n} as const;\r\nexport type AzureCloudInstance =\r\n (typeof AzureCloudInstance)[keyof typeof AzureCloudInstance];\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport const redirectUriEmpty = \"redirect_uri_empty\";\r\nexport const claimsRequestParsingError = \"claims_request_parsing_error\";\r\nexport const authorityUriInsecure = \"authority_uri_insecure\";\r\nexport const urlParseError = \"url_parse_error\";\r\nexport const urlEmptyError = \"empty_url_error\";\r\nexport const emptyInputScopesError = \"empty_input_scopes_error\";\r\nexport const invalidClaims = \"invalid_claims\";\r\nexport const tokenRequestEmpty = \"token_request_empty\";\r\nexport const logoutRequestEmpty = \"logout_request_empty\";\r\nexport const invalidCodeChallengeMethod = \"invalid_code_challenge_method\";\r\nexport const pkceParamsMissing = \"pkce_params_missing\";\r\nexport const invalidCloudDiscoveryMetadata = \"invalid_cloud_discovery_metadata\";\r\nexport const invalidAuthorityMetadata = \"invalid_authority_metadata\";\r\nexport const untrustedAuthority = \"untrusted_authority\";\r\nexport const missingSshJwk = \"missing_ssh_jwk\";\r\nexport const missingSshKid = \"missing_ssh_kid\";\r\nexport const missingNonceAuthenticationHeader =\r\n \"missing_nonce_authentication_header\";\r\nexport const invalidAuthenticationHeader = \"invalid_authentication_header\";\r\nexport const cannotSetOIDCOptions = \"cannot_set_OIDCOptions\";\r\nexport const cannotAllowPlatformBroker = \"cannot_allow_platform_broker\";\r\nexport const authorityMismatch = \"authority_mismatch\";\r\nexport const invalidRequestMethodForEAR = \"invalid_request_method_for_EAR\";\r\nexport const invalidAuthorizePostBodyParameters =\r\n \"invalid_authorize_post_body_parameters\";\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthError } from \"./AuthError.js\";\r\nimport * as ClientConfigurationErrorCodes from \"./ClientConfigurationErrorCodes.js\";\r\nexport { ClientConfigurationErrorCodes };\r\n\r\nexport const ClientConfigurationErrorMessages = {\r\n [ClientConfigurationErrorCodes.redirectUriEmpty]:\r\n \"A redirect URI is required for all calls, and none has been set.\",\r\n [ClientConfigurationErrorCodes.claimsRequestParsingError]:\r\n \"Could not parse the given claims request object.\",\r\n [ClientConfigurationErrorCodes.authorityUriInsecure]:\r\n \"Authority URIs must use https. Please see here for valid authority configuration options: https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-js-initializing-client-applications#configuration-options\",\r\n [ClientConfigurationErrorCodes.urlParseError]:\r\n \"URL could not be parsed into appropriate segments.\",\r\n [ClientConfigurationErrorCodes.urlEmptyError]: \"URL was empty or null.\",\r\n [ClientConfigurationErrorCodes.emptyInputScopesError]:\r\n \"Scopes cannot be passed as null, undefined or empty array because they are required to obtain an access token.\",\r\n [ClientConfigurationErrorCodes.invalidClaims]:\r\n \"Given claims parameter must be a stringified JSON object.\",\r\n [ClientConfigurationErrorCodes.tokenRequestEmpty]:\r\n \"Token request was empty and not found in cache.\",\r\n [ClientConfigurationErrorCodes.logoutRequestEmpty]:\r\n \"The logout request was null or undefined.\",\r\n [ClientConfigurationErrorCodes.invalidCodeChallengeMethod]:\r\n 'code_challenge_method passed is invalid. Valid values are \"plain\" and \"S256\".',\r\n [ClientConfigurationErrorCodes.pkceParamsMissing]:\r\n \"Both params: code_challenge and code_challenge_method are to be passed if to be sent in the request\",\r\n [ClientConfigurationErrorCodes.invalidCloudDiscoveryMetadata]:\r\n \"Invalid cloudDiscoveryMetadata provided. Must be a stringified JSON object containing tenant_discovery_endpoint and metadata fields\",\r\n [ClientConfigurationErrorCodes.invalidAuthorityMetadata]:\r\n \"Invalid authorityMetadata provided. Must by a stringified JSON object containing authorization_endpoint, token_endpoint, issuer fields.\",\r\n [ClientConfigurationErrorCodes.untrustedAuthority]:\r\n \"The provided authority is not a trusted authority. Please include this authority in the knownAuthorities config parameter.\",\r\n [ClientConfigurationErrorCodes.missingSshJwk]:\r\n \"Missing sshJwk in SSH certificate request. A stringified JSON Web Key is required when using the SSH authentication scheme.\",\r\n [ClientConfigurationErrorCodes.missingSshKid]:\r\n \"Missing sshKid in SSH certificate request. A string that uniquely identifies the public SSH key is required when using the SSH authentication scheme.\",\r\n [ClientConfigurationErrorCodes.missingNonceAuthenticationHeader]:\r\n \"Unable to find an authentication header containing server nonce. Either the Authentication-Info or WWW-Authenticate headers must be present in order to obtain a server nonce.\",\r\n [ClientConfigurationErrorCodes.invalidAuthenticationHeader]:\r\n \"Invalid authentication header provided\",\r\n [ClientConfigurationErrorCodes.cannotSetOIDCOptions]:\r\n \"Cannot set OIDCOptions parameter. Please change the protocol mode to OIDC or use a non-Microsoft authority.\",\r\n [ClientConfigurationErrorCodes.cannotAllowPlatformBroker]:\r\n \"Cannot set allowPlatformBroker parameter to true when not in AAD protocol mode.\",\r\n [ClientConfigurationErrorCodes.authorityMismatch]:\r\n \"Authority mismatch error. Authority provided in login request or PublicClientApplication config does not match the environment of the provided account. Please use a matching account or make an interactive request to login to this authority.\",\r\n [ClientConfigurationErrorCodes.invalidAuthorizePostBodyParameters]:\r\n \"Invalid authorize post body parameters provided. If you are using authorizePostBodyParameters, the request method must be POST. Please check the request method and parameters.\",\r\n [ClientConfigurationErrorCodes.invalidRequestMethodForEAR]:\r\n \"Invalid request method for EAR protocol mode. The request method cannot be GET when using EAR protocol mode. Please change the request method to POST.\",\r\n};\r\n\r\n/**\r\n * ClientConfigurationErrorMessage class containing string constants used by error codes and messages.\r\n * @deprecated Use ClientConfigurationErrorCodes instead\r\n */\r\nexport const ClientConfigurationErrorMessage = {\r\n redirectUriNotSet: {\r\n code: ClientConfigurationErrorCodes.redirectUriEmpty,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.redirectUriEmpty\r\n ],\r\n },\r\n claimsRequestParsingError: {\r\n code: ClientConfigurationErrorCodes.claimsRequestParsingError,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.claimsRequestParsingError\r\n ],\r\n },\r\n authorityUriInsecure: {\r\n code: ClientConfigurationErrorCodes.authorityUriInsecure,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.authorityUriInsecure\r\n ],\r\n },\r\n urlParseError: {\r\n code: ClientConfigurationErrorCodes.urlParseError,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.urlParseError\r\n ],\r\n },\r\n urlEmptyError: {\r\n code: ClientConfigurationErrorCodes.urlEmptyError,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.urlEmptyError\r\n ],\r\n },\r\n emptyScopesError: {\r\n code: ClientConfigurationErrorCodes.emptyInputScopesError,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.emptyInputScopesError\r\n ],\r\n },\r\n invalidClaimsRequest: {\r\n code: ClientConfigurationErrorCodes.invalidClaims,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.invalidClaims\r\n ],\r\n },\r\n tokenRequestEmptyError: {\r\n code: ClientConfigurationErrorCodes.tokenRequestEmpty,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.tokenRequestEmpty\r\n ],\r\n },\r\n logoutRequestEmptyError: {\r\n code: ClientConfigurationErrorCodes.logoutRequestEmpty,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.logoutRequestEmpty\r\n ],\r\n },\r\n invalidCodeChallengeMethod: {\r\n code: ClientConfigurationErrorCodes.invalidCodeChallengeMethod,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.invalidCodeChallengeMethod\r\n ],\r\n },\r\n invalidCodeChallengeParams: {\r\n code: ClientConfigurationErrorCodes.pkceParamsMissing,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.pkceParamsMissing\r\n ],\r\n },\r\n invalidCloudDiscoveryMetadata: {\r\n code: ClientConfigurationErrorCodes.invalidCloudDiscoveryMetadata,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.invalidCloudDiscoveryMetadata\r\n ],\r\n },\r\n invalidAuthorityMetadata: {\r\n code: ClientConfigurationErrorCodes.invalidAuthorityMetadata,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.invalidAuthorityMetadata\r\n ],\r\n },\r\n untrustedAuthority: {\r\n code: ClientConfigurationErrorCodes.untrustedAuthority,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.untrustedAuthority\r\n ],\r\n },\r\n missingSshJwk: {\r\n code: ClientConfigurationErrorCodes.missingSshJwk,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.missingSshJwk\r\n ],\r\n },\r\n missingSshKid: {\r\n code: ClientConfigurationErrorCodes.missingSshKid,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.missingSshKid\r\n ],\r\n },\r\n missingNonceAuthenticationHeader: {\r\n code: ClientConfigurationErrorCodes.missingNonceAuthenticationHeader,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.missingNonceAuthenticationHeader\r\n ],\r\n },\r\n invalidAuthenticationHeader: {\r\n code: ClientConfigurationErrorCodes.invalidAuthenticationHeader,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.invalidAuthenticationHeader\r\n ],\r\n },\r\n cannotSetOIDCOptions: {\r\n code: ClientConfigurationErrorCodes.cannotSetOIDCOptions,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.cannotSetOIDCOptions\r\n ],\r\n },\r\n cannotAllowPlatformBroker: {\r\n code: ClientConfigurationErrorCodes.cannotAllowPlatformBroker,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.cannotAllowPlatformBroker\r\n ],\r\n },\r\n authorityMismatch: {\r\n code: ClientConfigurationErrorCodes.authorityMismatch,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.authorityMismatch\r\n ],\r\n },\r\n invalidAuthorizePostBodyParameters: {\r\n code: ClientConfigurationErrorCodes.invalidAuthorizePostBodyParameters,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.invalidAuthorizePostBodyParameters\r\n ],\r\n },\r\n invalidRequestMethodForEAR: {\r\n code: ClientConfigurationErrorCodes.invalidRequestMethodForEAR,\r\n desc: ClientConfigurationErrorMessages[\r\n ClientConfigurationErrorCodes.invalidRequestMethodForEAR\r\n ],\r\n },\r\n};\r\n\r\n/**\r\n * Error thrown when there is an error in configuration of the MSAL.js library.\r\n */\r\nexport class ClientConfigurationError extends AuthError {\r\n constructor(errorCode: string) {\r\n super(errorCode, ClientConfigurationErrorMessages[errorCode]);\r\n this.name = \"ClientConfigurationError\";\r\n Object.setPrototypeOf(this, ClientConfigurationError.prototype);\r\n }\r\n}\r\n\r\nexport function createClientConfigurationError(\r\n errorCode: string\r\n): ClientConfigurationError {\r\n return new ClientConfigurationError(errorCode);\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n/**\r\n * @hidden\r\n */\r\nexport class StringUtils {\r\n /**\r\n * Check if stringified object is empty\r\n * @param strObj\r\n */\r\n static isEmptyObj(strObj?: string): boolean {\r\n if (strObj) {\r\n try {\r\n const obj = JSON.parse(strObj);\r\n return Object.keys(obj).length === 0;\r\n } catch (e) {}\r\n }\r\n return true;\r\n }\r\n\r\n static startsWith(str: string, search: string): boolean {\r\n return str.indexOf(search) === 0;\r\n }\r\n\r\n static endsWith(str: string, search: string): boolean {\r\n return (\r\n str.length >= search.length &&\r\n str.lastIndexOf(search) === str.length - search.length\r\n );\r\n }\r\n\r\n /**\r\n * Parses string into an object.\r\n *\r\n * @param query\r\n */\r\n static queryStringToObject(query: string): T {\r\n const obj: {} = {};\r\n const params = query.split(\"&\");\r\n const decode = (s: string) => decodeURIComponent(s.replace(/\\+/g, \" \"));\r\n params.forEach((pair) => {\r\n if (pair.trim()) {\r\n const [key, value] = pair.split(/=(.+)/g, 2); // Split on the first occurence of the '=' character\r\n if (key && value) {\r\n obj[decode(key)] = decode(value);\r\n }\r\n }\r\n });\r\n return obj as T;\r\n }\r\n\r\n /**\r\n * Trims entries in an array.\r\n *\r\n * @param arr\r\n */\r\n static trimArrayEntries(arr: Array): Array {\r\n return arr.map((entry) => entry.trim());\r\n }\r\n\r\n /**\r\n * Removes empty strings from array\r\n * @param arr\r\n */\r\n static removeEmptyStringsFromArray(arr: Array): Array {\r\n return arr.filter((entry) => {\r\n return !!entry;\r\n });\r\n }\r\n\r\n /**\r\n * Attempts to parse a string into JSON\r\n * @param str\r\n */\r\n static jsonParseHelper(str: string): T | null {\r\n try {\r\n return JSON.parse(str) as T;\r\n } catch (e) {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Tests if a given string matches a given pattern, with support for wildcards and queries.\r\n * @param pattern Wildcard pattern to string match. Supports \"*\" for wildcards and \"?\" for queries\r\n * @param input String to match against\r\n */\r\n static matchPattern(pattern: string, input: string): boolean {\r\n /**\r\n * Wildcard support: https://stackoverflow.com/a/3117248/4888559\r\n * Queries: replaces \"?\" in string with escaped \"\\?\" for regex test\r\n */\r\n // eslint-disable-next-line security/detect-non-literal-regexp\r\n const regex: RegExp = new RegExp(\r\n pattern\r\n .replace(/\\\\/g, \"\\\\\\\\\")\r\n .replace(/\\*/g, \"[^ ]*\")\r\n .replace(/\\?/g, \"\\\\?\")\r\n );\r\n\r\n return regex.test(input);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n createClientConfigurationError,\r\n ClientConfigurationErrorCodes,\r\n} from \"../error/ClientConfigurationError.js\";\r\nimport { StringUtils } from \"../utils/StringUtils.js\";\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n} from \"../error/ClientAuthError.js\";\r\nimport {\r\n Constants,\r\n OIDC_SCOPES,\r\n OIDC_DEFAULT_SCOPES,\r\n} from \"../utils/Constants.js\";\r\n\r\n/**\r\n * The ScopeSet class creates a set of scopes. Scopes are case-insensitive, unique values, so the Set object in JS makes\r\n * the most sense to implement for this class. All scopes are trimmed and converted to lower case strings in intersection and union functions\r\n * to ensure uniqueness of strings.\r\n */\r\nexport class ScopeSet {\r\n // Scopes as a Set of strings\r\n private scopes: Set;\r\n\r\n constructor(inputScopes: Array) {\r\n // Filter empty string and null/undefined array items\r\n const scopeArr = inputScopes\r\n ? StringUtils.trimArrayEntries([...inputScopes])\r\n : [];\r\n const filteredInput = scopeArr\r\n ? StringUtils.removeEmptyStringsFromArray(scopeArr)\r\n : [];\r\n\r\n // Check if scopes array has at least one member\r\n if (!filteredInput || !filteredInput.length) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.emptyInputScopesError\r\n );\r\n }\r\n\r\n this.scopes = new Set(); // Iterator in constructor not supported by IE11\r\n filteredInput.forEach((scope) => this.scopes.add(scope));\r\n }\r\n\r\n /**\r\n * Factory method to create ScopeSet from space-delimited string\r\n * @param inputScopeString\r\n * @param appClientId\r\n * @param scopesRequired\r\n */\r\n static fromString(inputScopeString: string): ScopeSet {\r\n const scopeString = inputScopeString || Constants.EMPTY_STRING;\r\n const inputScopes: Array = scopeString.split(\" \");\r\n return new ScopeSet(inputScopes);\r\n }\r\n\r\n /**\r\n * Creates the set of scopes to search for in cache lookups\r\n * @param inputScopeString\r\n * @returns\r\n */\r\n static createSearchScopes(inputScopeString: Array): ScopeSet {\r\n // Handle empty scopes by using default OIDC scopes for cache lookup\r\n const scopesToUse =\r\n inputScopeString && inputScopeString.length > 0\r\n ? inputScopeString\r\n : [...OIDC_DEFAULT_SCOPES];\r\n\r\n const scopeSet = new ScopeSet(scopesToUse);\r\n if (!scopeSet.containsOnlyOIDCScopes()) {\r\n scopeSet.removeOIDCScopes();\r\n } else {\r\n scopeSet.removeScope(Constants.OFFLINE_ACCESS_SCOPE);\r\n }\r\n\r\n return scopeSet;\r\n }\r\n\r\n /**\r\n * Check if a given scope is present in this set of scopes.\r\n * @param scope\r\n */\r\n containsScope(scope: string): boolean {\r\n const lowerCaseScopes = this.printScopesLowerCase().split(\" \");\r\n const lowerCaseScopesSet = new ScopeSet(lowerCaseScopes);\r\n // compare lowercase scopes\r\n return scope\r\n ? lowerCaseScopesSet.scopes.has(scope.toLowerCase())\r\n : false;\r\n }\r\n\r\n /**\r\n * Check if a set of scopes is present in this set of scopes.\r\n * @param scopeSet\r\n */\r\n containsScopeSet(scopeSet: ScopeSet): boolean {\r\n if (!scopeSet || scopeSet.scopes.size <= 0) {\r\n return false;\r\n }\r\n\r\n return (\r\n this.scopes.size >= scopeSet.scopes.size &&\r\n scopeSet.asArray().every((scope) => this.containsScope(scope))\r\n );\r\n }\r\n\r\n /**\r\n * Check if set of scopes contains only the defaults\r\n */\r\n containsOnlyOIDCScopes(): boolean {\r\n let defaultScopeCount = 0;\r\n OIDC_SCOPES.forEach((defaultScope: string) => {\r\n if (this.containsScope(defaultScope)) {\r\n defaultScopeCount += 1;\r\n }\r\n });\r\n\r\n return this.scopes.size === defaultScopeCount;\r\n }\r\n\r\n /**\r\n * Appends single scope if passed\r\n * @param newScope\r\n */\r\n appendScope(newScope: string): void {\r\n if (newScope) {\r\n this.scopes.add(newScope.trim());\r\n }\r\n }\r\n\r\n /**\r\n * Appends multiple scopes if passed\r\n * @param newScopes\r\n */\r\n appendScopes(newScopes: Array): void {\r\n try {\r\n newScopes.forEach((newScope) => this.appendScope(newScope));\r\n } catch (e) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.cannotAppendScopeSet\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Removes element from set of scopes.\r\n * @param scope\r\n */\r\n removeScope(scope: string): void {\r\n if (!scope) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.cannotRemoveEmptyScope\r\n );\r\n }\r\n this.scopes.delete(scope.trim());\r\n }\r\n\r\n /**\r\n * Removes default scopes from set of scopes\r\n * Primarily used to prevent cache misses if the default scopes are not returned from the server\r\n */\r\n removeOIDCScopes(): void {\r\n OIDC_SCOPES.forEach((defaultScope: string) => {\r\n this.scopes.delete(defaultScope);\r\n });\r\n }\r\n\r\n /**\r\n * Combines an array of scopes with the current set of scopes.\r\n * @param otherScopes\r\n */\r\n unionScopeSets(otherScopes: ScopeSet): Set {\r\n if (!otherScopes) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.emptyInputScopeSet\r\n );\r\n }\r\n const unionScopes = new Set(); // Iterator in constructor not supported in IE11\r\n otherScopes.scopes.forEach((scope) =>\r\n unionScopes.add(scope.toLowerCase())\r\n );\r\n this.scopes.forEach((scope) => unionScopes.add(scope.toLowerCase()));\r\n return unionScopes;\r\n }\r\n\r\n /**\r\n * Check if scopes intersect between this set and another.\r\n * @param otherScopes\r\n */\r\n intersectingScopeSets(otherScopes: ScopeSet): boolean {\r\n if (!otherScopes) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.emptyInputScopeSet\r\n );\r\n }\r\n\r\n // Do not allow OIDC scopes to be the only intersecting scopes\r\n if (!otherScopes.containsOnlyOIDCScopes()) {\r\n otherScopes.removeOIDCScopes();\r\n }\r\n const unionScopes = this.unionScopeSets(otherScopes);\r\n const sizeOtherScopes = otherScopes.getScopeCount();\r\n const sizeThisScopes = this.getScopeCount();\r\n const sizeUnionScopes = unionScopes.size;\r\n return sizeUnionScopes < sizeThisScopes + sizeOtherScopes;\r\n }\r\n\r\n /**\r\n * Returns size of set of scopes.\r\n */\r\n getScopeCount(): number {\r\n return this.scopes.size;\r\n }\r\n\r\n /**\r\n * Returns the scopes as an array of string values\r\n */\r\n asArray(): Array {\r\n const array: Array = [];\r\n this.scopes.forEach((val) => array.push(val));\r\n return array;\r\n }\r\n\r\n /**\r\n * Prints scopes into a space-delimited string\r\n */\r\n printScopes(): string {\r\n if (this.scopes) {\r\n const scopeArr = this.asArray();\r\n return scopeArr.join(\" \");\r\n }\r\n return Constants.EMPTY_STRING;\r\n }\r\n\r\n /**\r\n * Prints scopes into a space-delimited lower-case string (used for caching)\r\n */\r\n printScopesLowerCase(): string {\r\n return this.printScopes().toLowerCase();\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { TokenClaims } from \"./TokenClaims.js\";\r\n/**\r\n * Account object with the following signature:\r\n * - homeAccountId - Home account identifier for this account object\r\n * - environment - Entity which issued the token represented by the domain of the issuer (e.g. login.microsoftonline.com)\r\n * - tenantId - Full tenant or organizational id that this account belongs to\r\n * - username - preferred_username claim of the id_token that represents this account\r\n * - localAccountId - Local, tenant-specific account identifer for this account object, usually used in legacy cases\r\n * - name - Full name for the account, including given name and family name\r\n * - idToken - raw ID token\r\n * - idTokenClaims - Object contains claims from ID token\r\n * - nativeAccountId - The user's native account ID\r\n * - tenantProfiles - Map of tenant profile objects for each tenant that the account has authenticated with in the browser\r\n */\r\nexport type AccountInfo = {\r\n homeAccountId: string;\r\n environment: string;\r\n tenantId: string;\r\n username: string;\r\n localAccountId: string;\r\n loginHint?: string;\r\n name?: string;\r\n idToken?: string;\r\n idTokenClaims?: TokenClaims & {\r\n [key: string]:\r\n | string\r\n | number\r\n | string[]\r\n | object\r\n | undefined\r\n | unknown;\r\n };\r\n nativeAccountId?: string;\r\n authorityType?: string;\r\n tenantProfiles?: Map;\r\n};\r\n\r\n/**\r\n * Account details that vary across tenants for the same user\r\n */\r\nexport type TenantProfile = Pick<\r\n AccountInfo,\r\n \"tenantId\" | \"localAccountId\" | \"name\" | \"username\" | \"loginHint\"\r\n> & {\r\n /**\r\n * - isHomeTenant - True if this is the home tenant profile of the account, false if it's a guest tenant profile\r\n */\r\n isHomeTenant?: boolean;\r\n};\r\n\r\nexport type ActiveAccountFilters = {\r\n homeAccountId: string;\r\n localAccountId: string;\r\n tenantId?: string;\r\n lastUpdatedAt?: string;\r\n};\r\n\r\n/**\r\n * Returns true if tenantId matches the utid portion of homeAccountId\r\n * @param tenantId\r\n * @param homeAccountId\r\n * @returns\r\n */\r\nexport function tenantIdMatchesHomeTenant(\r\n tenantId?: string,\r\n homeAccountId?: string\r\n): boolean {\r\n return (\r\n !!tenantId &&\r\n !!homeAccountId &&\r\n tenantId === homeAccountId.split(\".\")[1]\r\n );\r\n}\r\n\r\n/**\r\n * Build tenant profile\r\n * @param homeAccountId - Home account identifier for this account object\r\n * @param localAccountId - Local account identifer for this account object\r\n * @param tenantId - Full tenant or organizational id that this account belongs to\r\n * @param idTokenClaims - Claims from the ID token\r\n * @returns\r\n */\r\nexport function buildTenantProfile(\r\n homeAccountId: string,\r\n localAccountId: string,\r\n tenantId: string,\r\n idTokenClaims?: TokenClaims\r\n): TenantProfile {\r\n if (idTokenClaims) {\r\n const {\r\n oid,\r\n sub,\r\n tid,\r\n name,\r\n tfp,\r\n acr,\r\n preferred_username,\r\n upn,\r\n login_hint,\r\n } = idTokenClaims;\r\n\r\n /**\r\n * Since there is no way to determine if the authority is AAD or B2C, we exhaust all the possible claims that can serve as tenant ID with the following precedence:\r\n * tid - TenantID claim that identifies the tenant that issued the token in AAD. Expected in all AAD ID tokens, not present in B2C ID Tokens.\r\n * tfp - Trust Framework Policy claim that identifies the policy that was used to authenticate the user. Functions as tenant for B2C scenarios.\r\n * acr - Authentication Context Class Reference claim used only with older B2C policies. Fallback in case tfp is not present, but likely won't be present anyway.\r\n */\r\n const tenantId = tid || tfp || acr || \"\";\r\n\r\n return {\r\n tenantId: tenantId,\r\n localAccountId: oid || sub || \"\",\r\n name: name,\r\n username: preferred_username || upn || \"\",\r\n loginHint: login_hint,\r\n isHomeTenant: tenantIdMatchesHomeTenant(tenantId, homeAccountId),\r\n };\r\n } else {\r\n return {\r\n tenantId,\r\n localAccountId,\r\n username: \"\",\r\n isHomeTenant: tenantIdMatchesHomeTenant(tenantId, homeAccountId),\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Replaces account info that varies by tenant profile sourced from the ID token claims passed in with the tenant-specific account info\r\n * @param baseAccountInfo\r\n * @param idTokenClaims\r\n * @returns\r\n */\r\nexport function updateAccountTenantProfileData(\r\n baseAccountInfo: AccountInfo,\r\n tenantProfile?: TenantProfile,\r\n idTokenClaims?: TokenClaims,\r\n idTokenSecret?: string\r\n): AccountInfo {\r\n let updatedAccountInfo = baseAccountInfo;\r\n // Tenant Profile overrides passed in account info\r\n if (tenantProfile) {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const { isHomeTenant, ...tenantProfileOverride } = tenantProfile;\r\n updatedAccountInfo = { ...baseAccountInfo, ...tenantProfileOverride };\r\n }\r\n\r\n // ID token claims override passed in account info and tenant profile\r\n if (idTokenClaims) {\r\n // Ignore isHomeTenant, loginHint, and sid which are part of tenant profile but not base account info\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n const { isHomeTenant, ...claimsSourcedTenantProfile } =\r\n buildTenantProfile(\r\n baseAccountInfo.homeAccountId,\r\n baseAccountInfo.localAccountId,\r\n baseAccountInfo.tenantId,\r\n idTokenClaims\r\n );\r\n\r\n updatedAccountInfo = {\r\n ...updatedAccountInfo,\r\n ...claimsSourcedTenantProfile,\r\n idTokenClaims: idTokenClaims,\r\n idToken: idTokenSecret,\r\n };\r\n\r\n return updatedAccountInfo;\r\n }\r\n\r\n return updatedAccountInfo;\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { TokenClaims } from \"./TokenClaims.js\";\r\nimport {\r\n createClientAuthError,\r\n ClientAuthErrorCodes,\r\n} from \"../error/ClientAuthError.js\";\r\n\r\n/**\r\n * Extract token by decoding the rawToken\r\n *\r\n * @param encodedToken\r\n */\r\nexport function extractTokenClaims(\r\n encodedToken: string,\r\n base64Decode: (input: string) => string\r\n): TokenClaims {\r\n const jswPayload = getJWSPayload(encodedToken);\r\n\r\n // token will be decoded to get the username\r\n try {\r\n // base64Decode() should throw an error if there is an issue\r\n const base64Decoded = base64Decode(jswPayload);\r\n return JSON.parse(base64Decoded) as TokenClaims;\r\n } catch (err) {\r\n throw createClientAuthError(ClientAuthErrorCodes.tokenParsingError);\r\n }\r\n}\r\n\r\n/**\r\n * decode a JWT\r\n *\r\n * @param authToken\r\n */\r\nexport function getJWSPayload(authToken: string): string {\r\n if (!authToken) {\r\n throw createClientAuthError(ClientAuthErrorCodes.nullOrEmptyToken);\r\n }\r\n const tokenPartsRegex = /^([^\\.\\s]*)\\.([^\\.\\s]+)\\.([^\\.\\s]*)$/;\r\n const matches = tokenPartsRegex.exec(authToken);\r\n if (!matches || matches.length < 4) {\r\n throw createClientAuthError(ClientAuthErrorCodes.tokenParsingError);\r\n }\r\n /**\r\n * const crackedToken = {\r\n * header: matches[1],\r\n * JWSPayload: matches[2],\r\n * JWSSig: matches[3],\r\n * };\r\n */\r\n\r\n return matches[2];\r\n}\r\n\r\n/**\r\n * Determine if the token's max_age has transpired\r\n */\r\nexport function checkMaxAge(authTime: number, maxAge: number): void {\r\n /*\r\n * per https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest\r\n * To force an immediate re-authentication: If an app requires that a user re-authenticate prior to access,\r\n * provide a value of 0 for the max_age parameter and the AS will force a fresh login.\r\n */\r\n const fiveMinuteSkew = 300000; // five minutes in milliseconds\r\n if (maxAge === 0 || Date.now() - fiveMinuteSkew > authTime + maxAge) {\r\n throw createClientAuthError(ClientAuthErrorCodes.maxAgeTranspired);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthorizeResponse } from \"../response/AuthorizeResponse.js\";\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n} from \"../error/ClientAuthError.js\";\r\nimport { StringDict } from \"./MsalTypes.js\";\r\nimport { StringUtils } from \"./StringUtils.js\";\r\n\r\n/**\r\n * Canonicalizes a URL by making it lowercase and ensuring it ends with /\r\n * Inlined version of UrlString.canonicalizeUri to avoid circular dependency\r\n * @param url - URL to canonicalize\r\n * @returns Canonicalized URL\r\n */\r\nfunction canonicalizeUrl(url: string): string {\r\n if (!url) {\r\n return url;\r\n }\r\n\r\n let lowerCaseUrl = url.toLowerCase();\r\n\r\n if (StringUtils.endsWith(lowerCaseUrl, \"?\")) {\r\n lowerCaseUrl = lowerCaseUrl.slice(0, -1);\r\n } else if (StringUtils.endsWith(lowerCaseUrl, \"?/\")) {\r\n lowerCaseUrl = lowerCaseUrl.slice(0, -2);\r\n }\r\n\r\n if (!StringUtils.endsWith(lowerCaseUrl, \"/\")) {\r\n lowerCaseUrl += \"/\";\r\n }\r\n\r\n return lowerCaseUrl;\r\n}\r\n\r\n/**\r\n * Parses hash string from given string. Returns empty string if no hash symbol is found.\r\n * @param hashString\r\n */\r\nexport function stripLeadingHashOrQuery(responseString: string): string {\r\n if (responseString.startsWith(\"#/\")) {\r\n return responseString.substring(2);\r\n } else if (\r\n responseString.startsWith(\"#\") ||\r\n responseString.startsWith(\"?\")\r\n ) {\r\n return responseString.substring(1);\r\n }\r\n\r\n return responseString;\r\n}\r\n\r\n/**\r\n * Returns URL hash as server auth code response object.\r\n */\r\nexport function getDeserializedResponse(\r\n responseString: string\r\n): AuthorizeResponse | null {\r\n // Check if given hash is empty\r\n if (!responseString || responseString.indexOf(\"=\") < 0) {\r\n return null;\r\n }\r\n try {\r\n // Strip the # or ? symbol if present\r\n const normalizedResponse = stripLeadingHashOrQuery(responseString);\r\n // If # symbol was not present, above will return empty string, so give original hash value\r\n const deserializedHash: AuthorizeResponse = Object.fromEntries(\r\n new URLSearchParams(normalizedResponse)\r\n );\r\n\r\n // Check for known response properties\r\n if (\r\n deserializedHash.code ||\r\n deserializedHash.ear_jwe ||\r\n deserializedHash.error ||\r\n deserializedHash.error_description ||\r\n deserializedHash.state\r\n ) {\r\n return deserializedHash;\r\n }\r\n } catch (e) {\r\n throw createClientAuthError(ClientAuthErrorCodes.hashNotDeserialized);\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Utility to create a URL from the params map\r\n */\r\nexport function mapToQueryString(\r\n parameters: Map,\r\n encodeExtraParams: boolean = true,\r\n extraQueryParameters?: StringDict\r\n): string {\r\n const queryParameterArray: Array = new Array();\r\n\r\n parameters.forEach((value, key) => {\r\n if (\r\n !encodeExtraParams &&\r\n extraQueryParameters &&\r\n key in extraQueryParameters\r\n ) {\r\n queryParameterArray.push(`${key}=${value}`);\r\n } else {\r\n queryParameterArray.push(`${key}=${encodeURIComponent(value)}`);\r\n }\r\n });\r\n\r\n return queryParameterArray.join(\"&\");\r\n}\r\n\r\n/**\r\n * Normalizes URLs for comparison by removing hash, canonicalizing,\r\n * and ensuring consistent URL encoding in query parameters.\r\n * This fixes redirect loops when URLs contain encoded characters like apostrophes (%27).\r\n * @param url - URL to normalize\r\n * @returns Normalized URL string for comparison\r\n */\r\nexport function normalizeUrlForComparison(url: string): string {\r\n if (!url) {\r\n return url;\r\n }\r\n\r\n // Remove hash first\r\n const urlWithoutHash = url.split(\"#\")[0];\r\n\r\n try {\r\n // Parse the URL to handle encoding consistently\r\n const urlObj = new URL(urlWithoutHash);\r\n\r\n /*\r\n * Reconstruct the URL with properly decoded query parameters\r\n * This ensures that %27 and ' are treated as equivalent\r\n */\r\n const normalizedUrl = urlObj.origin + urlObj.pathname + urlObj.search;\r\n\r\n // Apply canonicalization logic inline to avoid circular dependency\r\n return canonicalizeUrl(normalizedUrl);\r\n } catch (e) {\r\n // Fallback to original logic if URL parsing fails\r\n return canonicalizeUrl(urlWithoutHash);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n createClientConfigurationError,\r\n ClientConfigurationErrorCodes,\r\n} from \"../error/ClientConfigurationError.js\";\r\nimport { StringUtils } from \"../utils/StringUtils.js\";\r\nimport { IUri } from \"./IUri.js\";\r\nimport { AADAuthorityConstants, Constants } from \"../utils/Constants.js\";\r\nimport * as UrlUtils from \"../utils/UrlUtils.js\";\r\n\r\n/**\r\n * Url object class which can perform various transformations on url strings.\r\n */\r\nexport class UrlString {\r\n // internal url string field\r\n private _urlString: string;\r\n public get urlString(): string {\r\n return this._urlString;\r\n }\r\n\r\n constructor(url: string) {\r\n this._urlString = url;\r\n if (!this._urlString) {\r\n // Throws error if url is empty\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.urlEmptyError\r\n );\r\n }\r\n\r\n if (!url.includes(\"#\")) {\r\n this._urlString = UrlString.canonicalizeUri(url);\r\n }\r\n }\r\n\r\n /**\r\n * Ensure urls are lower case and end with a / character.\r\n * @param url\r\n */\r\n static canonicalizeUri(url: string): string {\r\n if (url) {\r\n let lowerCaseUrl = url.toLowerCase();\r\n\r\n if (StringUtils.endsWith(lowerCaseUrl, \"?\")) {\r\n lowerCaseUrl = lowerCaseUrl.slice(0, -1);\r\n } else if (StringUtils.endsWith(lowerCaseUrl, \"?/\")) {\r\n lowerCaseUrl = lowerCaseUrl.slice(0, -2);\r\n }\r\n\r\n if (!StringUtils.endsWith(lowerCaseUrl, \"/\")) {\r\n lowerCaseUrl += \"/\";\r\n }\r\n\r\n return lowerCaseUrl;\r\n }\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Throws if urlString passed is not a valid authority URI string.\r\n */\r\n validateAsUri(): void {\r\n // Attempts to parse url for uri components\r\n let components;\r\n try {\r\n components = this.getUrlComponents();\r\n } catch (e) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.urlParseError\r\n );\r\n }\r\n\r\n // Throw error if URI or path segments are not parseable.\r\n if (!components.HostNameAndPort || !components.PathSegments) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.urlParseError\r\n );\r\n }\r\n\r\n // Throw error if uri is insecure.\r\n if (\r\n !components.Protocol ||\r\n components.Protocol.toLowerCase() !== \"https:\"\r\n ) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.authorityUriInsecure\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Given a url and a query string return the url with provided query string appended\r\n * @param url\r\n * @param queryString\r\n */\r\n static appendQueryString(url: string, queryString: string): string {\r\n if (!queryString) {\r\n return url;\r\n }\r\n\r\n return url.indexOf(\"?\") < 0\r\n ? `${url}?${queryString}`\r\n : `${url}&${queryString}`;\r\n }\r\n\r\n /**\r\n * Returns a url with the hash removed\r\n * @param url\r\n */\r\n static removeHashFromUrl(url: string): string {\r\n return UrlString.canonicalizeUri(url.split(\"#\")[0]);\r\n }\r\n\r\n /**\r\n * Given a url like https://a:b/common/d?e=f#g, and a tenantId, returns https://a:b/tenantId/d\r\n * @param href The url\r\n * @param tenantId The tenant id to replace\r\n */\r\n replaceTenantPath(tenantId: string): UrlString {\r\n const urlObject = this.getUrlComponents();\r\n const pathArray = urlObject.PathSegments;\r\n if (\r\n tenantId &&\r\n pathArray.length !== 0 &&\r\n (pathArray[0] === AADAuthorityConstants.COMMON ||\r\n pathArray[0] === AADAuthorityConstants.ORGANIZATIONS)\r\n ) {\r\n pathArray[0] = tenantId;\r\n }\r\n return UrlString.constructAuthorityUriFromObject(urlObject);\r\n }\r\n\r\n /**\r\n * Parses out the components from a url string.\r\n * @returns An object with the various components. Please cache this value insted of calling this multiple times on the same url.\r\n */\r\n getUrlComponents(): IUri {\r\n // https://gist.github.com/curtisz/11139b2cfcaef4a261e0\r\n const regEx = RegExp(\r\n \"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\\\?([^#]*))?(#(.*))?\"\r\n );\r\n\r\n // If url string does not match regEx, we throw an error\r\n const match = this.urlString.match(regEx);\r\n if (!match) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.urlParseError\r\n );\r\n }\r\n\r\n // Url component object\r\n const urlComponents = {\r\n Protocol: match[1],\r\n HostNameAndPort: match[4],\r\n AbsolutePath: match[5],\r\n QueryString: match[7],\r\n } as IUri;\r\n\r\n let pathSegments = urlComponents.AbsolutePath.split(\"/\");\r\n pathSegments = pathSegments.filter((val) => val && val.length > 0); // remove empty elements\r\n urlComponents.PathSegments = pathSegments;\r\n\r\n if (\r\n urlComponents.QueryString &&\r\n urlComponents.QueryString.endsWith(\"/\")\r\n ) {\r\n urlComponents.QueryString = urlComponents.QueryString.substring(\r\n 0,\r\n urlComponents.QueryString.length - 1\r\n );\r\n }\r\n return urlComponents;\r\n }\r\n\r\n static getDomainFromUrl(url: string): string {\r\n const regEx = RegExp(\"^([^:/?#]+://)?([^/?#]*)\");\r\n\r\n const match = url.match(regEx);\r\n\r\n if (!match) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.urlParseError\r\n );\r\n }\r\n\r\n return match[2];\r\n }\r\n\r\n static getAbsoluteUrl(relativeUrl: string, baseUrl: string): string {\r\n if (relativeUrl[0] === Constants.FORWARD_SLASH) {\r\n const url = new UrlString(baseUrl);\r\n const baseComponents = url.getUrlComponents();\r\n\r\n return (\r\n baseComponents.Protocol +\r\n \"//\" +\r\n baseComponents.HostNameAndPort +\r\n relativeUrl\r\n );\r\n }\r\n\r\n return relativeUrl;\r\n }\r\n\r\n static constructAuthorityUriFromObject(urlObject: IUri): UrlString {\r\n return new UrlString(\r\n urlObject.Protocol +\r\n \"//\" +\r\n urlObject.HostNameAndPort +\r\n \"/\" +\r\n urlObject.PathSegments.join(\"/\")\r\n );\r\n }\r\n\r\n /**\r\n * Check if the hash of the URL string contains known properties\r\n * @deprecated This API will be removed in a future version\r\n */\r\n static hashContainsKnownProperties(response: string): boolean {\r\n return !!UrlUtils.getDeserializedResponse(response);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { Logger } from \"../logger/Logger.js\";\r\nimport { UrlString } from \"../url/UrlString.js\";\r\nimport { AuthorityMetadataSource } from \"../utils/Constants.js\";\r\nimport { StaticAuthorityOptions } from \"./AuthorityOptions.js\";\r\nimport { CloudDiscoveryMetadata } from \"./CloudDiscoveryMetadata.js\";\r\nimport { CloudInstanceDiscoveryResponse } from \"./CloudInstanceDiscoveryResponse.js\";\r\nimport { OpenIdConfigResponse } from \"./OpenIdConfigResponse.js\";\r\n\r\ntype RawMetadata = {\r\n endpointMetadata: { [key: string]: OpenIdConfigResponse };\r\n instanceDiscoveryMetadata: CloudInstanceDiscoveryResponse;\r\n};\r\n\r\nexport const rawMetdataJSON: RawMetadata = {\r\n endpointMetadata: {\r\n \"login.microsoftonline.com\": {\r\n token_endpoint:\r\n \"https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/token\",\r\n jwks_uri:\r\n \"https://login.microsoftonline.com/{tenantid}/discovery/v2.0/keys\",\r\n issuer: \"https://login.microsoftonline.com/{tenantid}/v2.0\",\r\n authorization_endpoint:\r\n \"https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/authorize\",\r\n end_session_endpoint:\r\n \"https://login.microsoftonline.com/{tenantid}/oauth2/v2.0/logout\",\r\n },\r\n \"login.chinacloudapi.cn\": {\r\n token_endpoint:\r\n \"https://login.chinacloudapi.cn/{tenantid}/oauth2/v2.0/token\",\r\n jwks_uri:\r\n \"https://login.chinacloudapi.cn/{tenantid}/discovery/v2.0/keys\",\r\n issuer: \"https://login.partner.microsoftonline.cn/{tenantid}/v2.0\",\r\n authorization_endpoint:\r\n \"https://login.chinacloudapi.cn/{tenantid}/oauth2/v2.0/authorize\",\r\n end_session_endpoint:\r\n \"https://login.chinacloudapi.cn/{tenantid}/oauth2/v2.0/logout\",\r\n },\r\n \"login.microsoftonline.us\": {\r\n token_endpoint:\r\n \"https://login.microsoftonline.us/{tenantid}/oauth2/v2.0/token\",\r\n jwks_uri:\r\n \"https://login.microsoftonline.us/{tenantid}/discovery/v2.0/keys\",\r\n issuer: \"https://login.microsoftonline.us/{tenantid}/v2.0\",\r\n authorization_endpoint:\r\n \"https://login.microsoftonline.us/{tenantid}/oauth2/v2.0/authorize\",\r\n end_session_endpoint:\r\n \"https://login.microsoftonline.us/{tenantid}/oauth2/v2.0/logout\",\r\n },\r\n },\r\n instanceDiscoveryMetadata: {\r\n tenant_discovery_endpoint:\r\n \"https://{canonicalAuthority}/v2.0/.well-known/openid-configuration\",\r\n metadata: [\r\n {\r\n preferred_network: \"login.microsoftonline.com\",\r\n preferred_cache: \"login.windows.net\",\r\n aliases: [\r\n \"login.microsoftonline.com\",\r\n \"login.windows.net\",\r\n \"login.microsoft.com\",\r\n \"sts.windows.net\",\r\n ],\r\n },\r\n {\r\n preferred_network: \"login.partner.microsoftonline.cn\",\r\n preferred_cache: \"login.partner.microsoftonline.cn\",\r\n aliases: [\r\n \"login.partner.microsoftonline.cn\",\r\n \"login.chinacloudapi.cn\",\r\n ],\r\n },\r\n {\r\n preferred_network: \"login.microsoftonline.de\",\r\n preferred_cache: \"login.microsoftonline.de\",\r\n aliases: [\"login.microsoftonline.de\"],\r\n },\r\n {\r\n preferred_network: \"login.microsoftonline.us\",\r\n preferred_cache: \"login.microsoftonline.us\",\r\n aliases: [\r\n \"login.microsoftonline.us\",\r\n \"login.usgovcloudapi.net\",\r\n ],\r\n },\r\n {\r\n preferred_network: \"login-us.microsoftonline.com\",\r\n preferred_cache: \"login-us.microsoftonline.com\",\r\n aliases: [\"login-us.microsoftonline.com\"],\r\n },\r\n ],\r\n },\r\n};\r\n\r\nexport const EndpointMetadata = rawMetdataJSON.endpointMetadata;\r\nexport const InstanceDiscoveryMetadata =\r\n rawMetdataJSON.instanceDiscoveryMetadata;\r\n\r\nexport const InstanceDiscoveryMetadataAliases: Set = new Set();\r\nInstanceDiscoveryMetadata.metadata.forEach(\r\n (metadataEntry: CloudDiscoveryMetadata) => {\r\n metadataEntry.aliases.forEach((alias: string) => {\r\n InstanceDiscoveryMetadataAliases.add(alias);\r\n });\r\n }\r\n);\r\n\r\n/**\r\n * Attempts to get an aliases array from the static authority metadata sources based on the canonical authority host\r\n * @param staticAuthorityOptions\r\n * @param logger\r\n * @returns\r\n */\r\nexport function getAliasesFromStaticSources(\r\n staticAuthorityOptions: StaticAuthorityOptions,\r\n logger?: Logger\r\n): string[] {\r\n let staticAliases: string[] | undefined;\r\n const canonicalAuthority = staticAuthorityOptions.canonicalAuthority;\r\n if (canonicalAuthority) {\r\n const authorityHost = new UrlString(\r\n canonicalAuthority\r\n ).getUrlComponents().HostNameAndPort;\r\n staticAliases =\r\n getAliasesFromMetadata(\r\n authorityHost,\r\n staticAuthorityOptions.cloudDiscoveryMetadata?.metadata,\r\n AuthorityMetadataSource.CONFIG,\r\n logger\r\n ) ||\r\n getAliasesFromMetadata(\r\n authorityHost,\r\n InstanceDiscoveryMetadata.metadata,\r\n AuthorityMetadataSource.HARDCODED_VALUES,\r\n logger\r\n ) ||\r\n staticAuthorityOptions.knownAuthorities;\r\n }\r\n\r\n return staticAliases || [];\r\n}\r\n\r\n/**\r\n * Returns aliases for from the raw cloud discovery metadata passed in\r\n * @param authorityHost\r\n * @param rawCloudDiscoveryMetadata\r\n * @returns\r\n */\r\nexport function getAliasesFromMetadata(\r\n authorityHost?: string,\r\n cloudDiscoveryMetadata?: CloudDiscoveryMetadata[],\r\n source?: AuthorityMetadataSource,\r\n logger?: Logger\r\n): string[] | null {\r\n logger?.trace(`getAliasesFromMetadata called with source: ${source}`);\r\n if (authorityHost && cloudDiscoveryMetadata) {\r\n const metadata = getCloudDiscoveryMetadataFromNetworkResponse(\r\n cloudDiscoveryMetadata,\r\n authorityHost\r\n );\r\n\r\n if (metadata) {\r\n logger?.trace(\r\n `getAliasesFromMetadata: found cloud discovery metadata in ${source}, returning aliases`\r\n );\r\n return metadata.aliases;\r\n } else {\r\n logger?.trace(\r\n `getAliasesFromMetadata: did not find cloud discovery metadata in ${source}`\r\n );\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Get cloud discovery metadata for common authorities\r\n */\r\nexport function getCloudDiscoveryMetadataFromHardcodedValues(\r\n authorityHost: string\r\n): CloudDiscoveryMetadata | null {\r\n const metadata = getCloudDiscoveryMetadataFromNetworkResponse(\r\n InstanceDiscoveryMetadata.metadata,\r\n authorityHost\r\n );\r\n return metadata;\r\n}\r\n\r\n/**\r\n * Searches instance discovery network response for the entry that contains the host in the aliases list\r\n * @param response\r\n * @param authority\r\n */\r\nexport function getCloudDiscoveryMetadataFromNetworkResponse(\r\n response: CloudDiscoveryMetadata[],\r\n authorityHost: string\r\n): CloudDiscoveryMetadata | null {\r\n for (let i = 0; i < response.length; i++) {\r\n const metadata = response[i];\r\n if (metadata.aliases.includes(authorityHost)) {\r\n return metadata;\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport const cacheQuotaExceeded = \"cache_quota_exceeded\";\r\nexport const cacheErrorUnknown = \"cache_error_unknown\";\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthError } from \"./AuthError.js\";\r\nimport * as CacheErrorCodes from \"./CacheErrorCodes.js\";\r\nexport { CacheErrorCodes };\r\n\r\nexport const CacheErrorMessages = {\r\n [CacheErrorCodes.cacheQuotaExceeded]: \"Exceeded cache storage capacity.\",\r\n [CacheErrorCodes.cacheErrorUnknown]:\r\n \"Unexpected error occurred when using cache storage.\",\r\n};\r\n\r\n/**\r\n * Error thrown when there is an error with the cache\r\n */\r\nexport class CacheError extends AuthError {\r\n /**\r\n * Short string denoting error\r\n */\r\n errorCode: string;\r\n\r\n /**\r\n * Detailed description of error\r\n */\r\n errorMessage: string;\r\n\r\n constructor(errorCode: string, errorMessage?: string) {\r\n const message =\r\n errorMessage ||\r\n (CacheErrorMessages[errorCode]\r\n ? CacheErrorMessages[errorCode]\r\n : CacheErrorMessages[CacheErrorCodes.cacheErrorUnknown]);\r\n\r\n super(`${errorCode}: ${message}`);\r\n Object.setPrototypeOf(this, CacheError.prototype);\r\n\r\n this.name = \"CacheError\";\r\n this.errorCode = errorCode;\r\n this.errorMessage = message;\r\n }\r\n}\r\n\r\n/**\r\n * Helper function to wrap browser errors in a CacheError object\r\n * @param e\r\n * @returns\r\n */\r\nexport function createCacheError(e: unknown): CacheError {\r\n if (!(e instanceof Error)) {\r\n return new CacheError(CacheErrorCodes.cacheErrorUnknown);\r\n }\r\n\r\n if (\r\n e.name === \"QuotaExceededError\" ||\r\n e.name === \"NS_ERROR_DOM_QUOTA_REACHED\" ||\r\n e.message.includes(\"exceeded the quota\")\r\n ) {\r\n return new CacheError(CacheErrorCodes.cacheQuotaExceeded);\r\n } else {\r\n return new CacheError(e.name, e.message);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n AccountFilter,\r\n CredentialFilter,\r\n ValidCredentialType,\r\n AppMetadataFilter,\r\n AppMetadataCache,\r\n TokenKeys,\r\n TenantProfileFilter,\r\n} from \"./utils/CacheTypes.js\";\r\nimport { CacheRecord } from \"./entities/CacheRecord.js\";\r\nimport {\r\n CredentialType,\r\n APP_METADATA,\r\n THE_FAMILY_ID,\r\n AUTHORITY_METADATA_CONSTANTS,\r\n AuthenticationScheme,\r\n} from \"../utils/Constants.js\";\r\nimport { CredentialEntity } from \"./entities/CredentialEntity.js\";\r\nimport { ScopeSet } from \"../request/ScopeSet.js\";\r\nimport { AccountEntity } from \"./entities/AccountEntity.js\";\r\nimport { AccessTokenEntity } from \"./entities/AccessTokenEntity.js\";\r\nimport { IdTokenEntity } from \"./entities/IdTokenEntity.js\";\r\nimport { RefreshTokenEntity } from \"./entities/RefreshTokenEntity.js\";\r\nimport { ICacheManager } from \"./interface/ICacheManager.js\";\r\nimport {\r\n createClientAuthError,\r\n ClientAuthErrorCodes,\r\n} from \"../error/ClientAuthError.js\";\r\nimport {\r\n AccountInfo,\r\n TenantProfile,\r\n updateAccountTenantProfileData,\r\n} from \"../account/AccountInfo.js\";\r\nimport { AppMetadataEntity } from \"./entities/AppMetadataEntity.js\";\r\nimport { ServerTelemetryEntity } from \"./entities/ServerTelemetryEntity.js\";\r\nimport { ThrottlingEntity } from \"./entities/ThrottlingEntity.js\";\r\nimport { extractTokenClaims } from \"../account/AuthToken.js\";\r\nimport { ICrypto } from \"../crypto/ICrypto.js\";\r\nimport { AuthorityMetadataEntity } from \"./entities/AuthorityMetadataEntity.js\";\r\nimport { BaseAuthRequest } from \"../request/BaseAuthRequest.js\";\r\nimport { Logger } from \"../logger/Logger.js\";\r\nimport { name, version } from \"../packageMetadata.js\";\r\nimport { StoreInCache } from \"../request/StoreInCache.js\";\r\nimport { getAliasesFromStaticSources } from \"../authority/AuthorityMetadata.js\";\r\nimport { StaticAuthorityOptions } from \"../authority/AuthorityOptions.js\";\r\nimport { TokenClaims } from \"../account/TokenClaims.js\";\r\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\r\nimport { createCacheError } from \"../error/CacheError.js\";\r\nimport { AuthError } from \"../error/AuthError.js\";\r\n\r\n/**\r\n * Interface class which implement cache storage functions used by MSAL to perform validity checks, and store tokens.\r\n * @internal\r\n */\r\nexport abstract class CacheManager implements ICacheManager {\r\n protected clientId: string;\r\n protected cryptoImpl: ICrypto;\r\n // Instance of logger for functions defined in the msal-common layer\r\n private commonLogger: Logger;\r\n private staticAuthorityOptions?: StaticAuthorityOptions;\r\n protected performanceClient: IPerformanceClient;\r\n\r\n constructor(\r\n clientId: string,\r\n cryptoImpl: ICrypto,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient,\r\n staticAuthorityOptions?: StaticAuthorityOptions\r\n ) {\r\n this.clientId = clientId;\r\n this.cryptoImpl = cryptoImpl;\r\n this.commonLogger = logger.clone(name, version);\r\n this.staticAuthorityOptions = staticAuthorityOptions;\r\n this.performanceClient = performanceClient;\r\n }\r\n\r\n /**\r\n * fetch the account entity from the platform cache\r\n * @param accountKey\r\n */\r\n abstract getAccount(\r\n accountKey: string,\r\n correlationId: string\r\n ): AccountEntity | null;\r\n\r\n /**\r\n * set account entity in the platform cache\r\n * @param account\r\n * @param correlationId\r\n */\r\n abstract setAccount(\r\n account: AccountEntity,\r\n correlationId: string\r\n ): Promise;\r\n\r\n /**\r\n * fetch the idToken entity from the platform cache\r\n * @param idTokenKey\r\n */\r\n abstract getIdTokenCredential(\r\n idTokenKey: string,\r\n correlationId: string\r\n ): IdTokenEntity | null;\r\n\r\n /**\r\n * set idToken entity to the platform cache\r\n * @param idToken\r\n * @param correlationId\r\n */\r\n abstract setIdTokenCredential(\r\n idToken: IdTokenEntity,\r\n correlationId: string\r\n ): Promise;\r\n\r\n /**\r\n * fetch the idToken entity from the platform cache\r\n * @param accessTokenKey\r\n */\r\n abstract getAccessTokenCredential(\r\n accessTokenKey: string,\r\n correlationId: string\r\n ): AccessTokenEntity | null;\r\n\r\n /**\r\n * set accessToken entity to the platform cache\r\n * @param accessToken\r\n * @param correlationId\r\n */\r\n abstract setAccessTokenCredential(\r\n accessToken: AccessTokenEntity,\r\n correlationId: string\r\n ): Promise;\r\n\r\n /**\r\n * fetch the idToken entity from the platform cache\r\n * @param refreshTokenKey\r\n */\r\n abstract getRefreshTokenCredential(\r\n refreshTokenKey: string,\r\n correlationId: string\r\n ): RefreshTokenEntity | null;\r\n\r\n /**\r\n * set refreshToken entity to the platform cache\r\n * @param refreshToken\r\n * @param correlationId\r\n */\r\n abstract setRefreshTokenCredential(\r\n refreshToken: RefreshTokenEntity,\r\n correlationId: string\r\n ): Promise;\r\n\r\n /**\r\n * fetch appMetadata entity from the platform cache\r\n * @param appMetadataKey\r\n */\r\n abstract getAppMetadata(appMetadataKey: string): AppMetadataEntity | null;\r\n\r\n /**\r\n * set appMetadata entity to the platform cache\r\n * @param appMetadata\r\n */\r\n abstract setAppMetadata(\r\n appMetadata: AppMetadataEntity,\r\n correlationId: string\r\n ): void;\r\n\r\n /**\r\n * fetch server telemetry entity from the platform cache\r\n * @param serverTelemetryKey\r\n */\r\n abstract getServerTelemetry(\r\n serverTelemetryKey: string\r\n ): ServerTelemetryEntity | null;\r\n\r\n /**\r\n * set server telemetry entity to the platform cache\r\n * @param serverTelemetryKey\r\n * @param serverTelemetry\r\n */\r\n abstract setServerTelemetry(\r\n serverTelemetryKey: string,\r\n serverTelemetry: ServerTelemetryEntity,\r\n correlationId: string\r\n ): void;\r\n\r\n /**\r\n * fetch cloud discovery metadata entity from the platform cache\r\n * @param key\r\n */\r\n abstract getAuthorityMetadata(key: string): AuthorityMetadataEntity | null;\r\n\r\n /**\r\n *\r\n */\r\n abstract getAuthorityMetadataKeys(): Array;\r\n\r\n /**\r\n * set cloud discovery metadata entity to the platform cache\r\n * @param key\r\n * @param value\r\n */\r\n abstract setAuthorityMetadata(\r\n key: string,\r\n value: AuthorityMetadataEntity\r\n ): void;\r\n\r\n /**\r\n * fetch throttling entity from the platform cache\r\n * @param throttlingCacheKey\r\n */\r\n abstract getThrottlingCache(\r\n throttlingCacheKey: string\r\n ): ThrottlingEntity | null;\r\n\r\n /**\r\n * set throttling entity to the platform cache\r\n * @param throttlingCacheKey\r\n * @param throttlingCache\r\n */\r\n abstract setThrottlingCache(\r\n throttlingCacheKey: string,\r\n throttlingCache: ThrottlingEntity,\r\n correlationId: string\r\n ): void;\r\n\r\n /**\r\n * Function to remove an item from cache given its key.\r\n * @param key\r\n */\r\n abstract removeItem(key: string, correlationId: string): void;\r\n\r\n /**\r\n * Function which retrieves all current keys from the cache.\r\n */\r\n abstract getKeys(): string[];\r\n\r\n /**\r\n * Function which retrieves all account keys from the cache\r\n */\r\n abstract getAccountKeys(): string[];\r\n\r\n /**\r\n * Function which retrieves all token keys from the cache\r\n */\r\n abstract getTokenKeys(): TokenKeys;\r\n\r\n /**\r\n * Returns credential cache key from the entity\r\n * @param credential\r\n */\r\n abstract generateCredentialKey(credential: CredentialEntity): string;\r\n\r\n /**\r\n * Returns the account cache key from the account info\r\n * @param account\r\n */\r\n abstract generateAccountKey(account: AccountInfo): string;\r\n\r\n /**\r\n * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.\r\n * @param accountFilter - (Optional) filter to narrow down the accounts returned\r\n * @returns Array of AccountInfo objects in cache\r\n */\r\n getAllAccounts(\r\n accountFilter: AccountFilter,\r\n correlationId: string\r\n ): AccountInfo[] {\r\n return this.buildTenantProfiles(\r\n this.getAccountsFilteredBy(accountFilter, correlationId),\r\n correlationId,\r\n accountFilter\r\n );\r\n }\r\n\r\n /**\r\n * Gets first tenanted AccountInfo object found based on provided filters\r\n */\r\n getAccountInfoFilteredBy(\r\n accountFilter: AccountFilter,\r\n correlationId: string\r\n ): AccountInfo | null {\r\n if (\r\n Object.keys(accountFilter).length === 0 ||\r\n Object.values(accountFilter).every((value) => !value)\r\n ) {\r\n this.commonLogger.warning(\r\n \"getAccountInfoFilteredBy: Account filter is empty or invalid, returning null\"\r\n );\r\n return null;\r\n }\r\n const allAccounts = this.getAllAccounts(accountFilter, correlationId);\r\n if (allAccounts.length > 1) {\r\n // If one or more accounts are found, prioritize accounts that have an ID token\r\n const sortedAccounts = allAccounts.sort((account) => {\r\n return account.idTokenClaims ? -1 : 1;\r\n });\r\n return sortedAccounts[0];\r\n } else if (allAccounts.length === 1) {\r\n // If only one account is found, return it regardless of whether a matching ID token was found\r\n return allAccounts[0];\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Returns a single matching\r\n * @param accountFilter\r\n * @returns\r\n */\r\n getBaseAccountInfo(\r\n accountFilter: AccountFilter,\r\n correlationId: string\r\n ): AccountInfo | null {\r\n const accountEntities = this.getAccountsFilteredBy(\r\n accountFilter,\r\n correlationId\r\n );\r\n if (accountEntities.length > 0) {\r\n return accountEntities[0].getAccountInfo();\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Matches filtered account entities with cached ID tokens that match the tenant profile-specific account filters\r\n * and builds the account info objects from the matching ID token's claims\r\n * @param cachedAccounts\r\n * @param accountFilter\r\n * @returns Array of AccountInfo objects that match account and tenant profile filters\r\n */\r\n private buildTenantProfiles(\r\n cachedAccounts: AccountEntity[],\r\n correlationId: string,\r\n accountFilter?: AccountFilter\r\n ): AccountInfo[] {\r\n return cachedAccounts.flatMap((accountEntity) => {\r\n return this.getTenantProfilesFromAccountEntity(\r\n accountEntity,\r\n correlationId,\r\n accountFilter?.tenantId,\r\n accountFilter\r\n );\r\n });\r\n }\r\n\r\n private getTenantedAccountInfoByFilter(\r\n accountInfo: AccountInfo,\r\n tokenKeys: TokenKeys,\r\n tenantProfile: TenantProfile,\r\n correlationId: string,\r\n tenantProfileFilter?: TenantProfileFilter\r\n ): AccountInfo | null {\r\n let tenantedAccountInfo: AccountInfo | null = null;\r\n let idTokenClaims: TokenClaims | undefined;\r\n\r\n if (tenantProfileFilter) {\r\n if (\r\n !this.tenantProfileMatchesFilter(\r\n tenantProfile,\r\n tenantProfileFilter\r\n )\r\n ) {\r\n return null;\r\n }\r\n }\r\n\r\n const idToken = this.getIdToken(\r\n accountInfo,\r\n correlationId,\r\n tokenKeys,\r\n tenantProfile.tenantId\r\n );\r\n\r\n if (idToken) {\r\n idTokenClaims = extractTokenClaims(\r\n idToken.secret,\r\n this.cryptoImpl.base64Decode\r\n );\r\n\r\n if (\r\n !this.idTokenClaimsMatchTenantProfileFilter(\r\n idTokenClaims,\r\n tenantProfileFilter\r\n )\r\n ) {\r\n // ID token sourced claims don't match so this tenant profile is not a match\r\n return null;\r\n }\r\n }\r\n\r\n // Expand tenant profile into account info based on matching tenant profile and if available matching ID token claims\r\n tenantedAccountInfo = updateAccountTenantProfileData(\r\n accountInfo,\r\n tenantProfile,\r\n idTokenClaims,\r\n idToken?.secret\r\n );\r\n\r\n return tenantedAccountInfo;\r\n }\r\n\r\n private getTenantProfilesFromAccountEntity(\r\n accountEntity: AccountEntity,\r\n correlationId: string,\r\n targetTenantId?: string,\r\n tenantProfileFilter?: TenantProfileFilter\r\n ): AccountInfo[] {\r\n const accountInfo = accountEntity.getAccountInfo();\r\n let searchTenantProfiles: Map =\r\n accountInfo.tenantProfiles || new Map();\r\n const tokenKeys = this.getTokenKeys();\r\n\r\n // If a tenant ID was provided, only return the tenant profile for that tenant ID if it exists\r\n if (targetTenantId) {\r\n const tenantProfile = searchTenantProfiles.get(targetTenantId);\r\n if (tenantProfile) {\r\n // Reduce search field to just this tenant profile\r\n searchTenantProfiles = new Map([\r\n [targetTenantId, tenantProfile],\r\n ]);\r\n } else {\r\n // No tenant profile for search tenant ID, return empty array\r\n return [];\r\n }\r\n }\r\n\r\n const matchingTenantProfiles: AccountInfo[] = [];\r\n searchTenantProfiles.forEach((tenantProfile: TenantProfile) => {\r\n const tenantedAccountInfo = this.getTenantedAccountInfoByFilter(\r\n accountInfo,\r\n tokenKeys,\r\n tenantProfile,\r\n correlationId,\r\n tenantProfileFilter\r\n );\r\n if (tenantedAccountInfo) {\r\n matchingTenantProfiles.push(tenantedAccountInfo);\r\n }\r\n });\r\n\r\n return matchingTenantProfiles;\r\n }\r\n\r\n private tenantProfileMatchesFilter(\r\n tenantProfile: TenantProfile,\r\n tenantProfileFilter: TenantProfileFilter\r\n ): boolean {\r\n if (\r\n !!tenantProfileFilter.localAccountId &&\r\n !this.matchLocalAccountIdFromTenantProfile(\r\n tenantProfile,\r\n tenantProfileFilter.localAccountId\r\n )\r\n ) {\r\n return false;\r\n }\r\n\r\n if (\r\n !!tenantProfileFilter.name &&\r\n !(tenantProfile.name === tenantProfileFilter.name)\r\n ) {\r\n return false;\r\n }\r\n\r\n if (\r\n tenantProfileFilter.isHomeTenant !== undefined &&\r\n !(tenantProfile.isHomeTenant === tenantProfileFilter.isHomeTenant)\r\n ) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private idTokenClaimsMatchTenantProfileFilter(\r\n idTokenClaims: TokenClaims,\r\n tenantProfileFilter?: TenantProfileFilter\r\n ): boolean {\r\n // Tenant Profile filtering\r\n if (tenantProfileFilter) {\r\n if (\r\n !!tenantProfileFilter.localAccountId &&\r\n !this.matchLocalAccountIdFromTokenClaims(\r\n idTokenClaims,\r\n tenantProfileFilter.localAccountId\r\n )\r\n ) {\r\n return false;\r\n }\r\n\r\n if (\r\n !!tenantProfileFilter.loginHint &&\r\n !this.matchLoginHintFromTokenClaims(\r\n idTokenClaims,\r\n tenantProfileFilter.loginHint\r\n )\r\n ) {\r\n return false;\r\n }\r\n\r\n if (\r\n !!tenantProfileFilter.username &&\r\n !this.matchUsername(\r\n idTokenClaims.preferred_username,\r\n tenantProfileFilter.username\r\n )\r\n ) {\r\n return false;\r\n }\r\n\r\n if (\r\n !!tenantProfileFilter.name &&\r\n !this.matchName(idTokenClaims, tenantProfileFilter.name)\r\n ) {\r\n return false;\r\n }\r\n\r\n if (\r\n !!tenantProfileFilter.sid &&\r\n !this.matchSid(idTokenClaims, tenantProfileFilter.sid)\r\n ) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * saves a cache record\r\n * @param cacheRecord {CacheRecord}\r\n * @param storeInCache {?StoreInCache}\r\n * @param correlationId {?string} correlation id\r\n */\r\n async saveCacheRecord(\r\n cacheRecord: CacheRecord,\r\n correlationId: string,\r\n storeInCache?: StoreInCache\r\n ): Promise {\r\n if (!cacheRecord) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.invalidCacheRecord\r\n );\r\n }\r\n\r\n try {\r\n if (!!cacheRecord.account) {\r\n await this.setAccount(cacheRecord.account, correlationId);\r\n }\r\n\r\n if (!!cacheRecord.idToken && storeInCache?.idToken !== false) {\r\n await this.setIdTokenCredential(\r\n cacheRecord.idToken,\r\n correlationId\r\n );\r\n }\r\n\r\n if (\r\n !!cacheRecord.accessToken &&\r\n storeInCache?.accessToken !== false\r\n ) {\r\n await this.saveAccessToken(\r\n cacheRecord.accessToken,\r\n correlationId\r\n );\r\n }\r\n\r\n if (\r\n !!cacheRecord.refreshToken &&\r\n storeInCache?.refreshToken !== false\r\n ) {\r\n await this.setRefreshTokenCredential(\r\n cacheRecord.refreshToken,\r\n correlationId\r\n );\r\n }\r\n\r\n if (!!cacheRecord.appMetadata) {\r\n this.setAppMetadata(cacheRecord.appMetadata, correlationId);\r\n }\r\n } catch (e: unknown) {\r\n this.commonLogger?.error(`CacheManager.saveCacheRecord: failed`);\r\n if (e instanceof AuthError) {\r\n throw e;\r\n } else {\r\n throw createCacheError(e);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * saves access token credential\r\n * @param credential\r\n */\r\n private async saveAccessToken(\r\n credential: AccessTokenEntity,\r\n correlationId: string\r\n ): Promise {\r\n const accessTokenFilter: CredentialFilter = {\r\n clientId: credential.clientId,\r\n credentialType: credential.credentialType,\r\n environment: credential.environment,\r\n homeAccountId: credential.homeAccountId,\r\n realm: credential.realm,\r\n tokenType: credential.tokenType,\r\n requestedClaimsHash: credential.requestedClaimsHash,\r\n };\r\n\r\n const tokenKeys = this.getTokenKeys();\r\n const currentScopes = ScopeSet.fromString(credential.target);\r\n\r\n tokenKeys.accessToken.forEach((key) => {\r\n if (\r\n !this.accessTokenKeyMatchesFilter(key, accessTokenFilter, false)\r\n ) {\r\n return;\r\n }\r\n\r\n const tokenEntity = this.getAccessTokenCredential(\r\n key,\r\n correlationId\r\n );\r\n\r\n if (\r\n tokenEntity &&\r\n this.credentialMatchesFilter(tokenEntity, accessTokenFilter)\r\n ) {\r\n const tokenScopeSet = ScopeSet.fromString(tokenEntity.target);\r\n if (tokenScopeSet.intersectingScopeSets(currentScopes)) {\r\n this.removeAccessToken(key, correlationId);\r\n }\r\n }\r\n });\r\n await this.setAccessTokenCredential(credential, correlationId);\r\n }\r\n\r\n /**\r\n * Retrieve account entities matching all provided tenant-agnostic filters; if no filter is set, get all account entities in the cache\r\n * Not checking for casing as keys are all generated in lower case, remember to convert to lower case if object properties are compared\r\n * @param accountFilter - An object containing Account properties to filter by\r\n */\r\n getAccountsFilteredBy(\r\n accountFilter: AccountFilter,\r\n correlationId: string\r\n ): AccountEntity[] {\r\n const allAccountKeys = this.getAccountKeys();\r\n const matchingAccounts: AccountEntity[] = [];\r\n allAccountKeys.forEach((cacheKey) => {\r\n const entity: AccountEntity | null = this.getAccount(\r\n cacheKey,\r\n correlationId\r\n );\r\n\r\n // Match base account fields\r\n\r\n if (!entity) {\r\n return;\r\n }\r\n\r\n if (\r\n !!accountFilter.homeAccountId &&\r\n !this.matchHomeAccountId(entity, accountFilter.homeAccountId)\r\n ) {\r\n return;\r\n }\r\n\r\n if (\r\n !!accountFilter.username &&\r\n !this.matchUsername(entity.username, accountFilter.username)\r\n ) {\r\n return;\r\n }\r\n\r\n if (\r\n !!accountFilter.environment &&\r\n !this.matchEnvironment(entity, accountFilter.environment)\r\n ) {\r\n return;\r\n }\r\n\r\n if (\r\n !!accountFilter.realm &&\r\n !this.matchRealm(entity, accountFilter.realm)\r\n ) {\r\n return;\r\n }\r\n\r\n if (\r\n !!accountFilter.nativeAccountId &&\r\n !this.matchNativeAccountId(\r\n entity,\r\n accountFilter.nativeAccountId\r\n )\r\n ) {\r\n return;\r\n }\r\n\r\n if (\r\n !!accountFilter.authorityType &&\r\n !this.matchAuthorityType(entity, accountFilter.authorityType)\r\n ) {\r\n return;\r\n }\r\n\r\n // If at least one tenant profile matches the tenant profile filter, add the account to the list of matching accounts\r\n const tenantProfileFilter: TenantProfileFilter = {\r\n localAccountId: accountFilter?.localAccountId,\r\n name: accountFilter?.name,\r\n };\r\n\r\n const matchingTenantProfiles = entity.tenantProfiles?.filter(\r\n (tenantProfile: TenantProfile) => {\r\n return this.tenantProfileMatchesFilter(\r\n tenantProfile,\r\n tenantProfileFilter\r\n );\r\n }\r\n );\r\n\r\n if (matchingTenantProfiles && matchingTenantProfiles.length === 0) {\r\n // No tenant profile for this account matches filter, don't add to list of matching accounts\r\n return;\r\n }\r\n\r\n matchingAccounts.push(entity);\r\n });\r\n\r\n return matchingAccounts;\r\n }\r\n\r\n /**\r\n * Returns whether or not the given credential entity matches the filter\r\n * @param entity\r\n * @param filter\r\n * @returns\r\n */\r\n credentialMatchesFilter(\r\n entity: ValidCredentialType,\r\n filter: CredentialFilter\r\n ): boolean {\r\n if (!!filter.clientId && !this.matchClientId(entity, filter.clientId)) {\r\n return false;\r\n }\r\n\r\n if (\r\n !!filter.userAssertionHash &&\r\n !this.matchUserAssertionHash(entity, filter.userAssertionHash)\r\n ) {\r\n return false;\r\n }\r\n\r\n /*\r\n * homeAccountId can be undefined, and we want to filter out cached items that have a homeAccountId of \"\"\r\n * because we don't want a client_credential request to return a cached token that has a homeAccountId\r\n */\r\n if (\r\n typeof filter.homeAccountId === \"string\" &&\r\n !this.matchHomeAccountId(entity, filter.homeAccountId)\r\n ) {\r\n return false;\r\n }\r\n\r\n if (\r\n !!filter.environment &&\r\n !this.matchEnvironment(entity, filter.environment)\r\n ) {\r\n return false;\r\n }\r\n\r\n if (!!filter.realm && !this.matchRealm(entity, filter.realm)) {\r\n return false;\r\n }\r\n\r\n if (\r\n !!filter.credentialType &&\r\n !this.matchCredentialType(entity, filter.credentialType)\r\n ) {\r\n return false;\r\n }\r\n\r\n if (!!filter.familyId && !this.matchFamilyId(entity, filter.familyId)) {\r\n return false;\r\n }\r\n\r\n /*\r\n * idTokens do not have \"target\", target specific refreshTokens do exist for some types of authentication\r\n * Resource specific refresh tokens case will be added when the support is deemed necessary\r\n */\r\n if (!!filter.target && !this.matchTarget(entity, filter.target)) {\r\n return false;\r\n }\r\n\r\n // If request OR cached entity has requested Claims Hash, check if they match\r\n if (filter.requestedClaimsHash || entity.requestedClaimsHash) {\r\n // Don't match if either is undefined or they are different\r\n if (entity.requestedClaimsHash !== filter.requestedClaimsHash) {\r\n return false;\r\n }\r\n }\r\n\r\n // Access Token with Auth Scheme specific matching\r\n if (\r\n entity.credentialType ===\r\n CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME\r\n ) {\r\n if (\r\n !!filter.tokenType &&\r\n !this.matchTokenType(entity, filter.tokenType)\r\n ) {\r\n return false;\r\n }\r\n\r\n // KeyId (sshKid) in request must match cached SSH certificate keyId because SSH cert is bound to a specific key\r\n if (filter.tokenType === AuthenticationScheme.SSH) {\r\n if (filter.keyId && !this.matchKeyId(entity, filter.keyId)) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * retrieve appMetadata matching all provided filters; if no filter is set, get all appMetadata\r\n * @param filter\r\n */\r\n getAppMetadataFilteredBy(filter: AppMetadataFilter): AppMetadataCache {\r\n const allCacheKeys = this.getKeys();\r\n const matchingAppMetadata: AppMetadataCache = {};\r\n\r\n allCacheKeys.forEach((cacheKey) => {\r\n // don't parse any non-appMetadata type cache entities\r\n if (!this.isAppMetadata(cacheKey)) {\r\n return;\r\n }\r\n\r\n // Attempt retrieval\r\n const entity = this.getAppMetadata(cacheKey);\r\n\r\n if (!entity) {\r\n return;\r\n }\r\n\r\n if (\r\n !!filter.environment &&\r\n !this.matchEnvironment(entity, filter.environment)\r\n ) {\r\n return;\r\n }\r\n\r\n if (\r\n !!filter.clientId &&\r\n !this.matchClientId(entity, filter.clientId)\r\n ) {\r\n return;\r\n }\r\n\r\n matchingAppMetadata[cacheKey] = entity;\r\n });\r\n\r\n return matchingAppMetadata;\r\n }\r\n\r\n /**\r\n * retrieve authorityMetadata that contains a matching alias\r\n * @param filter\r\n */\r\n getAuthorityMetadataByAlias(host: string): AuthorityMetadataEntity | null {\r\n const allCacheKeys = this.getAuthorityMetadataKeys();\r\n let matchedEntity = null;\r\n\r\n allCacheKeys.forEach((cacheKey) => {\r\n // don't parse any non-authorityMetadata type cache entities\r\n if (\r\n !this.isAuthorityMetadata(cacheKey) ||\r\n cacheKey.indexOf(this.clientId) === -1\r\n ) {\r\n return;\r\n }\r\n\r\n // Attempt retrieval\r\n const entity = this.getAuthorityMetadata(cacheKey);\r\n\r\n if (!entity) {\r\n return;\r\n }\r\n\r\n if (entity.aliases.indexOf(host) === -1) {\r\n return;\r\n }\r\n\r\n matchedEntity = entity;\r\n });\r\n\r\n return matchedEntity;\r\n }\r\n\r\n /**\r\n * Removes all accounts and related tokens from cache.\r\n */\r\n removeAllAccounts(correlationId: string): void {\r\n const accounts = this.getAllAccounts({}, correlationId);\r\n accounts.forEach((account) => {\r\n this.removeAccount(account, correlationId);\r\n });\r\n }\r\n\r\n /**\r\n * Removes the account and related tokens for a given account key\r\n * @param account\r\n */\r\n removeAccount(account: AccountInfo, correlationId: string): void {\r\n this.removeAccountContext(account, correlationId);\r\n const accountKeys = this.getAccountKeys();\r\n const keyFilter = (key: string): boolean => {\r\n return (\r\n key.includes(account.homeAccountId) &&\r\n key.includes(account.environment)\r\n );\r\n };\r\n accountKeys.filter(keyFilter).forEach((key) => {\r\n this.removeItem(key, correlationId);\r\n this.performanceClient.incrementFields(\r\n { accountsRemoved: 1 },\r\n correlationId\r\n );\r\n });\r\n }\r\n\r\n /**\r\n * Removes credentials associated with the provided account\r\n * @param account\r\n */\r\n removeAccountContext(account: AccountInfo, correlationId: string): void {\r\n const allTokenKeys = this.getTokenKeys();\r\n const keyFilter = (key: string): boolean => {\r\n return (\r\n key.includes(account.homeAccountId) &&\r\n key.includes(account.environment)\r\n );\r\n };\r\n\r\n allTokenKeys.idToken.filter(keyFilter).forEach((key) => {\r\n this.removeIdToken(key, correlationId);\r\n });\r\n\r\n allTokenKeys.accessToken.filter(keyFilter).forEach((key) => {\r\n this.removeAccessToken(key, correlationId);\r\n });\r\n\r\n allTokenKeys.refreshToken.filter(keyFilter).forEach((key) => {\r\n this.removeRefreshToken(key, correlationId);\r\n });\r\n }\r\n\r\n /**\r\n * Removes accessToken from the cache\r\n * @param key\r\n * @param correlationId\r\n */\r\n removeAccessToken(key: string, correlationId: string): void {\r\n const credential = this.getAccessTokenCredential(key, correlationId);\r\n this.removeItem(key, correlationId);\r\n this.performanceClient.incrementFields(\r\n { accessTokensRemoved: 1 },\r\n correlationId\r\n );\r\n\r\n if (\r\n !credential ||\r\n credential.credentialType.toLowerCase() !==\r\n CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME.toLowerCase() ||\r\n credential.tokenType !== AuthenticationScheme.POP\r\n ) {\r\n // If the credential is not a PoP token, we can return\r\n return;\r\n }\r\n\r\n // Remove Token Binding Key from key store for PoP Tokens Credentials\r\n const kid = credential.keyId;\r\n\r\n if (kid) {\r\n void this.cryptoImpl.removeTokenBindingKey(kid).catch(() => {\r\n this.commonLogger.error(\r\n `Failed to remove token binding key ${kid}`,\r\n correlationId\r\n );\r\n this.performanceClient?.incrementFields(\r\n { removeTokenBindingKeyFailure: 1 },\r\n correlationId\r\n );\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Removes all app metadata objects from cache.\r\n */\r\n removeAppMetadata(correlationId: string): boolean {\r\n const allCacheKeys = this.getKeys();\r\n allCacheKeys.forEach((cacheKey) => {\r\n if (this.isAppMetadata(cacheKey)) {\r\n this.removeItem(cacheKey, correlationId);\r\n }\r\n });\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Retrieve IdTokenEntity from cache\r\n * @param account {AccountInfo}\r\n * @param tokenKeys {?TokenKeys}\r\n * @param targetRealm {?string}\r\n * @param performanceClient {?IPerformanceClient}\r\n * @param correlationId {?string}\r\n */\r\n getIdToken(\r\n account: AccountInfo,\r\n correlationId: string,\r\n tokenKeys?: TokenKeys,\r\n targetRealm?: string,\r\n performanceClient?: IPerformanceClient\r\n ): IdTokenEntity | null {\r\n this.commonLogger.trace(\"CacheManager - getIdToken called\");\r\n const idTokenFilter: CredentialFilter = {\r\n homeAccountId: account.homeAccountId,\r\n environment: account.environment,\r\n credentialType: CredentialType.ID_TOKEN,\r\n clientId: this.clientId,\r\n realm: targetRealm,\r\n };\r\n\r\n const idTokenMap: Map = this.getIdTokensByFilter(\r\n idTokenFilter,\r\n correlationId,\r\n tokenKeys\r\n );\r\n\r\n const numIdTokens = idTokenMap.size;\r\n\r\n if (numIdTokens < 1) {\r\n this.commonLogger.info(\"CacheManager:getIdToken - No token found\");\r\n return null;\r\n } else if (numIdTokens > 1) {\r\n let tokensToBeRemoved: Map = idTokenMap;\r\n // Multiple tenant profiles and no tenant specified, pick home account\r\n if (!targetRealm) {\r\n const homeIdTokenMap: Map = new Map<\r\n string,\r\n IdTokenEntity\r\n >();\r\n idTokenMap.forEach((idToken, key) => {\r\n if (idToken.realm === account.tenantId) {\r\n homeIdTokenMap.set(key, idToken);\r\n }\r\n });\r\n const numHomeIdTokens = homeIdTokenMap.size;\r\n if (numHomeIdTokens < 1) {\r\n this.commonLogger.info(\r\n \"CacheManager:getIdToken - Multiple ID tokens found for account but none match account entity tenant id, returning first result\"\r\n );\r\n return idTokenMap.values().next().value;\r\n } else if (numHomeIdTokens === 1) {\r\n this.commonLogger.info(\r\n \"CacheManager:getIdToken - Multiple ID tokens found for account, defaulting to home tenant profile\"\r\n );\r\n return homeIdTokenMap.values().next().value;\r\n } else {\r\n // Multiple ID tokens for home tenant profile, remove all and return null\r\n tokensToBeRemoved = homeIdTokenMap;\r\n }\r\n }\r\n // Multiple tokens for a single tenant profile, remove all and return null\r\n this.commonLogger.info(\r\n \"CacheManager:getIdToken - Multiple matching ID tokens found, clearing them\"\r\n );\r\n tokensToBeRemoved.forEach((idToken, key) => {\r\n this.removeIdToken(key, correlationId);\r\n });\r\n if (performanceClient && correlationId) {\r\n performanceClient.addFields(\r\n { multiMatchedID: idTokenMap.size },\r\n correlationId\r\n );\r\n }\r\n return null;\r\n }\r\n\r\n this.commonLogger.info(\"CacheManager:getIdToken - Returning ID token\");\r\n return idTokenMap.values().next().value;\r\n }\r\n\r\n /**\r\n * Gets all idTokens matching the given filter\r\n * @param filter\r\n * @returns\r\n */\r\n getIdTokensByFilter(\r\n filter: CredentialFilter,\r\n correlationId: string,\r\n tokenKeys?: TokenKeys\r\n ): Map {\r\n const idTokenKeys =\r\n (tokenKeys && tokenKeys.idToken) || this.getTokenKeys().idToken;\r\n\r\n const idTokens: Map = new Map<\r\n string,\r\n IdTokenEntity\r\n >();\r\n idTokenKeys.forEach((key) => {\r\n if (\r\n !this.idTokenKeyMatchesFilter(key, {\r\n clientId: this.clientId,\r\n ...filter,\r\n })\r\n ) {\r\n return;\r\n }\r\n const idToken = this.getIdTokenCredential(key, correlationId);\r\n if (idToken && this.credentialMatchesFilter(idToken, filter)) {\r\n idTokens.set(key, idToken);\r\n }\r\n });\r\n\r\n return idTokens;\r\n }\r\n\r\n /**\r\n * Validate the cache key against filter before retrieving and parsing cache value\r\n * @param key\r\n * @param filter\r\n * @returns\r\n */\r\n idTokenKeyMatchesFilter(\r\n inputKey: string,\r\n filter: CredentialFilter\r\n ): boolean {\r\n const key = inputKey.toLowerCase();\r\n if (\r\n filter.clientId &&\r\n key.indexOf(filter.clientId.toLowerCase()) === -1\r\n ) {\r\n return false;\r\n }\r\n\r\n if (\r\n filter.homeAccountId &&\r\n key.indexOf(filter.homeAccountId.toLowerCase()) === -1\r\n ) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Removes idToken from the cache\r\n * @param key\r\n */\r\n removeIdToken(key: string, correlationId: string): void {\r\n this.removeItem(key, correlationId);\r\n }\r\n\r\n /**\r\n * Removes refresh token from the cache\r\n * @param key\r\n */\r\n removeRefreshToken(key: string, correlationId: string): void {\r\n this.removeItem(key, correlationId);\r\n }\r\n\r\n /**\r\n * Retrieve AccessTokenEntity from cache\r\n * @param account {AccountInfo}\r\n * @param request {BaseAuthRequest}\r\n * @param correlationId {?string}\r\n * @param tokenKeys {?TokenKeys}\r\n * @param performanceClient {?IPerformanceClient}\r\n */\r\n getAccessToken(\r\n account: AccountInfo,\r\n request: BaseAuthRequest,\r\n tokenKeys?: TokenKeys,\r\n targetRealm?: string\r\n ): AccessTokenEntity | null {\r\n const correlationId = request.correlationId;\r\n this.commonLogger.trace(\r\n \"CacheManager - getAccessToken called\",\r\n correlationId\r\n );\r\n const scopes = ScopeSet.createSearchScopes(request.scopes);\r\n const authScheme =\r\n request.authenticationScheme || AuthenticationScheme.BEARER;\r\n /*\r\n * Distinguish between Bearer and PoP/SSH token cache types\r\n * Cast to lowercase to handle \"bearer\" from ADFS\r\n */\r\n const credentialType =\r\n authScheme &&\r\n authScheme.toLowerCase() !==\r\n AuthenticationScheme.BEARER.toLowerCase()\r\n ? CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME\r\n : CredentialType.ACCESS_TOKEN;\r\n\r\n const accessTokenFilter: CredentialFilter = {\r\n homeAccountId: account.homeAccountId,\r\n environment: account.environment,\r\n credentialType: credentialType,\r\n clientId: this.clientId,\r\n realm: targetRealm || account.tenantId,\r\n target: scopes,\r\n tokenType: authScheme,\r\n keyId: request.sshKid,\r\n requestedClaimsHash: request.requestedClaimsHash,\r\n };\r\n\r\n const accessTokenKeys =\r\n (tokenKeys && tokenKeys.accessToken) ||\r\n this.getTokenKeys().accessToken;\r\n const accessTokens: AccessTokenEntity[] = [];\r\n\r\n accessTokenKeys.forEach((key) => {\r\n // Validate key\r\n if (\r\n this.accessTokenKeyMatchesFilter(key, accessTokenFilter, true)\r\n ) {\r\n const accessToken = this.getAccessTokenCredential(\r\n key,\r\n correlationId\r\n );\r\n\r\n // Validate value\r\n if (\r\n accessToken &&\r\n this.credentialMatchesFilter(accessToken, accessTokenFilter)\r\n ) {\r\n accessTokens.push(accessToken);\r\n }\r\n }\r\n });\r\n\r\n const numAccessTokens = accessTokens.length;\r\n if (numAccessTokens < 1) {\r\n this.commonLogger.info(\r\n \"CacheManager:getAccessToken - No token found\",\r\n correlationId\r\n );\r\n return null;\r\n } else if (numAccessTokens > 1) {\r\n this.commonLogger.info(\r\n \"CacheManager:getAccessToken - Multiple access tokens found, clearing them\",\r\n correlationId\r\n );\r\n accessTokens.forEach((accessToken) => {\r\n this.removeAccessToken(\r\n this.generateCredentialKey(accessToken),\r\n correlationId\r\n );\r\n });\r\n this.performanceClient.addFields(\r\n { multiMatchedAT: accessTokens.length },\r\n correlationId\r\n );\r\n return null;\r\n }\r\n\r\n this.commonLogger.info(\r\n \"CacheManager:getAccessToken - Returning access token\",\r\n correlationId\r\n );\r\n return accessTokens[0];\r\n }\r\n\r\n /**\r\n * Validate the cache key against filter before retrieving and parsing cache value\r\n * @param key\r\n * @param filter\r\n * @param keyMustContainAllScopes\r\n * @returns\r\n */\r\n accessTokenKeyMatchesFilter(\r\n inputKey: string,\r\n filter: CredentialFilter,\r\n keyMustContainAllScopes: boolean\r\n ): boolean {\r\n const key = inputKey.toLowerCase();\r\n if (\r\n filter.clientId &&\r\n key.indexOf(filter.clientId.toLowerCase()) === -1\r\n ) {\r\n return false;\r\n }\r\n\r\n if (\r\n filter.homeAccountId &&\r\n key.indexOf(filter.homeAccountId.toLowerCase()) === -1\r\n ) {\r\n return false;\r\n }\r\n\r\n if (filter.realm && key.indexOf(filter.realm.toLowerCase()) === -1) {\r\n return false;\r\n }\r\n\r\n if (\r\n filter.requestedClaimsHash &&\r\n key.indexOf(filter.requestedClaimsHash.toLowerCase()) === -1\r\n ) {\r\n return false;\r\n }\r\n\r\n if (filter.target) {\r\n const scopes = filter.target.asArray();\r\n for (let i = 0; i < scopes.length; i++) {\r\n if (\r\n keyMustContainAllScopes &&\r\n !key.includes(scopes[i].toLowerCase())\r\n ) {\r\n // When performing a cache lookup a missing scope would be a cache miss\r\n return false;\r\n } else if (\r\n !keyMustContainAllScopes &&\r\n key.includes(scopes[i].toLowerCase())\r\n ) {\r\n // When performing a cache write, any token with a subset of requested scopes should be replaced\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Gets all access tokens matching the filter\r\n * @param filter\r\n * @returns\r\n */\r\n getAccessTokensByFilter(\r\n filter: CredentialFilter,\r\n correlationId: string\r\n ): AccessTokenEntity[] {\r\n const tokenKeys = this.getTokenKeys();\r\n\r\n const accessTokens: AccessTokenEntity[] = [];\r\n tokenKeys.accessToken.forEach((key) => {\r\n if (!this.accessTokenKeyMatchesFilter(key, filter, true)) {\r\n return;\r\n }\r\n\r\n const accessToken = this.getAccessTokenCredential(\r\n key,\r\n correlationId\r\n );\r\n if (\r\n accessToken &&\r\n this.credentialMatchesFilter(accessToken, filter)\r\n ) {\r\n accessTokens.push(accessToken);\r\n }\r\n });\r\n\r\n return accessTokens;\r\n }\r\n\r\n /**\r\n * Helper to retrieve the appropriate refresh token from cache\r\n * @param account {AccountInfo}\r\n * @param familyRT {boolean}\r\n * @param correlationId {?string}\r\n * @param tokenKeys {?TokenKeys}\r\n * @param performanceClient {?IPerformanceClient}\r\n */\r\n getRefreshToken(\r\n account: AccountInfo,\r\n familyRT: boolean,\r\n correlationId: string,\r\n tokenKeys?: TokenKeys,\r\n performanceClient?: IPerformanceClient\r\n ): RefreshTokenEntity | null {\r\n this.commonLogger.trace(\"CacheManager - getRefreshToken called\");\r\n const id = familyRT ? THE_FAMILY_ID : undefined;\r\n const refreshTokenFilter: CredentialFilter = {\r\n homeAccountId: account.homeAccountId,\r\n environment: account.environment,\r\n credentialType: CredentialType.REFRESH_TOKEN,\r\n clientId: this.clientId,\r\n familyId: id,\r\n };\r\n\r\n const refreshTokenKeys =\r\n (tokenKeys && tokenKeys.refreshToken) ||\r\n this.getTokenKeys().refreshToken;\r\n const refreshTokens: RefreshTokenEntity[] = [];\r\n\r\n refreshTokenKeys.forEach((key) => {\r\n // Validate key\r\n if (this.refreshTokenKeyMatchesFilter(key, refreshTokenFilter)) {\r\n const refreshToken = this.getRefreshTokenCredential(\r\n key,\r\n correlationId\r\n );\r\n // Validate value\r\n if (\r\n refreshToken &&\r\n this.credentialMatchesFilter(\r\n refreshToken,\r\n refreshTokenFilter\r\n )\r\n ) {\r\n refreshTokens.push(refreshToken);\r\n }\r\n }\r\n });\r\n\r\n const numRefreshTokens = refreshTokens.length;\r\n if (numRefreshTokens < 1) {\r\n this.commonLogger.info(\r\n \"CacheManager:getRefreshToken - No refresh token found.\"\r\n );\r\n return null;\r\n }\r\n // address the else case after remove functions address environment aliases\r\n\r\n if (numRefreshTokens > 1 && performanceClient && correlationId) {\r\n performanceClient.addFields(\r\n { multiMatchedRT: numRefreshTokens },\r\n correlationId\r\n );\r\n }\r\n\r\n this.commonLogger.info(\r\n \"CacheManager:getRefreshToken - returning refresh token\"\r\n );\r\n return refreshTokens[0] as RefreshTokenEntity;\r\n }\r\n\r\n /**\r\n * Validate the cache key against filter before retrieving and parsing cache value\r\n * @param key\r\n * @param filter\r\n */\r\n refreshTokenKeyMatchesFilter(\r\n inputKey: string,\r\n filter: CredentialFilter\r\n ): boolean {\r\n const key = inputKey.toLowerCase();\r\n if (\r\n filter.familyId &&\r\n key.indexOf(filter.familyId.toLowerCase()) === -1\r\n ) {\r\n return false;\r\n }\r\n\r\n // If familyId is used, clientId is not in the key\r\n if (\r\n !filter.familyId &&\r\n filter.clientId &&\r\n key.indexOf(filter.clientId.toLowerCase()) === -1\r\n ) {\r\n return false;\r\n }\r\n\r\n if (\r\n filter.homeAccountId &&\r\n key.indexOf(filter.homeAccountId.toLowerCase()) === -1\r\n ) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Retrieve AppMetadataEntity from cache\r\n */\r\n readAppMetadataFromCache(environment: string): AppMetadataEntity | null {\r\n const appMetadataFilter: AppMetadataFilter = {\r\n environment,\r\n clientId: this.clientId,\r\n };\r\n\r\n const appMetadata: AppMetadataCache =\r\n this.getAppMetadataFilteredBy(appMetadataFilter);\r\n const appMetadataEntries: AppMetadataEntity[] = Object.keys(\r\n appMetadata\r\n ).map((key) => appMetadata[key]);\r\n\r\n const numAppMetadata = appMetadataEntries.length;\r\n if (numAppMetadata < 1) {\r\n return null;\r\n } else if (numAppMetadata > 1) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.multipleMatchingAppMetadata\r\n );\r\n }\r\n\r\n return appMetadataEntries[0] as AppMetadataEntity;\r\n }\r\n\r\n /**\r\n * Return the family_id value associated with FOCI\r\n * @param environment\r\n * @param clientId\r\n */\r\n isAppMetadataFOCI(environment: string): boolean {\r\n const appMetadata = this.readAppMetadataFromCache(environment);\r\n return !!(appMetadata && appMetadata.familyId === THE_FAMILY_ID);\r\n }\r\n\r\n /**\r\n * helper to match account ids\r\n * @param value\r\n * @param homeAccountId\r\n */\r\n private matchHomeAccountId(\r\n entity: AccountEntity | CredentialEntity,\r\n homeAccountId: string\r\n ): boolean {\r\n return !!(\r\n typeof entity.homeAccountId === \"string\" &&\r\n homeAccountId === entity.homeAccountId\r\n );\r\n }\r\n\r\n /**\r\n * helper to match account ids\r\n * @param entity\r\n * @param localAccountId\r\n * @returns\r\n */\r\n private matchLocalAccountIdFromTokenClaims(\r\n tokenClaims: TokenClaims,\r\n localAccountId: string\r\n ): boolean {\r\n const idTokenLocalAccountId = tokenClaims.oid || tokenClaims.sub;\r\n return localAccountId === idTokenLocalAccountId;\r\n }\r\n\r\n private matchLocalAccountIdFromTenantProfile(\r\n tenantProfile: TenantProfile,\r\n localAccountId: string\r\n ): boolean {\r\n return tenantProfile.localAccountId === localAccountId;\r\n }\r\n\r\n /**\r\n * helper to match names\r\n * @param entity\r\n * @param name\r\n * @returns true if the downcased name properties are present and match in the filter and the entity\r\n */\r\n private matchName(claims: TokenClaims, name: string): boolean {\r\n return !!(name.toLowerCase() === claims.name?.toLowerCase());\r\n }\r\n\r\n /**\r\n * helper to match usernames\r\n * @param entity\r\n * @param username\r\n * @returns\r\n */\r\n private matchUsername(\r\n cachedUsername?: string,\r\n filterUsername?: string\r\n ): boolean {\r\n return !!(\r\n cachedUsername &&\r\n typeof cachedUsername === \"string\" &&\r\n filterUsername?.toLowerCase() === cachedUsername.toLowerCase()\r\n );\r\n }\r\n\r\n /**\r\n * helper to match assertion\r\n * @param value\r\n * @param oboAssertion\r\n */\r\n private matchUserAssertionHash(\r\n entity: CredentialEntity,\r\n userAssertionHash: string\r\n ): boolean {\r\n return !!(\r\n entity.userAssertionHash &&\r\n userAssertionHash === entity.userAssertionHash\r\n );\r\n }\r\n\r\n /**\r\n * helper to match environment\r\n * @param value\r\n * @param environment\r\n */\r\n private matchEnvironment(\r\n entity: AccountEntity | CredentialEntity | AppMetadataEntity,\r\n environment: string\r\n ): boolean {\r\n // Check static authority options first for cases where authority metadata has not been resolved and cached yet\r\n if (this.staticAuthorityOptions) {\r\n const staticAliases = getAliasesFromStaticSources(\r\n this.staticAuthorityOptions,\r\n this.commonLogger\r\n );\r\n if (\r\n staticAliases.includes(environment) &&\r\n staticAliases.includes(entity.environment)\r\n ) {\r\n return true;\r\n }\r\n }\r\n\r\n // Query metadata cache if no static authority configuration has aliases that match enviroment\r\n const cloudMetadata = this.getAuthorityMetadataByAlias(environment);\r\n if (\r\n cloudMetadata &&\r\n cloudMetadata.aliases.indexOf(entity.environment) > -1\r\n ) {\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * helper to match credential type\r\n * @param entity\r\n * @param credentialType\r\n */\r\n private matchCredentialType(\r\n entity: CredentialEntity,\r\n credentialType: string\r\n ): boolean {\r\n return (\r\n entity.credentialType &&\r\n credentialType.toLowerCase() === entity.credentialType.toLowerCase()\r\n );\r\n }\r\n\r\n /**\r\n * helper to match client ids\r\n * @param entity\r\n * @param clientId\r\n */\r\n private matchClientId(\r\n entity: CredentialEntity | AppMetadataEntity,\r\n clientId: string\r\n ): boolean {\r\n return !!(entity.clientId && clientId === entity.clientId);\r\n }\r\n\r\n /**\r\n * helper to match family ids\r\n * @param entity\r\n * @param familyId\r\n */\r\n private matchFamilyId(\r\n entity: CredentialEntity | AppMetadataEntity,\r\n familyId: string\r\n ): boolean {\r\n return !!(entity.familyId && familyId === entity.familyId);\r\n }\r\n\r\n /**\r\n * helper to match realm\r\n * @param entity\r\n * @param realm\r\n */\r\n private matchRealm(\r\n entity: AccountEntity | CredentialEntity,\r\n realm: string\r\n ): boolean {\r\n return !!(entity.realm?.toLowerCase() === realm.toLowerCase());\r\n }\r\n\r\n /**\r\n * helper to match nativeAccountId\r\n * @param entity\r\n * @param nativeAccountId\r\n * @returns boolean indicating the match result\r\n */\r\n private matchNativeAccountId(\r\n entity: AccountEntity,\r\n nativeAccountId: string\r\n ): boolean {\r\n return !!(\r\n entity.nativeAccountId && nativeAccountId === entity.nativeAccountId\r\n );\r\n }\r\n\r\n /**\r\n * helper to match loginHint which can be either:\r\n * 1. login_hint ID token claim\r\n * 2. username in cached account object\r\n * 3. upn in ID token claims\r\n * @param entity\r\n * @param loginHint\r\n * @returns\r\n */\r\n private matchLoginHintFromTokenClaims(\r\n tokenClaims: TokenClaims,\r\n loginHint: string\r\n ): boolean {\r\n if (tokenClaims.login_hint === loginHint) {\r\n return true;\r\n }\r\n\r\n if (tokenClaims.preferred_username === loginHint) {\r\n return true;\r\n }\r\n\r\n if (tokenClaims.upn === loginHint) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Helper to match sid\r\n * @param entity\r\n * @param sid\r\n * @returns true if the sid claim is present and matches the filter\r\n */\r\n private matchSid(idTokenClaims: TokenClaims, sid: string): boolean {\r\n return idTokenClaims.sid === sid;\r\n }\r\n\r\n private matchAuthorityType(\r\n entity: AccountEntity,\r\n authorityType: string\r\n ): boolean {\r\n return !!(\r\n entity.authorityType &&\r\n authorityType.toLowerCase() === entity.authorityType.toLowerCase()\r\n );\r\n }\r\n\r\n /**\r\n * Returns true if the target scopes are a subset of the current entity's scopes, false otherwise.\r\n * @param entity\r\n * @param target\r\n */\r\n private matchTarget(entity: CredentialEntity, target: ScopeSet): boolean {\r\n const isNotAccessTokenCredential =\r\n entity.credentialType !== CredentialType.ACCESS_TOKEN &&\r\n entity.credentialType !==\r\n CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME;\r\n\r\n if (isNotAccessTokenCredential || !entity.target) {\r\n return false;\r\n }\r\n\r\n const entityScopeSet: ScopeSet = ScopeSet.fromString(entity.target);\r\n\r\n return entityScopeSet.containsScopeSet(target);\r\n }\r\n\r\n /**\r\n * Returns true if the credential's tokenType or Authentication Scheme matches the one in the request, false otherwise\r\n * @param entity\r\n * @param tokenType\r\n */\r\n private matchTokenType(\r\n entity: CredentialEntity,\r\n tokenType: AuthenticationScheme\r\n ): boolean {\r\n return !!(entity.tokenType && entity.tokenType === tokenType);\r\n }\r\n\r\n /**\r\n * Returns true if the credential's keyId matches the one in the request, false otherwise\r\n * @param entity\r\n * @param keyId\r\n */\r\n private matchKeyId(entity: CredentialEntity, keyId: string): boolean {\r\n return !!(entity.keyId && entity.keyId === keyId);\r\n }\r\n\r\n /**\r\n * returns if a given cache entity is of the type appmetadata\r\n * @param key\r\n */\r\n private isAppMetadata(key: string): boolean {\r\n return key.indexOf(APP_METADATA) !== -1;\r\n }\r\n\r\n /**\r\n * returns if a given cache entity is of the type authoritymetadata\r\n * @param key\r\n */\r\n protected isAuthorityMetadata(key: string): boolean {\r\n return key.indexOf(AUTHORITY_METADATA_CONSTANTS.CACHE_KEY) !== -1;\r\n }\r\n\r\n /**\r\n * returns cache key used for cloud instance metadata\r\n */\r\n generateAuthorityMetadataCacheKey(authority: string): string {\r\n return `${AUTHORITY_METADATA_CONSTANTS.CACHE_KEY}-${this.clientId}-${authority}`;\r\n }\r\n\r\n /**\r\n * Helper to convert serialized data to object\r\n * @param obj\r\n * @param json\r\n */\r\n static toObject(obj: T, json: object): T {\r\n for (const propertyName in json) {\r\n obj[propertyName] = json[propertyName];\r\n }\r\n return obj;\r\n }\r\n}\r\n\r\n/** @internal */\r\nexport class DefaultStorageClass extends CacheManager {\r\n async setAccount(): Promise {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n getAccount(): AccountEntity {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n async setIdTokenCredential(): Promise {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n getIdTokenCredential(): IdTokenEntity {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n async setAccessTokenCredential(): Promise {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n getAccessTokenCredential(): AccessTokenEntity {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n async setRefreshTokenCredential(): Promise {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n getRefreshTokenCredential(): RefreshTokenEntity {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n setAppMetadata(): void {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n getAppMetadata(): AppMetadataEntity {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n setServerTelemetry(): void {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n getServerTelemetry(): ServerTelemetryEntity {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n setAuthorityMetadata(): void {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n getAuthorityMetadata(): AuthorityMetadataEntity | null {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n getAuthorityMetadataKeys(): Array {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n setThrottlingCache(): void {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n getThrottlingCache(): ThrottlingEntity {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n removeItem(): boolean {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n getKeys(): string[] {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n getAccountKeys(): string[] {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n getTokenKeys(): TokenKeys {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n generateCredentialKey(): string {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n generateAccountKey(): string {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n/**\r\n * Protocol modes supported by MSAL.\r\n */\r\nexport const ProtocolMode = {\r\n /**\r\n * Auth Code + PKCE with Entra ID (formerly AAD) specific optimizations and features\r\n */\r\n AAD: \"AAD\",\r\n /**\r\n * Auth Code + PKCE without Entra ID specific optimizations and features. For use only with non-Microsoft owned authorities.\r\n * Support is limited for this mode.\r\n */\r\n OIDC: \"OIDC\",\r\n /**\r\n * Encrypted Authorize Response (EAR) with Entra ID specific optimizations and features\r\n */\r\n EAR: \"EAR\",\r\n} as const;\r\nexport type ProtocolMode = (typeof ProtocolMode)[keyof typeof ProtocolMode];\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n/**\r\n * Enumeration of operations that are instrumented by have their performance measured by the PerformanceClient.\r\n *\r\n * @export\r\n * @enum {number}\r\n */\r\nexport const PerformanceEvents = {\r\n /**\r\n * acquireTokenByCode API (msal-browser and msal-node).\r\n * Used to acquire tokens by trading an authorization code against the token endpoint.\r\n */\r\n AcquireTokenByCode: \"acquireTokenByCode\",\r\n\r\n /**\r\n * acquireTokenByRefreshToken API (msal-browser and msal-node).\r\n * Used to renew an access token using a refresh token against the token endpoint.\r\n */\r\n AcquireTokenByRefreshToken: \"acquireTokenByRefreshToken\",\r\n\r\n /**\r\n * acquireTokenSilent API (msal-browser and msal-node).\r\n * Used to silently acquire a new access token (from the cache or the network).\r\n */\r\n AcquireTokenSilent: \"acquireTokenSilent\",\r\n\r\n /**\r\n * acquireTokenSilentAsync (msal-browser).\r\n * Internal API for acquireTokenSilent.\r\n */\r\n AcquireTokenSilentAsync: \"acquireTokenSilentAsync\",\r\n\r\n /**\r\n * acquireTokenPopup (msal-browser).\r\n * Used to acquire a new access token interactively through pop ups\r\n */\r\n AcquireTokenPopup: \"acquireTokenPopup\",\r\n\r\n /**\r\n * acquireTokenPreRedirect (msal-browser).\r\n * First part of the redirect flow.\r\n * Used to acquire a new access token interactively through redirects.\r\n */\r\n AcquireTokenPreRedirect: \"acquireTokenPreRedirect\",\r\n\r\n /**\r\n * acquireTokenRedirect (msal-browser).\r\n * Second part of the redirect flow.\r\n * Used to acquire a new access token interactively through redirects.\r\n */\r\n AcquireTokenRedirect: \"acquireTokenRedirect\",\r\n\r\n /**\r\n * getPublicKeyThumbprint API in CryptoOpts class (msal-browser).\r\n * Used to generate a public/private keypair and generate a public key thumbprint for pop requests.\r\n */\r\n CryptoOptsGetPublicKeyThumbprint: \"cryptoOptsGetPublicKeyThumbprint\",\r\n\r\n /**\r\n * signJwt API in CryptoOpts class (msal-browser).\r\n * Used to signed a pop token.\r\n */\r\n CryptoOptsSignJwt: \"cryptoOptsSignJwt\",\r\n\r\n /**\r\n * acquireToken API in the SilentCacheClient class (msal-browser).\r\n * Used to read access tokens from the cache.\r\n */\r\n SilentCacheClientAcquireToken: \"silentCacheClientAcquireToken\",\r\n\r\n /**\r\n * acquireToken API in the SilentIframeClient class (msal-browser).\r\n * Used to acquire a new set of tokens from the authorize endpoint in a hidden iframe.\r\n */\r\n SilentIframeClientAcquireToken: \"silentIframeClientAcquireToken\",\r\n AwaitConcurrentIframe: \"awaitConcurrentIframe\", // Time spent waiting for a concurrent iframe to complete\r\n\r\n /**\r\n * acquireToken API in SilentRereshClient (msal-browser).\r\n * Used to acquire a new set of tokens from the token endpoint using a refresh token.\r\n */\r\n SilentRefreshClientAcquireToken: \"silentRefreshClientAcquireToken\",\r\n\r\n /**\r\n * ssoSilent API (msal-browser).\r\n * Used to silently acquire an authorization code and set of tokens using a hidden iframe.\r\n */\r\n SsoSilent: \"ssoSilent\",\r\n\r\n /**\r\n * getDiscoveredAuthority API in StandardInteractionClient class (msal-browser).\r\n * Used to load authority metadata for a request.\r\n */\r\n StandardInteractionClientGetDiscoveredAuthority:\r\n \"standardInteractionClientGetDiscoveredAuthority\",\r\n\r\n /**\r\n * acquireToken APIs in msal-browser.\r\n * Used to make an /authorize endpoint call with native brokering enabled.\r\n */\r\n FetchAccountIdWithNativeBroker: \"fetchAccountIdWithNativeBroker\",\r\n\r\n /**\r\n * acquireToken API in NativeInteractionClient class (msal-browser).\r\n * Used to acquire a token from Native component when native brokering is enabled.\r\n */\r\n NativeInteractionClientAcquireToken: \"nativeInteractionClientAcquireToken\",\r\n /**\r\n * Time spent creating default headers for requests to token endpoint\r\n */\r\n BaseClientCreateTokenRequestHeaders: \"baseClientCreateTokenRequestHeaders\",\r\n /**\r\n * Time spent sending/waiting for the response of a request to the token endpoint\r\n */\r\n NetworkClientSendPostRequestAsync: \"networkClientSendPostRequestAsync\",\r\n RefreshTokenClientExecutePostToTokenEndpoint:\r\n \"refreshTokenClientExecutePostToTokenEndpoint\",\r\n AuthorizationCodeClientExecutePostToTokenEndpoint:\r\n \"authorizationCodeClientExecutePostToTokenEndpoint\",\r\n /**\r\n * Used to measure the time taken for completing embedded-broker handshake (PW-Broker).\r\n */\r\n BrokerHandhshake: \"brokerHandshake\",\r\n /**\r\n * acquireTokenByRefreshToken API in BrokerClientApplication (PW-Broker) .\r\n */\r\n AcquireTokenByRefreshTokenInBroker: \"acquireTokenByRefreshTokenInBroker\",\r\n /**\r\n * Time taken for token acquisition by broker\r\n */\r\n AcquireTokenByBroker: \"acquireTokenByBroker\",\r\n\r\n /**\r\n * Time spent on the network for refresh token acquisition\r\n */\r\n RefreshTokenClientExecuteTokenRequest:\r\n \"refreshTokenClientExecuteTokenRequest\",\r\n\r\n /**\r\n * Time taken for acquiring refresh token , records RT size\r\n */\r\n RefreshTokenClientAcquireToken: \"refreshTokenClientAcquireToken\",\r\n\r\n /**\r\n * Time taken for acquiring cached refresh token\r\n */\r\n RefreshTokenClientAcquireTokenWithCachedRefreshToken:\r\n \"refreshTokenClientAcquireTokenWithCachedRefreshToken\",\r\n\r\n /**\r\n * acquireTokenByRefreshToken API in RefreshTokenClient (msal-common).\r\n */\r\n RefreshTokenClientAcquireTokenByRefreshToken:\r\n \"refreshTokenClientAcquireTokenByRefreshToken\",\r\n\r\n /**\r\n * Helper function to create token request body in RefreshTokenClient (msal-common).\r\n */\r\n RefreshTokenClientCreateTokenRequestBody:\r\n \"refreshTokenClientCreateTokenRequestBody\",\r\n\r\n /**\r\n * acquireTokenFromCache (msal-browser).\r\n * Internal API for acquiring token from cache\r\n */\r\n AcquireTokenFromCache: \"acquireTokenFromCache\",\r\n SilentFlowClientAcquireCachedToken: \"silentFlowClientAcquireCachedToken\",\r\n SilentFlowClientGenerateResultFromCacheRecord:\r\n \"silentFlowClientGenerateResultFromCacheRecord\",\r\n\r\n /**\r\n * acquireTokenBySilentIframe (msal-browser).\r\n * Internal API for acquiring token by silent Iframe\r\n */\r\n AcquireTokenBySilentIframe: \"acquireTokenBySilentIframe\",\r\n\r\n /**\r\n * Internal API for initializing base request in BaseInteractionClient (msal-browser)\r\n */\r\n InitializeBaseRequest: \"initializeBaseRequest\",\r\n\r\n /**\r\n * Internal API for initializing silent request in SilentCacheClient (msal-browser)\r\n */\r\n InitializeSilentRequest: \"initializeSilentRequest\",\r\n\r\n InitializeClientApplication: \"initializeClientApplication\",\r\n\r\n InitializeCache: \"initializeCache\",\r\n\r\n /**\r\n * Helper function in SilentIframeClient class (msal-browser).\r\n */\r\n SilentIframeClientTokenHelper: \"silentIframeClientTokenHelper\",\r\n\r\n /**\r\n * SilentHandler\r\n */\r\n SilentHandlerInitiateAuthRequest: \"silentHandlerInitiateAuthRequest\",\r\n SilentHandlerMonitorIframeForHash: \"silentHandlerMonitorIframeForHash\",\r\n SilentHandlerLoadFrame: \"silentHandlerLoadFrame\",\r\n SilentHandlerLoadFrameSync: \"silentHandlerLoadFrameSync\",\r\n\r\n /**\r\n * Helper functions in StandardInteractionClient class (msal-browser)\r\n */\r\n StandardInteractionClientCreateAuthCodeClient:\r\n \"standardInteractionClientCreateAuthCodeClient\",\r\n StandardInteractionClientGetClientConfiguration:\r\n \"standardInteractionClientGetClientConfiguration\",\r\n StandardInteractionClientInitializeAuthorizationRequest:\r\n \"standardInteractionClientInitializeAuthorizationRequest\",\r\n\r\n /**\r\n * getAuthCodeUrl API (msal-browser and msal-node).\r\n */\r\n GetAuthCodeUrl: \"getAuthCodeUrl\",\r\n GetStandardParams: \"getStandardParams\",\r\n\r\n /**\r\n * Functions from InteractionHandler (msal-browser)\r\n */\r\n HandleCodeResponseFromServer: \"handleCodeResponseFromServer\",\r\n HandleCodeResponse: \"handleCodeResponse\",\r\n HandleResponseEar: \"handleResponseEar\",\r\n HandleResponsePlatformBroker: \"handleResponsePlatformBroker\",\r\n HandleResponseCode: \"handleResponseCode\",\r\n UpdateTokenEndpointAuthority: \"updateTokenEndpointAuthority\",\r\n\r\n /**\r\n * APIs in Authorization Code Client (msal-common)\r\n */\r\n AuthClientAcquireToken: \"authClientAcquireToken\",\r\n AuthClientExecuteTokenRequest: \"authClientExecuteTokenRequest\",\r\n AuthClientCreateTokenRequestBody: \"authClientCreateTokenRequestBody\",\r\n\r\n /**\r\n * Generate functions in PopTokenGenerator (msal-common)\r\n */\r\n PopTokenGenerateCnf: \"popTokenGenerateCnf\",\r\n PopTokenGenerateKid: \"popTokenGenerateKid\",\r\n\r\n /**\r\n * handleServerTokenResponse API in ResponseHandler (msal-common)\r\n */\r\n HandleServerTokenResponse: \"handleServerTokenResponse\",\r\n DeserializeResponse: \"deserializeResponse\",\r\n\r\n /**\r\n * Authority functions\r\n */\r\n AuthorityFactoryCreateDiscoveredInstance:\r\n \"authorityFactoryCreateDiscoveredInstance\",\r\n AuthorityResolveEndpointsAsync: \"authorityResolveEndpointsAsync\",\r\n AuthorityResolveEndpointsFromLocalSources:\r\n \"authorityResolveEndpointsFromLocalSources\",\r\n AuthorityGetCloudDiscoveryMetadataFromNetwork:\r\n \"authorityGetCloudDiscoveryMetadataFromNetwork\",\r\n AuthorityUpdateCloudDiscoveryMetadata:\r\n \"authorityUpdateCloudDiscoveryMetadata\",\r\n AuthorityGetEndpointMetadataFromNetwork:\r\n \"authorityGetEndpointMetadataFromNetwork\",\r\n AuthorityUpdateEndpointMetadata: \"authorityUpdateEndpointMetadata\",\r\n AuthorityUpdateMetadataWithRegionalInformation:\r\n \"authorityUpdateMetadataWithRegionalInformation\",\r\n\r\n /**\r\n * Region Discovery functions\r\n */\r\n RegionDiscoveryDetectRegion: \"regionDiscoveryDetectRegion\",\r\n RegionDiscoveryGetRegionFromIMDS: \"regionDiscoveryGetRegionFromIMDS\",\r\n RegionDiscoveryGetCurrentVersion: \"regionDiscoveryGetCurrentVersion\",\r\n\r\n AcquireTokenByCodeAsync: \"acquireTokenByCodeAsync\",\r\n\r\n GetEndpointMetadataFromNetwork: \"getEndpointMetadataFromNetwork\",\r\n GetCloudDiscoveryMetadataFromNetworkMeasurement:\r\n \"getCloudDiscoveryMetadataFromNetworkMeasurement\",\r\n\r\n HandleRedirectPromiseMeasurement: \"handleRedirectPromise\",\r\n HandleNativeRedirectPromiseMeasurement: \"handleNativeRedirectPromise\",\r\n\r\n UpdateCloudDiscoveryMetadataMeasurement:\r\n \"updateCloudDiscoveryMetadataMeasurement\",\r\n\r\n UsernamePasswordClientAcquireToken: \"usernamePasswordClientAcquireToken\",\r\n\r\n NativeMessageHandlerHandshake: \"nativeMessageHandlerHandshake\",\r\n\r\n NativeGenerateAuthResult: \"nativeGenerateAuthResult\",\r\n\r\n RemoveHiddenIframe: \"removeHiddenIframe\",\r\n\r\n /**\r\n * Cache operations\r\n */\r\n ClearTokensAndKeysWithClaims: \"clearTokensAndKeysWithClaims\",\r\n CacheManagerGetRefreshToken: \"cacheManagerGetRefreshToken\",\r\n ImportExistingCache: \"importExistingCache\",\r\n SetUserData: \"setUserData\",\r\n LocalStorageUpdated: \"localStorageUpdated\",\r\n\r\n /**\r\n * Crypto Operations\r\n */\r\n GeneratePkceCodes: \"generatePkceCodes\",\r\n GenerateCodeVerifier: \"generateCodeVerifier\",\r\n GenerateCodeChallengeFromVerifier: \"generateCodeChallengeFromVerifier\",\r\n Sha256Digest: \"sha256Digest\",\r\n GetRandomValues: \"getRandomValues\",\r\n GenerateHKDF: \"generateHKDF\",\r\n GenerateBaseKey: \"generateBaseKey\",\r\n Base64Decode: \"base64Decode\",\r\n UrlEncodeArr: \"urlEncodeArr\",\r\n Encrypt: \"encrypt\",\r\n Decrypt: \"decrypt\",\r\n GenerateEarKey: \"generateEarKey\",\r\n DecryptEarResponse: \"decryptEarResponse\",\r\n} as const;\r\nexport type PerformanceEvents =\r\n (typeof PerformanceEvents)[keyof typeof PerformanceEvents];\r\n\r\nexport const PerformanceEventAbbreviations: ReadonlyMap =\r\n new Map([\r\n [PerformanceEvents.AcquireTokenByCode, \"ATByCode\"],\r\n [PerformanceEvents.AcquireTokenByRefreshToken, \"ATByRT\"],\r\n [PerformanceEvents.AcquireTokenSilent, \"ATS\"],\r\n [PerformanceEvents.AcquireTokenSilentAsync, \"ATSAsync\"],\r\n [PerformanceEvents.AcquireTokenPopup, \"ATPopup\"],\r\n [PerformanceEvents.AcquireTokenRedirect, \"ATRedirect\"],\r\n [\r\n PerformanceEvents.CryptoOptsGetPublicKeyThumbprint,\r\n \"CryptoGetPKThumb\",\r\n ],\r\n [PerformanceEvents.CryptoOptsSignJwt, \"CryptoSignJwt\"],\r\n [PerformanceEvents.SilentCacheClientAcquireToken, \"SltCacheClientAT\"],\r\n [PerformanceEvents.SilentIframeClientAcquireToken, \"SltIframeClientAT\"],\r\n [PerformanceEvents.SilentRefreshClientAcquireToken, \"SltRClientAT\"],\r\n [PerformanceEvents.SsoSilent, \"SsoSlt\"],\r\n [\r\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\r\n \"StdIntClientGetDiscAuth\",\r\n ],\r\n [\r\n PerformanceEvents.FetchAccountIdWithNativeBroker,\r\n \"FetchAccIdWithNtvBroker\",\r\n ],\r\n [\r\n PerformanceEvents.NativeInteractionClientAcquireToken,\r\n \"NtvIntClientAT\",\r\n ],\r\n [\r\n PerformanceEvents.BaseClientCreateTokenRequestHeaders,\r\n \"BaseClientCreateTReqHead\",\r\n ],\r\n [\r\n PerformanceEvents.NetworkClientSendPostRequestAsync,\r\n \"NetClientSendPost\",\r\n ],\r\n [\r\n PerformanceEvents.RefreshTokenClientExecutePostToTokenEndpoint,\r\n \"RTClientExecPost\",\r\n ],\r\n [\r\n PerformanceEvents.AuthorizationCodeClientExecutePostToTokenEndpoint,\r\n \"AuthCodeClientExecPost\",\r\n ],\r\n [PerformanceEvents.BrokerHandhshake, \"BrokerHandshake\"],\r\n [\r\n PerformanceEvents.AcquireTokenByRefreshTokenInBroker,\r\n \"ATByRTInBroker\",\r\n ],\r\n [PerformanceEvents.AcquireTokenByBroker, \"ATByBroker\"],\r\n [\r\n PerformanceEvents.RefreshTokenClientExecuteTokenRequest,\r\n \"RTClientExecTReq\",\r\n ],\r\n [PerformanceEvents.RefreshTokenClientAcquireToken, \"RTClientAT\"],\r\n [\r\n PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken,\r\n \"RTClientATWithCachedRT\",\r\n ],\r\n [\r\n PerformanceEvents.RefreshTokenClientAcquireTokenByRefreshToken,\r\n \"RTClientATByRT\",\r\n ],\r\n [\r\n PerformanceEvents.RefreshTokenClientCreateTokenRequestBody,\r\n \"RTClientCreateTReqBody\",\r\n ],\r\n [PerformanceEvents.AcquireTokenFromCache, \"ATFromCache\"],\r\n [\r\n PerformanceEvents.SilentFlowClientAcquireCachedToken,\r\n \"SltFlowClientATCached\",\r\n ],\r\n [\r\n PerformanceEvents.SilentFlowClientGenerateResultFromCacheRecord,\r\n \"SltFlowClientGenResFromCache\",\r\n ],\r\n [PerformanceEvents.AcquireTokenBySilentIframe, \"ATBySltIframe\"],\r\n [PerformanceEvents.InitializeBaseRequest, \"InitBaseReq\"],\r\n [PerformanceEvents.InitializeSilentRequest, \"InitSltReq\"],\r\n [\r\n PerformanceEvents.InitializeClientApplication,\r\n \"InitClientApplication\",\r\n ],\r\n [PerformanceEvents.InitializeCache, \"InitCache\"],\r\n [PerformanceEvents.ImportExistingCache, \"importCache\"],\r\n [PerformanceEvents.SetUserData, \"setUserData\"],\r\n [PerformanceEvents.LocalStorageUpdated, \"localStorageUpdated\"],\r\n [PerformanceEvents.SilentIframeClientTokenHelper, \"SIClientTHelper\"],\r\n [\r\n PerformanceEvents.SilentHandlerInitiateAuthRequest,\r\n \"SHandlerInitAuthReq\",\r\n ],\r\n [\r\n PerformanceEvents.SilentHandlerMonitorIframeForHash,\r\n \"SltHandlerMonitorIframeForHash\",\r\n ],\r\n [PerformanceEvents.SilentHandlerLoadFrame, \"SHandlerLoadFrame\"],\r\n [PerformanceEvents.SilentHandlerLoadFrameSync, \"SHandlerLoadFrameSync\"],\r\n\r\n [\r\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\r\n \"StdIntClientCreateAuthCodeClient\",\r\n ],\r\n [\r\n PerformanceEvents.StandardInteractionClientGetClientConfiguration,\r\n \"StdIntClientGetClientConf\",\r\n ],\r\n [\r\n PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,\r\n \"StdIntClientInitAuthReq\",\r\n ],\r\n\r\n [PerformanceEvents.GetAuthCodeUrl, \"GetAuthCodeUrl\"],\r\n\r\n [\r\n PerformanceEvents.HandleCodeResponseFromServer,\r\n \"HandleCodeResFromServer\",\r\n ],\r\n [PerformanceEvents.HandleCodeResponse, \"HandleCodeResp\"],\r\n [PerformanceEvents.HandleResponseEar, \"HandleRespEar\"],\r\n [PerformanceEvents.HandleResponseCode, \"HandleRespCode\"],\r\n [\r\n PerformanceEvents.HandleResponsePlatformBroker,\r\n \"HandleRespPlatBroker\",\r\n ],\r\n [PerformanceEvents.UpdateTokenEndpointAuthority, \"UpdTEndpointAuth\"],\r\n\r\n [PerformanceEvents.AuthClientAcquireToken, \"AuthClientAT\"],\r\n [PerformanceEvents.AuthClientExecuteTokenRequest, \"AuthClientExecTReq\"],\r\n [\r\n PerformanceEvents.AuthClientCreateTokenRequestBody,\r\n \"AuthClientCreateTReqBody\",\r\n ],\r\n [PerformanceEvents.PopTokenGenerateCnf, \"PopTGenCnf\"],\r\n [PerformanceEvents.PopTokenGenerateKid, \"PopTGenKid\"],\r\n [PerformanceEvents.HandleServerTokenResponse, \"HandleServerTRes\"],\r\n [PerformanceEvents.DeserializeResponse, \"DeserializeRes\"],\r\n [\r\n PerformanceEvents.AuthorityFactoryCreateDiscoveredInstance,\r\n \"AuthFactCreateDiscInst\",\r\n ],\r\n [\r\n PerformanceEvents.AuthorityResolveEndpointsAsync,\r\n \"AuthResolveEndpointsAsync\",\r\n ],\r\n [\r\n PerformanceEvents.AuthorityResolveEndpointsFromLocalSources,\r\n \"AuthResolveEndpointsFromLocal\",\r\n ],\r\n [\r\n PerformanceEvents.AuthorityGetCloudDiscoveryMetadataFromNetwork,\r\n \"AuthGetCDMetaFromNet\",\r\n ],\r\n [\r\n PerformanceEvents.AuthorityUpdateCloudDiscoveryMetadata,\r\n \"AuthUpdCDMeta\",\r\n ],\r\n [\r\n PerformanceEvents.AuthorityGetEndpointMetadataFromNetwork,\r\n \"AuthUpdCDMetaFromNet\",\r\n ],\r\n [\r\n PerformanceEvents.AuthorityUpdateEndpointMetadata,\r\n \"AuthUpdEndpointMeta\",\r\n ],\r\n [\r\n PerformanceEvents.AuthorityUpdateMetadataWithRegionalInformation,\r\n \"AuthUpdMetaWithRegInfo\",\r\n ],\r\n [PerformanceEvents.RegionDiscoveryDetectRegion, \"RegDiscDetectReg\"],\r\n [\r\n PerformanceEvents.RegionDiscoveryGetRegionFromIMDS,\r\n \"RegDiscGetRegFromIMDS\",\r\n ],\r\n [\r\n PerformanceEvents.RegionDiscoveryGetCurrentVersion,\r\n \"RegDiscGetCurrentVer\",\r\n ],\r\n [PerformanceEvents.AcquireTokenByCodeAsync, \"ATByCodeAsync\"],\r\n [\r\n PerformanceEvents.GetEndpointMetadataFromNetwork,\r\n \"GetEndpointMetaFromNet\",\r\n ],\r\n [\r\n PerformanceEvents.GetCloudDiscoveryMetadataFromNetworkMeasurement,\r\n \"GetCDMetaFromNet\",\r\n ],\r\n [\r\n PerformanceEvents.HandleRedirectPromiseMeasurement,\r\n \"HandleRedirectPromise\",\r\n ],\r\n [\r\n PerformanceEvents.HandleNativeRedirectPromiseMeasurement,\r\n \"HandleNtvRedirectPromise\",\r\n ],\r\n [\r\n PerformanceEvents.UpdateCloudDiscoveryMetadataMeasurement,\r\n \"UpdateCDMeta\",\r\n ],\r\n [\r\n PerformanceEvents.UsernamePasswordClientAcquireToken,\r\n \"UserPassClientAT\",\r\n ],\r\n [\r\n PerformanceEvents.NativeMessageHandlerHandshake,\r\n \"NtvMsgHandlerHandshake\",\r\n ],\r\n [PerformanceEvents.NativeGenerateAuthResult, \"NtvGenAuthRes\"],\r\n [PerformanceEvents.RemoveHiddenIframe, \"RemoveHiddenIframe\"],\r\n [\r\n PerformanceEvents.ClearTokensAndKeysWithClaims,\r\n \"ClearTAndKeysWithClaims\",\r\n ],\r\n [PerformanceEvents.CacheManagerGetRefreshToken, \"CacheManagerGetRT\"],\r\n [PerformanceEvents.GeneratePkceCodes, \"GenPkceCodes\"],\r\n [PerformanceEvents.GenerateCodeVerifier, \"GenCodeVerifier\"],\r\n [\r\n PerformanceEvents.GenerateCodeChallengeFromVerifier,\r\n \"GenCodeChallengeFromVerifier\",\r\n ],\r\n [PerformanceEvents.Sha256Digest, \"Sha256Digest\"],\r\n [PerformanceEvents.GetRandomValues, \"GetRandomValues\"],\r\n [PerformanceEvents.GenerateHKDF, \"genHKDF\"],\r\n [PerformanceEvents.GenerateBaseKey, \"genBaseKey\"],\r\n [PerformanceEvents.Base64Decode, \"b64Decode\"],\r\n [PerformanceEvents.UrlEncodeArr, \"urlEncArr\"],\r\n [PerformanceEvents.Encrypt, \"encrypt\"],\r\n [PerformanceEvents.Decrypt, \"decrypt\"],\r\n [PerformanceEvents.GenerateEarKey, \"genEarKey\"],\r\n [PerformanceEvents.DecryptEarResponse, \"decryptEarResp\"],\r\n ]);\r\n\r\n/**\r\n * State of the performance event.\r\n *\r\n * @export\r\n * @enum {number}\r\n */\r\nexport const PerformanceEventStatus = {\r\n NotStarted: 0,\r\n InProgress: 1,\r\n Completed: 2,\r\n} as const;\r\nexport type PerformanceEventStatus =\r\n (typeof PerformanceEventStatus)[keyof typeof PerformanceEventStatus];\r\n\r\nexport type SubMeasurement = {\r\n name: string;\r\n startTimeMs: number;\r\n};\r\n\r\n/**\r\n * Performance measurement taken by the library, including metadata about the request and application.\r\n *\r\n * @export\r\n * @typedef {PerformanceEvent}\r\n */\r\nexport type PerformanceEvent = {\r\n /**\r\n * Unique id for the event\r\n *\r\n * @type {string}\r\n */\r\n eventId: string;\r\n\r\n /**\r\n * State of the perforance measure.\r\n *\r\n * @type {PerformanceEventStatus}\r\n */\r\n status: PerformanceEventStatus;\r\n\r\n /**\r\n * Login authority used for the request\r\n *\r\n * @type {string}\r\n */\r\n authority: string;\r\n\r\n /**\r\n * Client id for the application\r\n *\r\n * @type {string}\r\n */\r\n clientId: string;\r\n\r\n /**\r\n * Correlation ID used for the request\r\n *\r\n * @type {string}\r\n */\r\n correlationId: string;\r\n\r\n /**\r\n * End-to-end duration in milliseconds.\r\n * @date 3/22/2022 - 3:40:05 PM\r\n *\r\n * @type {number}\r\n */\r\n durationMs?: number;\r\n\r\n /**\r\n * Visibility of the page when the event completed.\r\n * Read from: https://developer.mozilla.org/docs/Web/API/Page_Visibility_API\r\n *\r\n * @type {?(string | null)}\r\n */\r\n endPageVisibility?: string | null;\r\n\r\n /**\r\n * Whether the result was retrieved from the cache.\r\n *\r\n * @type {(boolean | null)}\r\n */\r\n fromCache?: boolean | null;\r\n\r\n /**\r\n * Event name (usually in the form of classNameFunctionName)\r\n *\r\n * @type {string}\r\n */\r\n name: string;\r\n\r\n /**\r\n * Visibility of the page when the event completed.\r\n * Read from: https://developer.mozilla.org/docs/Web/API/Page_Visibility_API\r\n *\r\n * @type {?(string | null)}\r\n */\r\n startPageVisibility?: string | null;\r\n\r\n /**\r\n * Unix millisecond timestamp when the event was initiated.\r\n *\r\n * @type {number}\r\n */\r\n startTimeMs: number;\r\n\r\n /**\r\n * Whether or the operation completed successfully.\r\n *\r\n * @type {(boolean | null)}\r\n */\r\n success?: boolean | null;\r\n\r\n /**\r\n * Add specific error code in case of failure\r\n *\r\n * @type {string}\r\n */\r\n errorCode?: string;\r\n\r\n /**\r\n * Add specific sub error code in case of failure\r\n *\r\n * @type {string}\r\n */\r\n subErrorCode?: string;\r\n\r\n /**\r\n * Server error number\r\n */\r\n serverErrorNo?: string;\r\n\r\n /**\r\n * Name of the library used for the operation.\r\n *\r\n * @type {string}\r\n */\r\n libraryName: string;\r\n\r\n /**\r\n * Version of the library used for the operation.\r\n *\r\n * @type {string}\r\n */\r\n libraryVersion: string;\r\n\r\n /**\r\n * Version of the library used last. Used to track upgrades and downgrades\r\n */\r\n previousLibraryVersion?: string;\r\n\r\n /**\r\n * Whether the response is from a native component (e.g., WAM)\r\n *\r\n * @type {?boolean}\r\n */\r\n isNativeBroker?: boolean;\r\n\r\n /**\r\n * Platform-specific fields, when calling STS and/or broker for token requests\r\n */\r\n isPlatformAuthorizeRequest?: boolean;\r\n isPlatformBrokerRequest?: boolean;\r\n brokerErrorName?: string;\r\n brokerErrorCode?: string;\r\n\r\n /**\r\n * Request ID returned from the response\r\n *\r\n * @type {?string}\r\n */\r\n requestId?: string;\r\n\r\n /**\r\n * Cache lookup policy\r\n *\r\n * @type {?number}\r\n */\r\n cacheLookupPolicy?: number | undefined;\r\n\r\n /**\r\n * Cache Outcome\r\n * @type {?number}\r\n */\r\n cacheOutcome?: number;\r\n\r\n /**\r\n * Amount of time spent in the JS queue in milliseconds.\r\n *\r\n * @type {?number}\r\n */\r\n queuedTimeMs?: number;\r\n\r\n /**\r\n * Sub-measurements for internal use. To be deleted before flushing.\r\n */\r\n incompleteSubMeasurements?: Map;\r\n\r\n visibilityChangeCount?: number;\r\n incompleteSubsCount?: number;\r\n\r\n /**\r\n * CorrelationId of the in progress iframe request that was awaited\r\n */\r\n awaitIframeCorrelationId?: string;\r\n /**\r\n * Amount of times queued in the JS event queue.\r\n *\r\n * @type {?number}\r\n */\r\n queuedCount?: number;\r\n /**\r\n * Amount of manually completed queue events.\r\n *\r\n * @type {?number}\r\n */\r\n queuedManuallyCompletedCount?: number;\r\n\r\n /**\r\n * Size of the id token\r\n *\r\n * @type {number}\r\n */\r\n idTokenSize?: number;\r\n\r\n /**\r\n *\r\n * Size of the access token\r\n *\r\n * @type {number}\r\n */\r\n\r\n accessTokenSize?: number;\r\n\r\n /**\r\n *\r\n * Size of the refresh token\r\n *\r\n * @type {number}\r\n */\r\n\r\n refreshTokenSize?: number | undefined;\r\n\r\n /**\r\n * Application name as specified by the app.\r\n *\r\n * @type {?string}\r\n */\r\n appName?: string;\r\n\r\n /**\r\n * Application version as specified by the app.\r\n *\r\n * @type {?string}\r\n */\r\n appVersion?: string;\r\n\r\n /**\r\n * The following are fields that may be emitted in native broker scenarios\r\n */\r\n extensionId?: string;\r\n extensionVersion?: string;\r\n matsBrokerVersion?: string;\r\n matsAccountJoinOnStart?: string;\r\n matsAccountJoinOnEnd?: string;\r\n matsDeviceJoin?: string;\r\n matsPromptBehavior?: string;\r\n matsApiErrorCode?: number;\r\n matsUiVisible?: boolean;\r\n matsSilentCode?: number;\r\n matsSilentBiSubCode?: number;\r\n matsSilentMessage?: string;\r\n matsSilentStatus?: number;\r\n matsHttpStatus?: number;\r\n matsHttpEventCount?: number;\r\n\r\n /**\r\n * Http POST metadata\r\n */\r\n httpVerToken?: string;\r\n httpStatus?: number;\r\n contentTypeHeader?: string;\r\n contentLengthHeader?: string;\r\n\r\n /**\r\n * Platform broker fields\r\n */\r\n allowPlatformBroker?: boolean;\r\n extensionInstalled?: boolean;\r\n extensionHandshakeTimeoutMs?: number;\r\n extensionHandshakeTimedOut?: boolean;\r\n\r\n /**\r\n * Nested App Auth Fields\r\n */\r\n nestedAppAuthRequest?: boolean;\r\n\r\n /**\r\n * Multiple matched access/id/refresh tokens in the cache\r\n */\r\n multiMatchedAT?: number;\r\n multiMatchedID?: number;\r\n multiMatchedRT?: number;\r\n\r\n errorName?: string;\r\n errorStack?: string[];\r\n\r\n // Event context as JSON string\r\n context?: string;\r\n\r\n // Cache Data\r\n cacheLocation?: string;\r\n cacheRetentionDays?: number;\r\n\r\n // Number of tokens in the cache to be reported when cache quota is exceeded\r\n cacheRtCount?: number;\r\n cacheIdCount?: number;\r\n cacheAtCount?: number;\r\n\r\n // Scenario id to track custom user prompts\r\n scenarioId?: string;\r\n\r\n accountType?: \"AAD\" | \"MSA\" | \"B2C\";\r\n\r\n /**\r\n * Server error that triggers a request retry\r\n *\r\n * @type {string}\r\n */\r\n retryError?: string;\r\n\r\n embeddedClientId?: string;\r\n embeddedRedirectUri?: string;\r\n\r\n isAsyncPopup?: boolean;\r\n\r\n rtExpiresOnMs?: number;\r\n\r\n sidFromClaims?: boolean;\r\n sidFromRequest?: boolean;\r\n loginHintFromRequest?: boolean;\r\n loginHintFromUpn?: boolean;\r\n loginHintFromClaim?: boolean;\r\n domainHintFromRequest?: boolean;\r\n\r\n prompt?: string;\r\n\r\n usePreGeneratedPkce?: boolean;\r\n\r\n // Number of MSAL JS instances in the frame\r\n msalInstanceCount?: number;\r\n // Number of MSAL JS instances using the same client id in the frame\r\n sameClientIdInstanceCount?: number;\r\n\r\n navigateCallbackResult?: boolean;\r\n};\r\n\r\nexport type PerformanceEventContext = {\r\n dur?: number;\r\n err?: string;\r\n subErr?: string;\r\n fail?: number;\r\n};\r\n\r\nexport type PerformanceEventStackedContext = PerformanceEventContext & {\r\n name?: string;\r\n childErr?: string;\r\n};\r\n\r\nexport const IntFields: ReadonlySet = new Set([\r\n \"accessTokenSize\",\r\n \"durationMs\",\r\n \"idTokenSize\",\r\n \"matsSilentStatus\",\r\n \"matsHttpStatus\",\r\n \"refreshTokenSize\",\r\n \"queuedTimeMs\",\r\n \"startTimeMs\",\r\n \"status\",\r\n \"multiMatchedAT\",\r\n \"multiMatchedID\",\r\n \"multiMatchedRT\",\r\n \"unencryptedCacheCount\",\r\n \"encryptedCacheExpiredCount\",\r\n \"oldAccountCount\",\r\n \"oldAccessCount\",\r\n \"oldIdCount\",\r\n \"oldRefreshCount\",\r\n \"currAccountCount\",\r\n \"currAccessCount\",\r\n \"currIdCount\",\r\n \"currRefreshCount\",\r\n \"expiredCacheRemovedCount\",\r\n \"upgradedCacheCount\",\r\n]);\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n IPerformanceClient,\r\n InProgressPerformanceEvent,\r\n} from \"./IPerformanceClient.js\";\r\nimport { IPerformanceMeasurement } from \"./IPerformanceMeasurement.js\";\r\nimport {\r\n PerformanceEvent,\r\n PerformanceEventStatus,\r\n} from \"./PerformanceEvent.js\";\r\n\r\nexport class StubPerformanceMeasurement implements IPerformanceMeasurement {\r\n startMeasurement(): void {\r\n return;\r\n }\r\n endMeasurement(): void {\r\n return;\r\n }\r\n flushMeasurement(): number | null {\r\n return null;\r\n }\r\n}\r\n\r\nexport class StubPerformanceClient implements IPerformanceClient {\r\n generateId(): string {\r\n return \"callback-id\";\r\n }\r\n\r\n startMeasurement(\r\n measureName: string,\r\n correlationId?: string | undefined\r\n ): InProgressPerformanceEvent {\r\n return {\r\n end: () => null,\r\n discard: () => {},\r\n add: () => {},\r\n increment: () => {},\r\n event: {\r\n eventId: this.generateId(),\r\n status: PerformanceEventStatus.InProgress,\r\n authority: \"\",\r\n libraryName: \"\",\r\n libraryVersion: \"\",\r\n clientId: \"\",\r\n name: measureName,\r\n startTimeMs: Date.now(),\r\n correlationId: correlationId || \"\",\r\n },\r\n measurement: new StubPerformanceMeasurement(),\r\n };\r\n }\r\n\r\n startPerformanceMeasurement(): IPerformanceMeasurement {\r\n return new StubPerformanceMeasurement();\r\n }\r\n calculateQueuedTime(): number {\r\n return 0;\r\n }\r\n\r\n addQueueMeasurement(): void {\r\n return;\r\n }\r\n\r\n setPreQueueTime(): void {\r\n return;\r\n }\r\n\r\n endMeasurement(): PerformanceEvent | null {\r\n return null;\r\n }\r\n\r\n discardMeasurements(): void {\r\n return;\r\n }\r\n\r\n removePerformanceCallback(): boolean {\r\n return true;\r\n }\r\n\r\n addPerformanceCallback(): string {\r\n return \"\";\r\n }\r\n\r\n emitEvents(): void {\r\n return;\r\n }\r\n\r\n addFields(): void {\r\n return;\r\n }\r\n\r\n incrementFields(): void {\r\n return;\r\n }\r\n\r\n cacheEventByCorrelationId(): void {\r\n return;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { INetworkModule } from \"../network/INetworkModule.js\";\r\nimport { DEFAULT_CRYPTO_IMPLEMENTATION, ICrypto } from \"../crypto/ICrypto.js\";\r\nimport { ILoggerCallback, Logger, LogLevel } from \"../logger/Logger.js\";\r\nimport {\r\n Constants,\r\n DEFAULT_TOKEN_RENEWAL_OFFSET_SEC,\r\n} from \"../utils/Constants.js\";\r\nimport { version } from \"../packageMetadata.js\";\r\nimport type { Authority } from \"../authority/Authority.js\";\r\nimport { AzureCloudInstance } from \"../authority/AuthorityOptions.js\";\r\nimport { CacheManager, DefaultStorageClass } from \"../cache/CacheManager.js\";\r\nimport { ServerTelemetryManager } from \"../telemetry/server/ServerTelemetryManager.js\";\r\nimport { ICachePlugin } from \"../cache/interface/ICachePlugin.js\";\r\nimport { ISerializableTokenCache } from \"../cache/interface/ISerializableTokenCache.js\";\r\nimport { ClientCredentials } from \"../account/ClientCredentials.js\";\r\nimport { ProtocolMode } from \"../authority/ProtocolMode.js\";\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n} from \"../error/ClientAuthError.js\";\r\nimport { StubPerformanceClient } from \"../telemetry/performance/StubPerformanceClient.js\";\r\n\r\n/**\r\n * Use the configuration object to configure MSAL Modules and initialize the base interfaces for MSAL.\r\n *\r\n * This object allows you to configure important elements of MSAL functionality:\r\n * - authOptions - Authentication for application\r\n * - cryptoInterface - Implementation of crypto functions\r\n * - libraryInfo - Library metadata\r\n * - telemetry - Telemetry options and data\r\n * - loggerOptions - Logging for application\r\n * - networkInterface - Network implementation\r\n * - storageInterface - Storage implementation\r\n * - systemOptions - Additional library options\r\n * - clientCredentials - Credentials options for confidential clients\r\n * @internal\r\n */\r\nexport type ClientConfiguration = {\r\n authOptions: AuthOptions;\r\n systemOptions?: SystemOptions;\r\n loggerOptions?: LoggerOptions;\r\n cacheOptions?: CacheOptions;\r\n storageInterface?: CacheManager;\r\n networkInterface?: INetworkModule;\r\n cryptoInterface?: ICrypto;\r\n clientCredentials?: ClientCredentials;\r\n libraryInfo?: LibraryInfo;\r\n telemetry?: TelemetryOptions;\r\n serverTelemetryManager?: ServerTelemetryManager | null;\r\n persistencePlugin?: ICachePlugin | null;\r\n serializableCache?: ISerializableTokenCache | null;\r\n};\r\n\r\nexport type CommonClientConfiguration = {\r\n authOptions: Required;\r\n systemOptions: Required;\r\n loggerOptions: Required;\r\n cacheOptions: Required;\r\n storageInterface: CacheManager;\r\n networkInterface: INetworkModule;\r\n cryptoInterface: Required;\r\n libraryInfo: LibraryInfo;\r\n telemetry: Required;\r\n serverTelemetryManager: ServerTelemetryManager | null;\r\n clientCredentials: ClientCredentials;\r\n persistencePlugin: ICachePlugin | null;\r\n serializableCache: ISerializableTokenCache | null;\r\n};\r\n\r\n/**\r\n * Use this to configure the auth options in the ClientConfiguration object\r\n *\r\n * - clientId - Client ID of your app registered with our Application registration portal : https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredAppsPreview in Microsoft Identity Platform\r\n * - authority - You can configure a specific authority, defaults to \" \" or \"https://login.microsoftonline.com/common\"\r\n * - knownAuthorities - An array of URIs that are known to be valid. Used in B2C scenarios.\r\n * - cloudDiscoveryMetadata - A string containing the cloud discovery response. Used in AAD scenarios.\r\n * - clientCapabilities - Array of capabilities which will be added to the claims.access_token.xms_cc request property on every network request.\r\n * - protocolMode - Enum that represents the protocol that msal follows. Used for configuring proper endpoints.\r\n * - skipAuthorityMetadataCache - A flag to choose whether to use or not use the local metadata cache during authority initialization. Defaults to false.\r\n * - instanceAware - A flag of whether the STS will send back additional parameters to specify where the tokens should be retrieved from.\r\n * - redirectUri - The redirect URI where authentication responses can be received by your application. It must exactly match one of the redirect URIs registered in the Azure portal.\r\n * - encodeExtraQueryParams - A flag to choose whether to encode the extra query parameters or not. Defaults to false.\r\n * @internal\r\n */\r\nexport type AuthOptions = {\r\n clientId: string;\r\n authority: Authority;\r\n redirectUri: string;\r\n clientCapabilities?: Array;\r\n azureCloudOptions?: AzureCloudOptions;\r\n skipAuthorityMetadataCache?: boolean;\r\n instanceAware?: boolean;\r\n /**\r\n * @deprecated This flag is deprecated and will be removed in the next major version where all extra query params will be encoded by default.\r\n */\r\n encodeExtraQueryParams?: boolean;\r\n};\r\n\r\n/**\r\n * Use this to configure token renewal info in the Configuration object\r\n *\r\n * - tokenRenewalOffsetSeconds - Sets the window of offset needed to renew the token before expiry\r\n */\r\nexport type SystemOptions = {\r\n tokenRenewalOffsetSeconds?: number;\r\n preventCorsPreflight?: boolean;\r\n};\r\n\r\n/**\r\n * Use this to configure the logging that MSAL does, by configuring logger options in the Configuration object\r\n *\r\n * - loggerCallback - Callback for logger\r\n * - piiLoggingEnabled - Sets whether pii logging is enabled\r\n * - logLevel - Sets the level at which logging happens\r\n * - correlationId - Sets the correlationId printed by the logger\r\n */\r\nexport type LoggerOptions = {\r\n loggerCallback?: ILoggerCallback;\r\n piiLoggingEnabled?: boolean;\r\n logLevel?: LogLevel;\r\n correlationId?: string;\r\n};\r\n\r\n/**\r\n * Use this to configure credential cache preferences in the ClientConfiguration object\r\n *\r\n * - claimsBasedCachingEnabled - Sets whether tokens should be cached based on the claims hash. Default is false.\r\n */\r\nexport type CacheOptions = {\r\n /**\r\n * @deprecated claimsBasedCachingEnabled is deprecated and will be removed in the next major version.\r\n */\r\n claimsBasedCachingEnabled?: boolean;\r\n};\r\n\r\n/**\r\n * Library-specific options\r\n */\r\nexport type LibraryInfo = {\r\n sku: string;\r\n version: string;\r\n cpu: string;\r\n os: string;\r\n};\r\n\r\n/**\r\n * AzureCloudInstance specific options\r\n *\r\n * - azureCloudInstance - string enum providing short notation for soverign and public cloud authorities\r\n * - tenant - provision to provide the tenant info\r\n */\r\nexport type AzureCloudOptions = {\r\n azureCloudInstance: AzureCloudInstance;\r\n tenant?: string;\r\n};\r\n\r\nexport type TelemetryOptions = {\r\n application: ApplicationTelemetry;\r\n};\r\n\r\n/**\r\n * Telemetry information sent on request\r\n * - appName: Unique string name of an application\r\n * - appVersion: Version of the application using MSAL\r\n */\r\nexport type ApplicationTelemetry = {\r\n appName: string;\r\n appVersion: string;\r\n};\r\n\r\nexport const DEFAULT_SYSTEM_OPTIONS: Required = {\r\n tokenRenewalOffsetSeconds: DEFAULT_TOKEN_RENEWAL_OFFSET_SEC,\r\n preventCorsPreflight: false,\r\n};\r\n\r\nconst DEFAULT_LOGGER_IMPLEMENTATION: Required = {\r\n loggerCallback: () => {\r\n // allow users to not set loggerCallback\r\n },\r\n piiLoggingEnabled: false,\r\n logLevel: LogLevel.Info,\r\n correlationId: Constants.EMPTY_STRING,\r\n};\r\n\r\nconst DEFAULT_CACHE_OPTIONS: Required = {\r\n claimsBasedCachingEnabled: false,\r\n};\r\n\r\nconst DEFAULT_NETWORK_IMPLEMENTATION: INetworkModule = {\r\n async sendGetRequestAsync(): Promise {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n },\r\n async sendPostRequestAsync(): Promise {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n },\r\n};\r\n\r\nconst DEFAULT_LIBRARY_INFO: LibraryInfo = {\r\n sku: Constants.SKU,\r\n version: version,\r\n cpu: Constants.EMPTY_STRING,\r\n os: Constants.EMPTY_STRING,\r\n};\r\n\r\nconst DEFAULT_CLIENT_CREDENTIALS: ClientCredentials = {\r\n clientSecret: Constants.EMPTY_STRING,\r\n clientAssertion: undefined,\r\n};\r\n\r\nconst DEFAULT_AZURE_CLOUD_OPTIONS: AzureCloudOptions = {\r\n azureCloudInstance: AzureCloudInstance.None,\r\n tenant: `${Constants.DEFAULT_COMMON_TENANT}`,\r\n};\r\n\r\nconst DEFAULT_TELEMETRY_OPTIONS: Required = {\r\n application: {\r\n appName: \"\",\r\n appVersion: \"\",\r\n },\r\n};\r\n\r\n/**\r\n * Function that sets the default options when not explicitly configured from app developer\r\n *\r\n * @param Configuration\r\n *\r\n * @returns Configuration\r\n */\r\nexport function buildClientConfiguration({\r\n authOptions: userAuthOptions,\r\n systemOptions: userSystemOptions,\r\n loggerOptions: userLoggerOption,\r\n cacheOptions: userCacheOptions,\r\n storageInterface: storageImplementation,\r\n networkInterface: networkImplementation,\r\n cryptoInterface: cryptoImplementation,\r\n clientCredentials: clientCredentials,\r\n libraryInfo: libraryInfo,\r\n telemetry: telemetry,\r\n serverTelemetryManager: serverTelemetryManager,\r\n persistencePlugin: persistencePlugin,\r\n serializableCache: serializableCache,\r\n}: ClientConfiguration): CommonClientConfiguration {\r\n const loggerOptions = {\r\n ...DEFAULT_LOGGER_IMPLEMENTATION,\r\n ...userLoggerOption,\r\n };\r\n\r\n return {\r\n authOptions: buildAuthOptions(userAuthOptions),\r\n systemOptions: { ...DEFAULT_SYSTEM_OPTIONS, ...userSystemOptions },\r\n loggerOptions: loggerOptions,\r\n cacheOptions: { ...DEFAULT_CACHE_OPTIONS, ...userCacheOptions },\r\n storageInterface:\r\n storageImplementation ||\r\n new DefaultStorageClass(\r\n userAuthOptions.clientId,\r\n DEFAULT_CRYPTO_IMPLEMENTATION,\r\n new Logger(loggerOptions),\r\n new StubPerformanceClient()\r\n ),\r\n networkInterface:\r\n networkImplementation || DEFAULT_NETWORK_IMPLEMENTATION,\r\n cryptoInterface: cryptoImplementation || DEFAULT_CRYPTO_IMPLEMENTATION,\r\n clientCredentials: clientCredentials || DEFAULT_CLIENT_CREDENTIALS,\r\n libraryInfo: { ...DEFAULT_LIBRARY_INFO, ...libraryInfo },\r\n telemetry: { ...DEFAULT_TELEMETRY_OPTIONS, ...telemetry },\r\n serverTelemetryManager: serverTelemetryManager || null,\r\n persistencePlugin: persistencePlugin || null,\r\n serializableCache: serializableCache || null,\r\n };\r\n}\r\n\r\n/**\r\n * Construct authoptions from the client and platform passed values\r\n * @param authOptions\r\n */\r\nfunction buildAuthOptions(authOptions: AuthOptions): Required {\r\n return {\r\n clientCapabilities: [],\r\n azureCloudOptions: DEFAULT_AZURE_CLOUD_OPTIONS,\r\n skipAuthorityMetadataCache: false,\r\n instanceAware: false,\r\n encodeExtraQueryParams: false,\r\n ...authOptions,\r\n };\r\n}\r\n\r\n/**\r\n * Returns true if config has protocolMode set to ProtocolMode.OIDC, false otherwise\r\n * @param ClientConfiguration\r\n */\r\nexport function isOidcProtocolMode(config: ClientConfiguration): boolean {\r\n return (\r\n config.authOptions.authority.options.protocolMode === ProtocolMode.OIDC\r\n );\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport type CcsCredential = {\r\n credential: string;\r\n type: CcsCredentialType;\r\n};\r\n\r\nexport const CcsCredentialType = {\r\n HOME_ACCOUNT_ID: \"home_account_id\",\r\n UPN: \"UPN\",\r\n} as const;\r\nexport type CcsCredentialType =\r\n (typeof CcsCredentialType)[keyof typeof CcsCredentialType];\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n createClientAuthError,\r\n ClientAuthErrorCodes,\r\n} from \"../error/ClientAuthError.js\";\r\nimport { Separators, Constants } from \"../utils/Constants.js\";\r\n\r\n/**\r\n * Client info object which consists of two IDs. Need to add more info here.\r\n */\r\nexport type ClientInfo = {\r\n uid: string;\r\n utid: string;\r\n};\r\n\r\n/**\r\n * Function to build a client info object from server clientInfo string\r\n * @param rawClientInfo\r\n * @param crypto\r\n */\r\nexport function buildClientInfo(\r\n rawClientInfo: string,\r\n base64Decode: (input: string) => string\r\n): ClientInfo {\r\n if (!rawClientInfo) {\r\n throw createClientAuthError(ClientAuthErrorCodes.clientInfoEmptyError);\r\n }\r\n\r\n try {\r\n const decodedClientInfo: string = base64Decode(rawClientInfo);\r\n return JSON.parse(decodedClientInfo) as ClientInfo;\r\n } catch (e) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.clientInfoDecodingError\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Function to build a client info object from cached homeAccountId string\r\n * @param homeAccountId\r\n */\r\nexport function buildClientInfoFromHomeAccountId(\r\n homeAccountId: string\r\n): ClientInfo {\r\n if (!homeAccountId) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.clientInfoDecodingError\r\n );\r\n }\r\n const clientInfoParts: string[] = homeAccountId.split(\r\n Separators.CLIENT_INFO_SEPARATOR,\r\n 2\r\n );\r\n return {\r\n uid: clientInfoParts[0],\r\n utid:\r\n clientInfoParts.length < 2\r\n ? Constants.EMPTY_STRING\r\n : clientInfoParts[1],\r\n };\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport const CLIENT_ID = \"client_id\";\r\nexport const REDIRECT_URI = \"redirect_uri\";\r\nexport const RESPONSE_TYPE = \"response_type\";\r\nexport const RESPONSE_MODE = \"response_mode\";\r\nexport const GRANT_TYPE = \"grant_type\";\r\nexport const CLAIMS = \"claims\";\r\nexport const SCOPE = \"scope\";\r\nexport const ERROR = \"error\";\r\nexport const ERROR_DESCRIPTION = \"error_description\";\r\nexport const ACCESS_TOKEN = \"access_token\";\r\nexport const ID_TOKEN = \"id_token\";\r\nexport const REFRESH_TOKEN = \"refresh_token\";\r\nexport const EXPIRES_IN = \"expires_in\";\r\nexport const REFRESH_TOKEN_EXPIRES_IN = \"refresh_token_expires_in\";\r\nexport const STATE = \"state\";\r\nexport const NONCE = \"nonce\";\r\nexport const PROMPT = \"prompt\";\r\nexport const SESSION_STATE = \"session_state\";\r\nexport const CLIENT_INFO = \"client_info\";\r\nexport const CODE = \"code\";\r\nexport const CODE_CHALLENGE = \"code_challenge\";\r\nexport const CODE_CHALLENGE_METHOD = \"code_challenge_method\";\r\nexport const CODE_VERIFIER = \"code_verifier\";\r\nexport const CLIENT_REQUEST_ID = \"client-request-id\";\r\nexport const X_CLIENT_SKU = \"x-client-SKU\";\r\nexport const X_CLIENT_VER = \"x-client-VER\";\r\nexport const X_CLIENT_OS = \"x-client-OS\";\r\nexport const X_CLIENT_CPU = \"x-client-CPU\";\r\nexport const X_CLIENT_CURR_TELEM = \"x-client-current-telemetry\";\r\nexport const X_CLIENT_LAST_TELEM = \"x-client-last-telemetry\";\r\nexport const X_MS_LIB_CAPABILITY = \"x-ms-lib-capability\";\r\nexport const X_APP_NAME = \"x-app-name\";\r\nexport const X_APP_VER = \"x-app-ver\";\r\nexport const POST_LOGOUT_URI = \"post_logout_redirect_uri\";\r\nexport const ID_TOKEN_HINT = \"id_token_hint\";\r\nexport const DEVICE_CODE = \"device_code\";\r\nexport const CLIENT_SECRET = \"client_secret\";\r\nexport const CLIENT_ASSERTION = \"client_assertion\";\r\nexport const CLIENT_ASSERTION_TYPE = \"client_assertion_type\";\r\nexport const TOKEN_TYPE = \"token_type\";\r\nexport const REQ_CNF = \"req_cnf\";\r\nexport const OBO_ASSERTION = \"assertion\";\r\nexport const REQUESTED_TOKEN_USE = \"requested_token_use\";\r\nexport const ON_BEHALF_OF = \"on_behalf_of\";\r\nexport const FOCI = \"foci\";\r\nexport const CCS_HEADER = \"X-AnchorMailbox\";\r\nexport const RETURN_SPA_CODE = \"return_spa_code\";\r\nexport const NATIVE_BROKER = \"nativebroker\";\r\nexport const LOGOUT_HINT = \"logout_hint\";\r\nexport const SID = \"sid\";\r\nexport const LOGIN_HINT = \"login_hint\";\r\nexport const DOMAIN_HINT = \"domain_hint\";\r\nexport const X_CLIENT_EXTRA_SKU = \"x-client-xtra-sku\";\r\nexport const BROKER_CLIENT_ID = \"brk_client_id\";\r\nexport const BROKER_REDIRECT_URI = \"brk_redirect_uri\";\r\nexport const INSTANCE_AWARE = \"instance_aware\";\r\nexport const EAR_JWK = \"ear_jwk\";\r\nexport const EAR_JWE_CRYPTO = \"ear_jwe_crypto\";\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n ResponseMode,\r\n CLIENT_INFO,\r\n AuthenticationScheme,\r\n ClaimsRequestKeys,\r\n PasswordGrantConstants,\r\n OIDC_DEFAULT_SCOPES,\r\n ThrottlingConstants,\r\n HeaderNames,\r\n OAuthResponseType,\r\n} from \"../utils/Constants.js\";\r\nimport * as AADServerParamKeys from \"../constants/AADServerParamKeys.js\";\r\nimport { ScopeSet } from \"./ScopeSet.js\";\r\nimport {\r\n createClientConfigurationError,\r\n ClientConfigurationErrorCodes,\r\n} from \"../error/ClientConfigurationError.js\";\r\nimport { StringDict } from \"../utils/MsalTypes.js\";\r\nimport {\r\n ApplicationTelemetry,\r\n LibraryInfo,\r\n} from \"../config/ClientConfiguration.js\";\r\nimport { ServerTelemetryManager } from \"../telemetry/server/ServerTelemetryManager.js\";\r\nimport { ClientInfo } from \"../account/ClientInfo.js\";\r\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\r\n\r\nexport function instrumentBrokerParams(\r\n parameters: Map,\r\n correlationId?: string,\r\n performanceClient?: IPerformanceClient\r\n): void {\r\n if (!correlationId) {\r\n return;\r\n }\r\n\r\n const clientId = parameters.get(AADServerParamKeys.CLIENT_ID);\r\n if (clientId && parameters.has(AADServerParamKeys.BROKER_CLIENT_ID)) {\r\n performanceClient?.addFields(\r\n {\r\n embeddedClientId: clientId,\r\n embeddedRedirectUri: parameters.get(\r\n AADServerParamKeys.REDIRECT_URI\r\n ),\r\n },\r\n correlationId\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Add the given response_type\r\n * @param parameters\r\n * @param responseType\r\n */\r\nexport function addResponseType(\r\n parameters: Map,\r\n responseType: OAuthResponseType\r\n): void {\r\n parameters.set(AADServerParamKeys.RESPONSE_TYPE, responseType);\r\n}\r\n\r\n/**\r\n * add response_mode. defaults to query.\r\n * @param responseMode\r\n */\r\nexport function addResponseMode(\r\n parameters: Map,\r\n responseMode?: ResponseMode\r\n): void {\r\n parameters.set(\r\n AADServerParamKeys.RESPONSE_MODE,\r\n responseMode ? responseMode : ResponseMode.QUERY\r\n );\r\n}\r\n\r\n/**\r\n * Add flag to indicate STS should attempt to use WAM if available\r\n */\r\nexport function addNativeBroker(parameters: Map): void {\r\n parameters.set(AADServerParamKeys.NATIVE_BROKER, \"1\");\r\n}\r\n\r\n/**\r\n * add scopes. set addOidcScopes to false to prevent default scopes in non-user scenarios\r\n * @param scopeSet\r\n * @param addOidcScopes\r\n */\r\nexport function addScopes(\r\n parameters: Map,\r\n scopes: string[],\r\n addOidcScopes: boolean = true,\r\n defaultScopes: Array = OIDC_DEFAULT_SCOPES\r\n): void {\r\n // Always add openid to the scopes when adding OIDC scopes\r\n if (\r\n addOidcScopes &&\r\n !defaultScopes.includes(\"openid\") &&\r\n !scopes.includes(\"openid\")\r\n ) {\r\n defaultScopes.push(\"openid\");\r\n }\r\n const requestScopes = addOidcScopes\r\n ? [...(scopes || []), ...defaultScopes]\r\n : scopes || [];\r\n const scopeSet = new ScopeSet(requestScopes);\r\n parameters.set(AADServerParamKeys.SCOPE, scopeSet.printScopes());\r\n}\r\n\r\n/**\r\n * add clientId\r\n * @param clientId\r\n */\r\nexport function addClientId(\r\n parameters: Map,\r\n clientId: string\r\n): void {\r\n parameters.set(AADServerParamKeys.CLIENT_ID, clientId);\r\n}\r\n\r\n/**\r\n * add redirect_uri\r\n * @param redirectUri\r\n */\r\nexport function addRedirectUri(\r\n parameters: Map,\r\n redirectUri: string\r\n): void {\r\n parameters.set(AADServerParamKeys.REDIRECT_URI, redirectUri);\r\n}\r\n\r\n/**\r\n * add post logout redirectUri\r\n * @param redirectUri\r\n */\r\nexport function addPostLogoutRedirectUri(\r\n parameters: Map,\r\n redirectUri: string\r\n): void {\r\n parameters.set(AADServerParamKeys.POST_LOGOUT_URI, redirectUri);\r\n}\r\n\r\n/**\r\n * add id_token_hint to logout request\r\n * @param idTokenHint\r\n */\r\nexport function addIdTokenHint(\r\n parameters: Map,\r\n idTokenHint: string\r\n): void {\r\n parameters.set(AADServerParamKeys.ID_TOKEN_HINT, idTokenHint);\r\n}\r\n\r\n/**\r\n * add domain_hint\r\n * @param domainHint\r\n */\r\nexport function addDomainHint(\r\n parameters: Map,\r\n domainHint: string\r\n): void {\r\n parameters.set(AADServerParamKeys.DOMAIN_HINT, domainHint);\r\n}\r\n\r\n/**\r\n * add login_hint\r\n * @param loginHint\r\n */\r\nexport function addLoginHint(\r\n parameters: Map,\r\n loginHint: string\r\n): void {\r\n parameters.set(AADServerParamKeys.LOGIN_HINT, loginHint);\r\n}\r\n\r\n/**\r\n * Adds the CCS (Cache Credential Service) query parameter for login_hint\r\n * @param loginHint\r\n */\r\nexport function addCcsUpn(\r\n parameters: Map,\r\n loginHint: string\r\n): void {\r\n parameters.set(HeaderNames.CCS_HEADER, `UPN:${loginHint}`);\r\n}\r\n\r\n/**\r\n * Adds the CCS (Cache Credential Service) query parameter for account object\r\n * @param loginHint\r\n */\r\nexport function addCcsOid(\r\n parameters: Map,\r\n clientInfo: ClientInfo\r\n): void {\r\n parameters.set(\r\n HeaderNames.CCS_HEADER,\r\n `Oid:${clientInfo.uid}@${clientInfo.utid}`\r\n );\r\n}\r\n\r\n/**\r\n * add sid\r\n * @param sid\r\n */\r\nexport function addSid(parameters: Map, sid: string): void {\r\n parameters.set(AADServerParamKeys.SID, sid);\r\n}\r\n\r\n/**\r\n * add claims\r\n * @param claims\r\n */\r\nexport function addClaims(\r\n parameters: Map,\r\n claims?: string,\r\n clientCapabilities?: Array\r\n): void {\r\n const mergedClaims = addClientCapabilitiesToClaims(\r\n claims,\r\n clientCapabilities\r\n );\r\n try {\r\n JSON.parse(mergedClaims);\r\n } catch (e) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.invalidClaims\r\n );\r\n }\r\n parameters.set(AADServerParamKeys.CLAIMS, mergedClaims);\r\n}\r\n\r\n/**\r\n * add correlationId\r\n * @param correlationId\r\n */\r\nexport function addCorrelationId(\r\n parameters: Map,\r\n correlationId: string\r\n): void {\r\n parameters.set(AADServerParamKeys.CLIENT_REQUEST_ID, correlationId);\r\n}\r\n\r\n/**\r\n * add library info query params\r\n * @param libraryInfo\r\n */\r\nexport function addLibraryInfo(\r\n parameters: Map,\r\n libraryInfo: LibraryInfo\r\n): void {\r\n // Telemetry Info\r\n parameters.set(AADServerParamKeys.X_CLIENT_SKU, libraryInfo.sku);\r\n parameters.set(AADServerParamKeys.X_CLIENT_VER, libraryInfo.version);\r\n if (libraryInfo.os) {\r\n parameters.set(AADServerParamKeys.X_CLIENT_OS, libraryInfo.os);\r\n }\r\n if (libraryInfo.cpu) {\r\n parameters.set(AADServerParamKeys.X_CLIENT_CPU, libraryInfo.cpu);\r\n }\r\n}\r\n\r\n/**\r\n * Add client telemetry parameters\r\n * @param appTelemetry\r\n */\r\nexport function addApplicationTelemetry(\r\n parameters: Map,\r\n appTelemetry: ApplicationTelemetry\r\n): void {\r\n if (appTelemetry?.appName) {\r\n parameters.set(AADServerParamKeys.X_APP_NAME, appTelemetry.appName);\r\n }\r\n\r\n if (appTelemetry?.appVersion) {\r\n parameters.set(AADServerParamKeys.X_APP_VER, appTelemetry.appVersion);\r\n }\r\n}\r\n\r\n/**\r\n * add prompt\r\n * @param prompt\r\n */\r\nexport function addPrompt(\r\n parameters: Map,\r\n prompt: string\r\n): void {\r\n parameters.set(AADServerParamKeys.PROMPT, prompt);\r\n}\r\n\r\n/**\r\n * add state\r\n * @param state\r\n */\r\nexport function addState(parameters: Map, state: string): void {\r\n if (state) {\r\n parameters.set(AADServerParamKeys.STATE, state);\r\n }\r\n}\r\n\r\n/**\r\n * add nonce\r\n * @param nonce\r\n */\r\nexport function addNonce(parameters: Map, nonce: string): void {\r\n parameters.set(AADServerParamKeys.NONCE, nonce);\r\n}\r\n\r\n/**\r\n * add code_challenge and code_challenge_method\r\n * - throw if either of them are not passed\r\n * @param codeChallenge\r\n * @param codeChallengeMethod\r\n */\r\nexport function addCodeChallengeParams(\r\n parameters: Map,\r\n codeChallenge?: string,\r\n codeChallengeMethod?: string\r\n): void {\r\n if (codeChallenge && codeChallengeMethod) {\r\n parameters.set(AADServerParamKeys.CODE_CHALLENGE, codeChallenge);\r\n parameters.set(\r\n AADServerParamKeys.CODE_CHALLENGE_METHOD,\r\n codeChallengeMethod\r\n );\r\n } else {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.pkceParamsMissing\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * add the `authorization_code` passed by the user to exchange for a token\r\n * @param code\r\n */\r\nexport function addAuthorizationCode(\r\n parameters: Map,\r\n code: string\r\n): void {\r\n parameters.set(AADServerParamKeys.CODE, code);\r\n}\r\n\r\n/**\r\n * add the `authorization_code` passed by the user to exchange for a token\r\n * @param code\r\n */\r\nexport function addDeviceCode(\r\n parameters: Map,\r\n code: string\r\n): void {\r\n parameters.set(AADServerParamKeys.DEVICE_CODE, code);\r\n}\r\n\r\n/**\r\n * add the `refreshToken` passed by the user\r\n * @param refreshToken\r\n */\r\nexport function addRefreshToken(\r\n parameters: Map,\r\n refreshToken: string\r\n): void {\r\n parameters.set(AADServerParamKeys.REFRESH_TOKEN, refreshToken);\r\n}\r\n\r\n/**\r\n * add the `code_verifier` passed by the user to exchange for a token\r\n * @param codeVerifier\r\n */\r\nexport function addCodeVerifier(\r\n parameters: Map,\r\n codeVerifier: string\r\n): void {\r\n parameters.set(AADServerParamKeys.CODE_VERIFIER, codeVerifier);\r\n}\r\n\r\n/**\r\n * add client_secret\r\n * @param clientSecret\r\n */\r\nexport function addClientSecret(\r\n parameters: Map,\r\n clientSecret: string\r\n): void {\r\n parameters.set(AADServerParamKeys.CLIENT_SECRET, clientSecret);\r\n}\r\n\r\n/**\r\n * add clientAssertion for confidential client flows\r\n * @param clientAssertion\r\n */\r\nexport function addClientAssertion(\r\n parameters: Map,\r\n clientAssertion: string\r\n): void {\r\n if (clientAssertion) {\r\n parameters.set(AADServerParamKeys.CLIENT_ASSERTION, clientAssertion);\r\n }\r\n}\r\n\r\n/**\r\n * add clientAssertionType for confidential client flows\r\n * @param clientAssertionType\r\n */\r\nexport function addClientAssertionType(\r\n parameters: Map,\r\n clientAssertionType: string\r\n): void {\r\n if (clientAssertionType) {\r\n parameters.set(\r\n AADServerParamKeys.CLIENT_ASSERTION_TYPE,\r\n clientAssertionType\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * add OBO assertion for confidential client flows\r\n * @param clientAssertion\r\n */\r\nexport function addOboAssertion(\r\n parameters: Map,\r\n oboAssertion: string\r\n): void {\r\n parameters.set(AADServerParamKeys.OBO_ASSERTION, oboAssertion);\r\n}\r\n\r\n/**\r\n * add grant type\r\n * @param grantType\r\n */\r\nexport function addRequestTokenUse(\r\n parameters: Map,\r\n tokenUse: string\r\n): void {\r\n parameters.set(AADServerParamKeys.REQUESTED_TOKEN_USE, tokenUse);\r\n}\r\n\r\n/**\r\n * add grant type\r\n * @param grantType\r\n */\r\nexport function addGrantType(\r\n parameters: Map,\r\n grantType: string\r\n): void {\r\n parameters.set(AADServerParamKeys.GRANT_TYPE, grantType);\r\n}\r\n\r\n/**\r\n * add client info\r\n *\r\n */\r\nexport function addClientInfo(parameters: Map): void {\r\n parameters.set(CLIENT_INFO, \"1\");\r\n}\r\n\r\nexport function addInstanceAware(parameters: Map): void {\r\n if (!parameters.has(AADServerParamKeys.INSTANCE_AWARE)) {\r\n parameters.set(AADServerParamKeys.INSTANCE_AWARE, \"true\");\r\n }\r\n}\r\n\r\n/**\r\n * add extraQueryParams\r\n * @param eQParams\r\n */\r\nexport function addExtraQueryParameters(\r\n parameters: Map,\r\n eQParams: StringDict\r\n): void {\r\n Object.entries(eQParams).forEach(([key, value]) => {\r\n if (!parameters.has(key) && value) {\r\n parameters.set(key, value);\r\n }\r\n });\r\n}\r\n\r\nexport function addClientCapabilitiesToClaims(\r\n claims?: string,\r\n clientCapabilities?: Array\r\n): string {\r\n let mergedClaims: object;\r\n\r\n // Parse provided claims into JSON object or initialize empty object\r\n if (!claims) {\r\n mergedClaims = {};\r\n } else {\r\n try {\r\n mergedClaims = JSON.parse(claims);\r\n } catch (e) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.invalidClaims\r\n );\r\n }\r\n }\r\n\r\n if (clientCapabilities && clientCapabilities.length > 0) {\r\n if (!mergedClaims.hasOwnProperty(ClaimsRequestKeys.ACCESS_TOKEN)) {\r\n // Add access_token key to claims object\r\n mergedClaims[ClaimsRequestKeys.ACCESS_TOKEN] = {};\r\n }\r\n\r\n // Add xms_cc claim with provided clientCapabilities to access_token key\r\n mergedClaims[ClaimsRequestKeys.ACCESS_TOKEN][ClaimsRequestKeys.XMS_CC] =\r\n {\r\n values: clientCapabilities,\r\n };\r\n }\r\n\r\n return JSON.stringify(mergedClaims);\r\n}\r\n\r\n/**\r\n * adds `username` for Password Grant flow\r\n * @param username\r\n */\r\nexport function addUsername(\r\n parameters: Map,\r\n username: string\r\n): void {\r\n parameters.set(PasswordGrantConstants.username, username);\r\n}\r\n\r\n/**\r\n * adds `password` for Password Grant flow\r\n * @param password\r\n */\r\nexport function addPassword(\r\n parameters: Map,\r\n password: string\r\n): void {\r\n parameters.set(PasswordGrantConstants.password, password);\r\n}\r\n\r\n/**\r\n * add pop_jwk to query params\r\n * @param cnfString\r\n */\r\nexport function addPopToken(\r\n parameters: Map,\r\n cnfString: string\r\n): void {\r\n if (cnfString) {\r\n parameters.set(AADServerParamKeys.TOKEN_TYPE, AuthenticationScheme.POP);\r\n parameters.set(AADServerParamKeys.REQ_CNF, cnfString);\r\n }\r\n}\r\n\r\n/**\r\n * add SSH JWK and key ID to query params\r\n */\r\nexport function addSshJwk(\r\n parameters: Map,\r\n sshJwkString: string\r\n): void {\r\n if (sshJwkString) {\r\n parameters.set(AADServerParamKeys.TOKEN_TYPE, AuthenticationScheme.SSH);\r\n parameters.set(AADServerParamKeys.REQ_CNF, sshJwkString);\r\n }\r\n}\r\n\r\n/**\r\n * add server telemetry fields\r\n * @param serverTelemetryManager\r\n */\r\nexport function addServerTelemetry(\r\n parameters: Map,\r\n serverTelemetryManager: ServerTelemetryManager\r\n): void {\r\n parameters.set(\r\n AADServerParamKeys.X_CLIENT_CURR_TELEM,\r\n serverTelemetryManager.generateCurrentRequestHeaderValue()\r\n );\r\n parameters.set(\r\n AADServerParamKeys.X_CLIENT_LAST_TELEM,\r\n serverTelemetryManager.generateLastRequestHeaderValue()\r\n );\r\n}\r\n\r\n/**\r\n * Adds parameter that indicates to the server that throttling is supported\r\n */\r\nexport function addThrottling(parameters: Map): void {\r\n parameters.set(\r\n AADServerParamKeys.X_MS_LIB_CAPABILITY,\r\n ThrottlingConstants.X_MS_LIB_CAPABILITY_VALUE\r\n );\r\n}\r\n\r\n/**\r\n * Adds logout_hint parameter for \"silent\" logout which prevent server account picker\r\n */\r\nexport function addLogoutHint(\r\n parameters: Map,\r\n logoutHint: string\r\n): void {\r\n parameters.set(AADServerParamKeys.LOGOUT_HINT, logoutHint);\r\n}\r\n\r\nexport function addBrokerParameters(\r\n parameters: Map,\r\n brokerClientId: string,\r\n brokerRedirectUri: string\r\n): void {\r\n if (!parameters.has(AADServerParamKeys.BROKER_CLIENT_ID)) {\r\n parameters.set(AADServerParamKeys.BROKER_CLIENT_ID, brokerClientId);\r\n }\r\n if (!parameters.has(AADServerParamKeys.BROKER_REDIRECT_URI)) {\r\n parameters.set(\r\n AADServerParamKeys.BROKER_REDIRECT_URI,\r\n brokerRedirectUri\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Add EAR (Encrypted Authorize Response) request parameters\r\n * @param parameters\r\n * @param jwk\r\n */\r\nexport function addEARParameters(\r\n parameters: Map,\r\n jwk: string\r\n): void {\r\n parameters.set(AADServerParamKeys.EAR_JWK, encodeURIComponent(jwk));\r\n\r\n // ear_jwe_crypto will always have value: {\"alg\":\"dir\",\"enc\":\"A256GCM\"} so we can hardcode this\r\n const jweCryptoB64Encoded = \"eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0\";\r\n parameters.set(AADServerParamKeys.EAR_JWE_CRYPTO, jweCryptoB64Encoded);\r\n}\r\n\r\n/**\r\n * Adds authorize body parameters to the request parameters\r\n * @param parameters\r\n * @param bodyParameters\r\n */\r\nexport function addPostBodyParameters(\r\n parameters: Map,\r\n bodyParameters: StringDict\r\n): void {\r\n Object.entries(bodyParameters).forEach(([key, value]) => {\r\n if (value) {\r\n parameters.set(key, value);\r\n }\r\n });\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n/**\r\n * Authority types supported by MSAL.\r\n */\r\nexport const AuthorityType = {\r\n Default: 0,\r\n Adfs: 1,\r\n Dsts: 2,\r\n Ciam: 3,\r\n} as const;\r\nexport type AuthorityType = (typeof AuthorityType)[keyof typeof AuthorityType];\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n/**\r\n * Tenant Discovery Response which contains the relevant OAuth endpoints and data needed for authentication and authorization.\r\n */\r\nexport type OpenIdConfigResponse = {\r\n authorization_endpoint: string;\r\n token_endpoint: string;\r\n end_session_endpoint?: string;\r\n issuer: string;\r\n jwks_uri: string;\r\n};\r\n\r\nexport function isOpenIdConfigResponse(response: object): boolean {\r\n return (\r\n response.hasOwnProperty(\"authorization_endpoint\") &&\r\n response.hasOwnProperty(\"token_endpoint\") &&\r\n response.hasOwnProperty(\"issuer\") &&\r\n response.hasOwnProperty(\"jwks_uri\")\r\n );\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { CloudDiscoveryMetadata } from \"./CloudDiscoveryMetadata.js\";\r\n\r\n/**\r\n * The OpenID Configuration Endpoint Response type. Used by the authority class to get relevant OAuth endpoints.\r\n */\r\nexport type CloudInstanceDiscoveryResponse = {\r\n tenant_discovery_endpoint: string;\r\n metadata: Array;\r\n};\r\n\r\nexport function isCloudInstanceDiscoveryResponse(response: object): boolean {\r\n return (\r\n response.hasOwnProperty(\"tenant_discovery_endpoint\") &&\r\n response.hasOwnProperty(\"metadata\")\r\n );\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n/**\r\n * The OpenID Configuration Endpoint Response type. Used by the authority class to get relevant OAuth endpoints.\r\n */\r\nexport type CloudInstanceDiscoveryErrorResponse = {\r\n error: String;\r\n error_description: String;\r\n error_codes?: Array;\r\n timestamp?: String;\r\n trace_id?: String;\r\n correlation_id?: String;\r\n error_uri?: String;\r\n};\r\n\r\nexport function isCloudInstanceDiscoveryErrorResponse(\r\n response: object\r\n): boolean {\r\n return (\r\n response.hasOwnProperty(\"error\") &&\r\n response.hasOwnProperty(\"error_description\")\r\n );\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { Logger } from \"../logger/Logger.js\";\r\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\r\n\r\n/**\r\n * Wraps a function with a performance measurement.\r\n * Usage: invoke(functionToCall, performanceClient, \"EventName\", \"correlationId\")(...argsToPassToFunction)\r\n * @param callback\r\n * @param eventName\r\n * @param logger\r\n * @param telemetryClient\r\n * @param correlationId\r\n * @returns\r\n * @internal\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport const invoke = , U>(\r\n callback: (...args: T) => U,\r\n eventName: string,\r\n logger: Logger,\r\n telemetryClient?: IPerformanceClient,\r\n correlationId?: string\r\n) => {\r\n return (...args: T): U => {\r\n logger.trace(`Executing function ${eventName}`);\r\n const inProgressEvent = telemetryClient?.startMeasurement(\r\n eventName,\r\n correlationId\r\n );\r\n if (correlationId) {\r\n // Track number of times this API is called in a single request\r\n const eventCount = eventName + \"CallCount\";\r\n telemetryClient?.incrementFields(\r\n { [eventCount]: 1 },\r\n correlationId\r\n );\r\n }\r\n try {\r\n const result = callback(...args);\r\n inProgressEvent?.end({\r\n success: true,\r\n });\r\n logger.trace(`Returning result from ${eventName}`);\r\n return result;\r\n } catch (e) {\r\n logger.trace(`Error occurred in ${eventName}`);\r\n try {\r\n logger.trace(JSON.stringify(e));\r\n } catch (e) {\r\n logger.trace(\"Unable to print error message.\");\r\n }\r\n inProgressEvent?.end(\r\n {\r\n success: false,\r\n },\r\n e\r\n );\r\n throw e;\r\n }\r\n };\r\n};\r\n\r\n/**\r\n * Wraps an async function with a performance measurement.\r\n * Usage: invokeAsync(functionToCall, performanceClient, \"EventName\", \"correlationId\")(...argsToPassToFunction)\r\n * @param callback\r\n * @param eventName\r\n * @param logger\r\n * @param telemetryClient\r\n * @param correlationId\r\n * @returns\r\n * @internal\r\n *\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport const invokeAsync = , U>(\r\n callback: (...args: T) => Promise,\r\n eventName: string,\r\n logger: Logger,\r\n telemetryClient?: IPerformanceClient,\r\n correlationId?: string\r\n) => {\r\n return (...args: T): Promise => {\r\n logger.trace(`Executing function ${eventName}`);\r\n const inProgressEvent = telemetryClient?.startMeasurement(\r\n eventName,\r\n correlationId\r\n );\r\n if (correlationId) {\r\n // Track number of times this API is called in a single request\r\n const eventCount = eventName + \"CallCount\";\r\n telemetryClient?.incrementFields(\r\n { [eventCount]: 1 },\r\n correlationId\r\n );\r\n }\r\n telemetryClient?.setPreQueueTime(eventName, correlationId);\r\n return callback(...args)\r\n .then((response) => {\r\n logger.trace(`Returning result from ${eventName}`);\r\n inProgressEvent?.end({\r\n success: true,\r\n });\r\n return response;\r\n })\r\n .catch((e) => {\r\n logger.trace(`Error occurred in ${eventName}`);\r\n try {\r\n logger.trace(JSON.stringify(e));\r\n } catch (e) {\r\n logger.trace(\"Unable to print error message.\");\r\n }\r\n inProgressEvent?.end(\r\n {\r\n success: false,\r\n },\r\n e\r\n );\r\n throw e;\r\n });\r\n };\r\n};\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { INetworkModule } from \"../network/INetworkModule.js\";\r\nimport { NetworkResponse } from \"../network/NetworkResponse.js\";\r\nimport { IMDSBadResponse } from \"../response/IMDSBadResponse.js\";\r\nimport {\r\n Constants,\r\n HttpStatus,\r\n RegionDiscoverySources,\r\n} from \"../utils/Constants.js\";\r\nimport { RegionDiscoveryMetadata } from \"./RegionDiscoveryMetadata.js\";\r\nimport { ImdsOptions } from \"./ImdsOptions.js\";\r\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\r\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\r\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\r\nimport { Logger } from \"../logger/Logger.js\";\r\n\r\nexport class RegionDiscovery {\r\n // Network interface to make requests with.\r\n protected networkInterface: INetworkModule;\r\n // Logger\r\n private logger: Logger;\r\n // Performance client\r\n protected performanceClient: IPerformanceClient | undefined;\r\n // CorrelationId\r\n protected correlationId: string | undefined;\r\n // Options for the IMDS endpoint request\r\n protected static IMDS_OPTIONS: ImdsOptions = {\r\n headers: {\r\n Metadata: \"true\",\r\n },\r\n };\r\n\r\n constructor(\r\n networkInterface: INetworkModule,\r\n logger: Logger,\r\n performanceClient?: IPerformanceClient,\r\n correlationId?: string\r\n ) {\r\n this.networkInterface = networkInterface;\r\n this.logger = logger;\r\n this.performanceClient = performanceClient;\r\n this.correlationId = correlationId;\r\n }\r\n\r\n /**\r\n * Detect the region from the application's environment.\r\n *\r\n * @returns Promise\r\n */\r\n public async detectRegion(\r\n environmentRegion: string | undefined,\r\n regionDiscoveryMetadata: RegionDiscoveryMetadata\r\n ): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.RegionDiscoveryDetectRegion,\r\n this.correlationId\r\n );\r\n\r\n // Initialize auto detected region with the region from the envrionment\r\n let autodetectedRegionName = environmentRegion;\r\n\r\n // Check if a region was detected from the environment, if not, attempt to get the region from IMDS\r\n if (!autodetectedRegionName) {\r\n const options = RegionDiscovery.IMDS_OPTIONS;\r\n\r\n try {\r\n const localIMDSVersionResponse = await invokeAsync(\r\n this.getRegionFromIMDS.bind(this),\r\n PerformanceEvents.RegionDiscoveryGetRegionFromIMDS,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(Constants.IMDS_VERSION, options);\r\n if (localIMDSVersionResponse.status === HttpStatus.SUCCESS) {\r\n autodetectedRegionName = localIMDSVersionResponse.body;\r\n regionDiscoveryMetadata.region_source =\r\n RegionDiscoverySources.IMDS;\r\n }\r\n\r\n // If the response using the local IMDS version failed, try to fetch the current version of IMDS and retry.\r\n if (\r\n localIMDSVersionResponse.status === HttpStatus.BAD_REQUEST\r\n ) {\r\n const currentIMDSVersion = await invokeAsync(\r\n this.getCurrentVersion.bind(this),\r\n PerformanceEvents.RegionDiscoveryGetCurrentVersion,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(options);\r\n if (!currentIMDSVersion) {\r\n regionDiscoveryMetadata.region_source =\r\n RegionDiscoverySources.FAILED_AUTO_DETECTION;\r\n return null;\r\n }\r\n\r\n const currentIMDSVersionResponse = await invokeAsync(\r\n this.getRegionFromIMDS.bind(this),\r\n PerformanceEvents.RegionDiscoveryGetRegionFromIMDS,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(currentIMDSVersion, options);\r\n if (\r\n currentIMDSVersionResponse.status === HttpStatus.SUCCESS\r\n ) {\r\n autodetectedRegionName =\r\n currentIMDSVersionResponse.body;\r\n regionDiscoveryMetadata.region_source =\r\n RegionDiscoverySources.IMDS;\r\n }\r\n }\r\n } catch (e) {\r\n regionDiscoveryMetadata.region_source =\r\n RegionDiscoverySources.FAILED_AUTO_DETECTION;\r\n return null;\r\n }\r\n } else {\r\n regionDiscoveryMetadata.region_source =\r\n RegionDiscoverySources.ENVIRONMENT_VARIABLE;\r\n }\r\n\r\n // If no region was auto detected from the environment or from the IMDS endpoint, mark the attempt as a FAILED_AUTO_DETECTION\r\n if (!autodetectedRegionName) {\r\n regionDiscoveryMetadata.region_source =\r\n RegionDiscoverySources.FAILED_AUTO_DETECTION;\r\n }\r\n\r\n return autodetectedRegionName || null;\r\n }\r\n\r\n /**\r\n * Make the call to the IMDS endpoint\r\n *\r\n * @param imdsEndpointUrl\r\n * @returns Promise>\r\n */\r\n private async getRegionFromIMDS(\r\n version: string,\r\n options: ImdsOptions\r\n ): Promise> {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.RegionDiscoveryGetRegionFromIMDS,\r\n this.correlationId\r\n );\r\n return this.networkInterface.sendGetRequestAsync(\r\n `${Constants.IMDS_ENDPOINT}?api-version=${version}&format=text`,\r\n options,\r\n Constants.IMDS_TIMEOUT\r\n );\r\n }\r\n\r\n /**\r\n * Get the most recent version of the IMDS endpoint available\r\n *\r\n * @returns Promise\r\n */\r\n private async getCurrentVersion(\r\n options: ImdsOptions\r\n ): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.RegionDiscoveryGetCurrentVersion,\r\n this.correlationId\r\n );\r\n try {\r\n const response =\r\n await this.networkInterface.sendGetRequestAsync(\r\n `${Constants.IMDS_ENDPOINT}?format=json`,\r\n options\r\n );\r\n\r\n // When IMDS endpoint is called without the api version query param, bad request response comes back with latest version.\r\n if (\r\n response.status === HttpStatus.BAD_REQUEST &&\r\n response.body &&\r\n response.body[\"newest-versions\"] &&\r\n response.body[\"newest-versions\"].length > 0\r\n ) {\r\n return response.body[\"newest-versions\"][0];\r\n }\r\n\r\n return null;\r\n } catch (e) {\r\n return null;\r\n }\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n/**\r\n * Utility functions for managing date and time operations.\r\n */\r\n\r\n/**\r\n * return the current time in Unix time (seconds).\r\n */\r\nexport function nowSeconds(): number {\r\n // Date.getTime() returns in milliseconds.\r\n return Math.round(new Date().getTime() / 1000.0);\r\n}\r\n\r\n/**\r\n * Converts JS Date object to seconds\r\n * @param date Date\r\n */\r\nexport function toSecondsFromDate(date: Date): number {\r\n // Convert date to seconds\r\n return date.getTime() / 1000;\r\n}\r\n\r\n/**\r\n * Convert seconds to JS Date object. Seconds can be in a number or string format or undefined (will still return a date).\r\n * @param seconds\r\n */\r\nexport function toDateFromSeconds(seconds: number | string | undefined): Date {\r\n if (seconds) {\r\n return new Date(Number(seconds) * 1000);\r\n }\r\n return new Date();\r\n}\r\n\r\n/**\r\n * check if a token is expired based on given UTC time in seconds.\r\n * @param expiresOn\r\n */\r\nexport function isTokenExpired(expiresOn: string, offset: number): boolean {\r\n // check for access token expiry\r\n const expirationSec = Number(expiresOn) || 0;\r\n const offsetCurrentTimeSec = nowSeconds() + offset;\r\n\r\n // If current time + offset is greater than token expiration time, then token is expired.\r\n return offsetCurrentTimeSec > expirationSec;\r\n}\r\n\r\n/**\r\n * Checks if a cache entry is expired based on the last updated time and cache retention days.\r\n * @param lastUpdatedAt\r\n * @param cacheRetentionDays\r\n * @returns\r\n */\r\nexport function isCacheExpired(\r\n lastUpdatedAt: string,\r\n cacheRetentionDays: number\r\n): boolean {\r\n const cacheExpirationTimestamp =\r\n Number(lastUpdatedAt) + cacheRetentionDays * 24 * 60 * 60 * 1000;\r\n return Date.now() > cacheExpirationTimestamp;\r\n}\r\n\r\n/**\r\n * If the current time is earlier than the time that a token was cached at, we must discard the token\r\n * i.e. The system clock was turned back after acquiring the cached token\r\n * @param cachedAt\r\n * @param offset\r\n */\r\nexport function wasClockTurnedBack(cachedAt: string): boolean {\r\n const cachedAtSec = Number(cachedAt);\r\n\r\n return cachedAtSec > nowSeconds();\r\n}\r\n\r\n/**\r\n * Waits for t number of milliseconds\r\n * @param t number\r\n * @param value T\r\n */\r\nexport function delay(t: number, value?: T): Promise {\r\n return new Promise((resolve) => setTimeout(() => resolve(value), t));\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { extractTokenClaims } from \"../../account/AuthToken.js\";\r\nimport { TokenClaims } from \"../../account/TokenClaims.js\";\r\nimport { CloudDiscoveryMetadata } from \"../../authority/CloudDiscoveryMetadata.js\";\r\nimport { OpenIdConfigResponse } from \"../../authority/OpenIdConfigResponse.js\";\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n} from \"../../error/ClientAuthError.js\";\r\nimport {\r\n APP_METADATA,\r\n AUTHORITY_METADATA_CONSTANTS,\r\n AuthenticationScheme,\r\n CredentialType,\r\n SERVER_TELEM_CONSTANTS,\r\n Separators,\r\n ThrottlingConstants,\r\n} from \"../../utils/Constants.js\";\r\nimport * as TimeUtils from \"../../utils/TimeUtils.js\";\r\nimport { AccessTokenEntity } from \"../entities/AccessTokenEntity.js\";\r\nimport { AppMetadataEntity } from \"../entities/AppMetadataEntity.js\";\r\nimport { AuthorityMetadataEntity } from \"../entities/AuthorityMetadataEntity.js\";\r\nimport { CredentialEntity } from \"../entities/CredentialEntity.js\";\r\nimport { IdTokenEntity } from \"../entities/IdTokenEntity.js\";\r\nimport { RefreshTokenEntity } from \"../entities/RefreshTokenEntity.js\";\r\n\r\n/**\r\n * Create IdTokenEntity\r\n * @param homeAccountId\r\n * @param authenticationResult\r\n * @param clientId\r\n * @param authority\r\n */\r\nexport function createIdTokenEntity(\r\n homeAccountId: string,\r\n environment: string,\r\n idToken: string,\r\n clientId: string,\r\n tenantId: string\r\n): IdTokenEntity {\r\n const idTokenEntity: IdTokenEntity = {\r\n credentialType: CredentialType.ID_TOKEN,\r\n homeAccountId: homeAccountId,\r\n environment: environment,\r\n clientId: clientId,\r\n secret: idToken,\r\n realm: tenantId,\r\n lastUpdatedAt: Date.now().toString(), // Set the last updated time to now\r\n };\r\n\r\n return idTokenEntity;\r\n}\r\n\r\n/**\r\n * Create AccessTokenEntity\r\n * @param homeAccountId\r\n * @param environment\r\n * @param accessToken\r\n * @param clientId\r\n * @param tenantId\r\n * @param scopes\r\n * @param expiresOn\r\n * @param extExpiresOn\r\n */\r\nexport function createAccessTokenEntity(\r\n homeAccountId: string,\r\n environment: string,\r\n accessToken: string,\r\n clientId: string,\r\n tenantId: string,\r\n scopes: string,\r\n expiresOn: number,\r\n extExpiresOn: number,\r\n base64Decode: (input: string) => string,\r\n refreshOn?: number,\r\n tokenType?: AuthenticationScheme,\r\n userAssertionHash?: string,\r\n keyId?: string,\r\n requestedClaims?: string,\r\n requestedClaimsHash?: string\r\n): AccessTokenEntity {\r\n const atEntity: AccessTokenEntity = {\r\n homeAccountId: homeAccountId,\r\n credentialType: CredentialType.ACCESS_TOKEN,\r\n secret: accessToken,\r\n cachedAt: TimeUtils.nowSeconds().toString(),\r\n expiresOn: expiresOn.toString(),\r\n extendedExpiresOn: extExpiresOn.toString(),\r\n environment: environment,\r\n clientId: clientId,\r\n realm: tenantId,\r\n target: scopes,\r\n tokenType: tokenType || AuthenticationScheme.BEARER,\r\n lastUpdatedAt: Date.now().toString(), // Set the last updated time to now\r\n };\r\n\r\n if (userAssertionHash) {\r\n atEntity.userAssertionHash = userAssertionHash;\r\n }\r\n\r\n if (refreshOn) {\r\n atEntity.refreshOn = refreshOn.toString();\r\n }\r\n\r\n if (requestedClaims) {\r\n atEntity.requestedClaims = requestedClaims;\r\n atEntity.requestedClaimsHash = requestedClaimsHash;\r\n }\r\n\r\n /*\r\n * Create Access Token With Auth Scheme instead of regular access token\r\n * Cast to lower to handle \"bearer\" from ADFS\r\n */\r\n if (\r\n atEntity.tokenType?.toLowerCase() !==\r\n AuthenticationScheme.BEARER.toLowerCase()\r\n ) {\r\n atEntity.credentialType = CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME;\r\n switch (atEntity.tokenType) {\r\n case AuthenticationScheme.POP:\r\n // Make sure keyId is present and add it to credential\r\n const tokenClaims: TokenClaims | null = extractTokenClaims(\r\n accessToken,\r\n base64Decode\r\n );\r\n if (!tokenClaims?.cnf?.kid) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.tokenClaimsCnfRequiredForSignedJwt\r\n );\r\n }\r\n atEntity.keyId = tokenClaims.cnf.kid;\r\n break;\r\n case AuthenticationScheme.SSH:\r\n atEntity.keyId = keyId;\r\n }\r\n }\r\n\r\n return atEntity;\r\n}\r\n\r\n/**\r\n * Create RefreshTokenEntity\r\n * @param homeAccountId\r\n * @param authenticationResult\r\n * @param clientId\r\n * @param authority\r\n */\r\nexport function createRefreshTokenEntity(\r\n homeAccountId: string,\r\n environment: string,\r\n refreshToken: string,\r\n clientId: string,\r\n familyId?: string,\r\n userAssertionHash?: string,\r\n expiresOn?: number\r\n): RefreshTokenEntity {\r\n const rtEntity: RefreshTokenEntity = {\r\n credentialType: CredentialType.REFRESH_TOKEN,\r\n homeAccountId: homeAccountId,\r\n environment: environment,\r\n clientId: clientId,\r\n secret: refreshToken,\r\n lastUpdatedAt: Date.now().toString(),\r\n };\r\n\r\n if (userAssertionHash) {\r\n rtEntity.userAssertionHash = userAssertionHash;\r\n }\r\n\r\n if (familyId) {\r\n rtEntity.familyId = familyId;\r\n }\r\n\r\n if (expiresOn) {\r\n rtEntity.expiresOn = expiresOn.toString();\r\n }\r\n\r\n return rtEntity;\r\n}\r\n\r\nexport function isCredentialEntity(entity: object): entity is CredentialEntity {\r\n return (\r\n entity.hasOwnProperty(\"homeAccountId\") &&\r\n entity.hasOwnProperty(\"environment\") &&\r\n entity.hasOwnProperty(\"credentialType\") &&\r\n entity.hasOwnProperty(\"clientId\") &&\r\n entity.hasOwnProperty(\"secret\")\r\n );\r\n}\r\n\r\n/**\r\n * Validates an entity: checks for all expected params\r\n * @param entity\r\n */\r\nexport function isAccessTokenEntity(\r\n entity: object\r\n): entity is AccessTokenEntity {\r\n if (!entity) {\r\n return false;\r\n }\r\n\r\n return (\r\n isCredentialEntity(entity) &&\r\n entity.hasOwnProperty(\"realm\") &&\r\n entity.hasOwnProperty(\"target\") &&\r\n (entity[\"credentialType\"] === CredentialType.ACCESS_TOKEN ||\r\n entity[\"credentialType\"] ===\r\n CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME)\r\n );\r\n}\r\n\r\n/**\r\n * Validates an entity: checks for all expected params\r\n * @param entity\r\n */\r\nexport function isIdTokenEntity(entity: object): entity is IdTokenEntity {\r\n if (!entity) {\r\n return false;\r\n }\r\n\r\n return (\r\n isCredentialEntity(entity) &&\r\n entity.hasOwnProperty(\"realm\") &&\r\n entity[\"credentialType\"] === CredentialType.ID_TOKEN\r\n );\r\n}\r\n\r\n/**\r\n * Validates an entity: checks for all expected params\r\n * @param entity\r\n */\r\nexport function isRefreshTokenEntity(\r\n entity: object\r\n): entity is RefreshTokenEntity {\r\n if (!entity) {\r\n return false;\r\n }\r\n\r\n return (\r\n isCredentialEntity(entity) &&\r\n entity[\"credentialType\"] === CredentialType.REFRESH_TOKEN\r\n );\r\n}\r\n\r\n/**\r\n * validates if a given cache entry is \"Telemetry\", parses \r\n * @param key\r\n * @param entity\r\n */\r\nexport function isServerTelemetryEntity(key: string, entity?: object): boolean {\r\n const validateKey: boolean =\r\n key.indexOf(SERVER_TELEM_CONSTANTS.CACHE_KEY) === 0;\r\n let validateEntity: boolean = true;\r\n\r\n if (entity) {\r\n validateEntity =\r\n entity.hasOwnProperty(\"failedRequests\") &&\r\n entity.hasOwnProperty(\"errors\") &&\r\n entity.hasOwnProperty(\"cacheHits\");\r\n }\r\n\r\n return validateKey && validateEntity;\r\n}\r\n\r\n/**\r\n * validates if a given cache entry is \"Throttling\", parses \r\n * @param key\r\n * @param entity\r\n */\r\nexport function isThrottlingEntity(key: string, entity?: object): boolean {\r\n let validateKey: boolean = false;\r\n if (key) {\r\n validateKey = key.indexOf(ThrottlingConstants.THROTTLING_PREFIX) === 0;\r\n }\r\n\r\n let validateEntity: boolean = true;\r\n if (entity) {\r\n validateEntity = entity.hasOwnProperty(\"throttleTime\");\r\n }\r\n\r\n return validateKey && validateEntity;\r\n}\r\n\r\n/**\r\n * Generate AppMetadata Cache Key as per the schema: appmetadata--\r\n */\r\nexport function generateAppMetadataKey({\r\n environment,\r\n clientId,\r\n}: AppMetadataEntity): string {\r\n const appMetaDataKeyArray: Array = [\r\n APP_METADATA,\r\n environment,\r\n clientId,\r\n ];\r\n return appMetaDataKeyArray\r\n .join(Separators.CACHE_KEY_SEPARATOR)\r\n .toLowerCase();\r\n}\r\n\r\n/*\r\n * Validates an entity: checks for all expected params\r\n * @param entity\r\n */\r\nexport function isAppMetadataEntity(key: string, entity: object): boolean {\r\n if (!entity) {\r\n return false;\r\n }\r\n\r\n return (\r\n key.indexOf(APP_METADATA) === 0 &&\r\n entity.hasOwnProperty(\"clientId\") &&\r\n entity.hasOwnProperty(\"environment\")\r\n );\r\n}\r\n\r\n/**\r\n * Validates an entity: checks for all expected params\r\n * @param entity\r\n */\r\nexport function isAuthorityMetadataEntity(\r\n key: string,\r\n entity: object\r\n): boolean {\r\n if (!entity) {\r\n return false;\r\n }\r\n\r\n return (\r\n key.indexOf(AUTHORITY_METADATA_CONSTANTS.CACHE_KEY) === 0 &&\r\n entity.hasOwnProperty(\"aliases\") &&\r\n entity.hasOwnProperty(\"preferred_cache\") &&\r\n entity.hasOwnProperty(\"preferred_network\") &&\r\n entity.hasOwnProperty(\"canonical_authority\") &&\r\n entity.hasOwnProperty(\"authorization_endpoint\") &&\r\n entity.hasOwnProperty(\"token_endpoint\") &&\r\n entity.hasOwnProperty(\"issuer\") &&\r\n entity.hasOwnProperty(\"aliasesFromNetwork\") &&\r\n entity.hasOwnProperty(\"endpointsFromNetwork\") &&\r\n entity.hasOwnProperty(\"expiresAt\") &&\r\n entity.hasOwnProperty(\"jwks_uri\")\r\n );\r\n}\r\n\r\n/**\r\n * Reset the exiresAt value\r\n */\r\nexport function generateAuthorityMetadataExpiresAt(): number {\r\n return (\r\n TimeUtils.nowSeconds() +\r\n AUTHORITY_METADATA_CONSTANTS.REFRESH_TIME_SECONDS\r\n );\r\n}\r\n\r\nexport function updateAuthorityEndpointMetadata(\r\n authorityMetadata: AuthorityMetadataEntity,\r\n updatedValues: OpenIdConfigResponse,\r\n fromNetwork: boolean\r\n): void {\r\n authorityMetadata.authorization_endpoint =\r\n updatedValues.authorization_endpoint;\r\n authorityMetadata.token_endpoint = updatedValues.token_endpoint;\r\n authorityMetadata.end_session_endpoint = updatedValues.end_session_endpoint;\r\n authorityMetadata.issuer = updatedValues.issuer;\r\n authorityMetadata.endpointsFromNetwork = fromNetwork;\r\n authorityMetadata.jwks_uri = updatedValues.jwks_uri;\r\n}\r\n\r\nexport function updateCloudDiscoveryMetadata(\r\n authorityMetadata: AuthorityMetadataEntity,\r\n updatedValues: CloudDiscoveryMetadata,\r\n fromNetwork: boolean\r\n): void {\r\n authorityMetadata.aliases = updatedValues.aliases;\r\n authorityMetadata.preferred_cache = updatedValues.preferred_cache;\r\n authorityMetadata.preferred_network = updatedValues.preferred_network;\r\n authorityMetadata.aliasesFromNetwork = fromNetwork;\r\n}\r\n\r\n/**\r\n * Returns whether or not the data needs to be refreshed\r\n */\r\nexport function isAuthorityMetadataExpired(\r\n metadata: AuthorityMetadataEntity\r\n): boolean {\r\n return metadata.expiresAt <= TimeUtils.nowSeconds();\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthorityType } from \"./AuthorityType.js\";\r\nimport {\r\n isOpenIdConfigResponse,\r\n OpenIdConfigResponse,\r\n} from \"./OpenIdConfigResponse.js\";\r\nimport { UrlString } from \"../url/UrlString.js\";\r\nimport { IUri } from \"../url/IUri.js\";\r\nimport {\r\n createClientAuthError,\r\n ClientAuthErrorCodes,\r\n} from \"../error/ClientAuthError.js\";\r\nimport { INetworkModule } from \"../network/INetworkModule.js\";\r\nimport {\r\n AADAuthorityConstants,\r\n AuthorityMetadataSource,\r\n Constants,\r\n RegionDiscoveryOutcomes,\r\n} from \"../utils/Constants.js\";\r\nimport {\r\n EndpointMetadata,\r\n getCloudDiscoveryMetadataFromHardcodedValues,\r\n getCloudDiscoveryMetadataFromNetworkResponse,\r\n InstanceDiscoveryMetadataAliases,\r\n} from \"./AuthorityMetadata.js\";\r\nimport {\r\n createClientConfigurationError,\r\n ClientConfigurationErrorCodes,\r\n} from \"../error/ClientConfigurationError.js\";\r\nimport { ProtocolMode } from \"./ProtocolMode.js\";\r\nimport { ICacheManager } from \"../cache/interface/ICacheManager.js\";\r\nimport { AuthorityMetadataEntity } from \"../cache/entities/AuthorityMetadataEntity.js\";\r\nimport {\r\n AuthorityOptions,\r\n AzureCloudInstance,\r\n StaticAuthorityOptions,\r\n} from \"./AuthorityOptions.js\";\r\nimport {\r\n CloudInstanceDiscoveryResponse,\r\n isCloudInstanceDiscoveryResponse,\r\n} from \"./CloudInstanceDiscoveryResponse.js\";\r\nimport {\r\n CloudInstanceDiscoveryErrorResponse,\r\n isCloudInstanceDiscoveryErrorResponse,\r\n} from \"./CloudInstanceDiscoveryErrorResponse.js\";\r\nimport { CloudDiscoveryMetadata } from \"./CloudDiscoveryMetadata.js\";\r\nimport { RegionDiscovery } from \"./RegionDiscovery.js\";\r\nimport { RegionDiscoveryMetadata } from \"./RegionDiscoveryMetadata.js\";\r\nimport { ImdsOptions } from \"./ImdsOptions.js\";\r\nimport type { AzureCloudOptions } from \"../config/ClientConfiguration.js\";\r\nimport { Logger } from \"../logger/Logger.js\";\r\nimport { AuthError } from \"../error/AuthError.js\";\r\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\r\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\r\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\r\nimport * as CacheHelpers from \"../cache/utils/CacheHelpers.js\";\r\n\r\n/**\r\n * The authority class validates the authority URIs used by the user, and retrieves the OpenID Configuration Data from the\r\n * endpoint. It will store the pertinent config data in this object for use during token calls.\r\n * @internal\r\n */\r\nexport class Authority {\r\n // Canonical authority url string\r\n private _canonicalAuthority: UrlString;\r\n // Canonicaly authority url components\r\n private _canonicalAuthorityUrlComponents: IUri | null;\r\n // Network interface to make requests with.\r\n protected networkInterface: INetworkModule;\r\n // Cache Manager to cache network responses\r\n protected cacheManager: ICacheManager;\r\n // Protocol mode to construct endpoints\r\n private authorityOptions: AuthorityOptions;\r\n // Authority metadata\r\n private metadata: AuthorityMetadataEntity;\r\n // Region discovery service\r\n private regionDiscovery: RegionDiscovery;\r\n // Region discovery metadata\r\n public regionDiscoveryMetadata: RegionDiscoveryMetadata;\r\n // Logger object\r\n private logger: Logger;\r\n // Performance client\r\n protected performanceClient: IPerformanceClient | undefined;\r\n // Correlation Id\r\n protected correlationId: string;\r\n // Indicates if the authority is fake, for the purpose of a Managed Identity Application\r\n private managedIdentity: boolean;\r\n // Reserved tenant domain names that will not be replaced with tenant id\r\n private static reservedTenantDomains: Set = new Set([\r\n \"{tenant}\",\r\n \"{tenantid}\",\r\n AADAuthorityConstants.COMMON,\r\n AADAuthorityConstants.CONSUMERS,\r\n AADAuthorityConstants.ORGANIZATIONS,\r\n ]);\r\n\r\n constructor(\r\n authority: string,\r\n networkInterface: INetworkModule,\r\n cacheManager: ICacheManager,\r\n authorityOptions: AuthorityOptions,\r\n logger: Logger,\r\n correlationId: string,\r\n performanceClient?: IPerformanceClient,\r\n managedIdentity?: boolean\r\n ) {\r\n this.canonicalAuthority = authority;\r\n this._canonicalAuthority.validateAsUri();\r\n this.networkInterface = networkInterface;\r\n this.cacheManager = cacheManager;\r\n this.authorityOptions = authorityOptions;\r\n this.regionDiscoveryMetadata = {\r\n region_used: undefined,\r\n region_source: undefined,\r\n region_outcome: undefined,\r\n };\r\n this.logger = logger;\r\n this.performanceClient = performanceClient;\r\n this.correlationId = correlationId;\r\n this.managedIdentity = managedIdentity || false;\r\n this.regionDiscovery = new RegionDiscovery(\r\n networkInterface,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Get {@link AuthorityType}\r\n * @param authorityUri {@link IUri}\r\n * @private\r\n */\r\n private getAuthorityType(authorityUri: IUri): AuthorityType {\r\n // CIAM auth url pattern is being standardized as: .ciamlogin.com\r\n if (authorityUri.HostNameAndPort.endsWith(Constants.CIAM_AUTH_URL)) {\r\n return AuthorityType.Ciam;\r\n }\r\n\r\n const pathSegments = authorityUri.PathSegments;\r\n if (pathSegments.length) {\r\n switch (pathSegments[0].toLowerCase()) {\r\n case Constants.ADFS:\r\n return AuthorityType.Adfs;\r\n case Constants.DSTS:\r\n return AuthorityType.Dsts;\r\n default:\r\n break;\r\n }\r\n }\r\n return AuthorityType.Default;\r\n }\r\n\r\n // See above for AuthorityType\r\n public get authorityType(): AuthorityType {\r\n return this.getAuthorityType(this.canonicalAuthorityUrlComponents);\r\n }\r\n\r\n /**\r\n * ProtocolMode enum representing the way endpoints are constructed.\r\n */\r\n public get protocolMode(): ProtocolMode {\r\n return this.authorityOptions.protocolMode;\r\n }\r\n\r\n /**\r\n * Returns authorityOptions which can be used to reinstantiate a new authority instance\r\n */\r\n public get options(): AuthorityOptions {\r\n return this.authorityOptions;\r\n }\r\n\r\n /**\r\n * A URL that is the authority set by the developer\r\n */\r\n public get canonicalAuthority(): string {\r\n return this._canonicalAuthority.urlString;\r\n }\r\n\r\n /**\r\n * Sets canonical authority.\r\n */\r\n public set canonicalAuthority(url: string) {\r\n this._canonicalAuthority = new UrlString(url);\r\n this._canonicalAuthority.validateAsUri();\r\n this._canonicalAuthorityUrlComponents = null;\r\n }\r\n\r\n /**\r\n * Get authority components.\r\n */\r\n public get canonicalAuthorityUrlComponents(): IUri {\r\n if (!this._canonicalAuthorityUrlComponents) {\r\n this._canonicalAuthorityUrlComponents =\r\n this._canonicalAuthority.getUrlComponents();\r\n }\r\n\r\n return this._canonicalAuthorityUrlComponents;\r\n }\r\n\r\n /**\r\n * Get hostname and port i.e. login.microsoftonline.com\r\n */\r\n public get hostnameAndPort(): string {\r\n return this.canonicalAuthorityUrlComponents.HostNameAndPort.toLowerCase();\r\n }\r\n\r\n /**\r\n * Get tenant for authority.\r\n */\r\n public get tenant(): string {\r\n return this.canonicalAuthorityUrlComponents.PathSegments[0];\r\n }\r\n\r\n /**\r\n * OAuth /authorize endpoint for requests\r\n */\r\n public get authorizationEndpoint(): string {\r\n if (this.discoveryComplete()) {\r\n return this.replacePath(this.metadata.authorization_endpoint);\r\n } else {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.endpointResolutionError\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * OAuth /token endpoint for requests\r\n */\r\n public get tokenEndpoint(): string {\r\n if (this.discoveryComplete()) {\r\n return this.replacePath(this.metadata.token_endpoint);\r\n } else {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.endpointResolutionError\r\n );\r\n }\r\n }\r\n\r\n public get deviceCodeEndpoint(): string {\r\n if (this.discoveryComplete()) {\r\n return this.replacePath(\r\n this.metadata.token_endpoint.replace(\"/token\", \"/devicecode\")\r\n );\r\n } else {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.endpointResolutionError\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * OAuth logout endpoint for requests\r\n */\r\n public get endSessionEndpoint(): string {\r\n if (this.discoveryComplete()) {\r\n // ROPC policies may not have end_session_endpoint set\r\n if (!this.metadata.end_session_endpoint) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.endSessionEndpointNotSupported\r\n );\r\n }\r\n return this.replacePath(this.metadata.end_session_endpoint);\r\n } else {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.endpointResolutionError\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * OAuth issuer for requests\r\n */\r\n public get selfSignedJwtAudience(): string {\r\n if (this.discoveryComplete()) {\r\n return this.replacePath(this.metadata.issuer);\r\n } else {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.endpointResolutionError\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Jwks_uri for token signing keys\r\n */\r\n public get jwksUri(): string {\r\n if (this.discoveryComplete()) {\r\n return this.replacePath(this.metadata.jwks_uri);\r\n } else {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.endpointResolutionError\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Returns a flag indicating that tenant name can be replaced in authority {@link IUri}\r\n * @param authorityUri {@link IUri}\r\n * @private\r\n */\r\n private canReplaceTenant(authorityUri: IUri): boolean {\r\n return (\r\n authorityUri.PathSegments.length === 1 &&\r\n !Authority.reservedTenantDomains.has(\r\n authorityUri.PathSegments[0]\r\n ) &&\r\n this.getAuthorityType(authorityUri) === AuthorityType.Default &&\r\n this.protocolMode !== ProtocolMode.OIDC\r\n );\r\n }\r\n\r\n /**\r\n * Replaces tenant in url path with current tenant. Defaults to common.\r\n * @param urlString\r\n */\r\n private replaceTenant(urlString: string): string {\r\n return urlString.replace(/{tenant}|{tenantid}/g, this.tenant);\r\n }\r\n\r\n /**\r\n * Replaces path such as tenant or policy with the current tenant or policy.\r\n * @param urlString\r\n */\r\n private replacePath(urlString: string): string {\r\n let endpoint = urlString;\r\n const cachedAuthorityUrl = new UrlString(\r\n this.metadata.canonical_authority\r\n );\r\n const cachedAuthorityUrlComponents =\r\n cachedAuthorityUrl.getUrlComponents();\r\n const cachedAuthorityParts = cachedAuthorityUrlComponents.PathSegments;\r\n const currentAuthorityParts =\r\n this.canonicalAuthorityUrlComponents.PathSegments;\r\n\r\n currentAuthorityParts.forEach((currentPart, index) => {\r\n let cachedPart = cachedAuthorityParts[index];\r\n if (\r\n index === 0 &&\r\n this.canReplaceTenant(cachedAuthorityUrlComponents)\r\n ) {\r\n const tenantId = new UrlString(\r\n this.metadata.authorization_endpoint\r\n ).getUrlComponents().PathSegments[0];\r\n /**\r\n * Check if AAD canonical authority contains tenant domain name, for example \"testdomain.onmicrosoft.com\",\r\n * by comparing its first path segment to the corresponding authorization endpoint path segment, which is\r\n * always resolved with tenant id by OIDC.\r\n */\r\n if (cachedPart !== tenantId) {\r\n this.logger.verbose(\r\n `Replacing tenant domain name ${cachedPart} with id ${tenantId}`\r\n );\r\n cachedPart = tenantId;\r\n }\r\n }\r\n if (currentPart !== cachedPart) {\r\n endpoint = endpoint.replace(\r\n `/${cachedPart}/`,\r\n `/${currentPart}/`\r\n );\r\n }\r\n });\r\n\r\n return this.replaceTenant(endpoint);\r\n }\r\n\r\n /**\r\n * The default open id configuration endpoint for any canonical authority.\r\n */\r\n protected get defaultOpenIdConfigurationEndpoint(): string {\r\n const canonicalAuthorityHost = this.hostnameAndPort;\r\n if (\r\n this.canonicalAuthority.endsWith(\"v2.0/\") ||\r\n this.authorityType === AuthorityType.Adfs ||\r\n (this.protocolMode === ProtocolMode.OIDC &&\r\n !this.isAliasOfKnownMicrosoftAuthority(canonicalAuthorityHost))\r\n ) {\r\n return `${this.canonicalAuthority}.well-known/openid-configuration`;\r\n }\r\n return `${this.canonicalAuthority}v2.0/.well-known/openid-configuration`;\r\n }\r\n\r\n /**\r\n * Boolean that returns whether or not tenant discovery has been completed.\r\n */\r\n discoveryComplete(): boolean {\r\n return !!this.metadata;\r\n }\r\n\r\n /**\r\n * Perform endpoint discovery to discover aliases, preferred_cache, preferred_network\r\n * and the /authorize, /token and logout endpoints.\r\n */\r\n public async resolveEndpointsAsync(): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.AuthorityResolveEndpointsAsync,\r\n this.correlationId\r\n );\r\n\r\n const metadataEntity = this.getCurrentMetadataEntity();\r\n\r\n const cloudDiscoverySource = await invokeAsync(\r\n this.updateCloudDiscoveryMetadata.bind(this),\r\n PerformanceEvents.AuthorityUpdateCloudDiscoveryMetadata,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(metadataEntity);\r\n this.canonicalAuthority = this.canonicalAuthority.replace(\r\n this.hostnameAndPort,\r\n metadataEntity.preferred_network\r\n );\r\n const endpointSource = await invokeAsync(\r\n this.updateEndpointMetadata.bind(this),\r\n PerformanceEvents.AuthorityUpdateEndpointMetadata,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(metadataEntity);\r\n this.updateCachedMetadata(metadataEntity, cloudDiscoverySource, {\r\n source: endpointSource,\r\n });\r\n this.performanceClient?.addFields(\r\n {\r\n cloudDiscoverySource: cloudDiscoverySource,\r\n authorityEndpointSource: endpointSource,\r\n },\r\n this.correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Returns metadata entity from cache if it exists, otherwiser returns a new metadata entity built\r\n * from the configured canonical authority\r\n * @returns\r\n */\r\n private getCurrentMetadataEntity(): AuthorityMetadataEntity {\r\n let metadataEntity: AuthorityMetadataEntity | null =\r\n this.cacheManager.getAuthorityMetadataByAlias(this.hostnameAndPort);\r\n\r\n if (!metadataEntity) {\r\n metadataEntity = {\r\n aliases: [],\r\n preferred_cache: this.hostnameAndPort,\r\n preferred_network: this.hostnameAndPort,\r\n canonical_authority: this.canonicalAuthority,\r\n authorization_endpoint: \"\",\r\n token_endpoint: \"\",\r\n end_session_endpoint: \"\",\r\n issuer: \"\",\r\n aliasesFromNetwork: false,\r\n endpointsFromNetwork: false,\r\n expiresAt: CacheHelpers.generateAuthorityMetadataExpiresAt(),\r\n jwks_uri: \"\",\r\n };\r\n }\r\n return metadataEntity;\r\n }\r\n\r\n /**\r\n * Updates cached metadata based on metadata source and sets the instance's metadata\r\n * property to the same value\r\n * @param metadataEntity\r\n * @param cloudDiscoverySource\r\n * @param endpointMetadataResult\r\n */\r\n private updateCachedMetadata(\r\n metadataEntity: AuthorityMetadataEntity,\r\n cloudDiscoverySource: AuthorityMetadataSource | null,\r\n endpointMetadataResult: {\r\n source: AuthorityMetadataSource;\r\n metadata?: OpenIdConfigResponse;\r\n } | null\r\n ): void {\r\n if (\r\n cloudDiscoverySource !== AuthorityMetadataSource.CACHE &&\r\n endpointMetadataResult?.source !== AuthorityMetadataSource.CACHE\r\n ) {\r\n // Reset the expiration time unless both values came from a successful cache lookup\r\n metadataEntity.expiresAt =\r\n CacheHelpers.generateAuthorityMetadataExpiresAt();\r\n metadataEntity.canonical_authority = this.canonicalAuthority;\r\n }\r\n\r\n const cacheKey = this.cacheManager.generateAuthorityMetadataCacheKey(\r\n metadataEntity.preferred_cache\r\n );\r\n this.cacheManager.setAuthorityMetadata(cacheKey, metadataEntity);\r\n this.metadata = metadataEntity;\r\n }\r\n\r\n /**\r\n * Update AuthorityMetadataEntity with new endpoints and return where the information came from\r\n * @param metadataEntity\r\n */\r\n private async updateEndpointMetadata(\r\n metadataEntity: AuthorityMetadataEntity\r\n ): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.AuthorityUpdateEndpointMetadata,\r\n this.correlationId\r\n );\r\n\r\n const localMetadata =\r\n this.updateEndpointMetadataFromLocalSources(metadataEntity);\r\n\r\n // Further update may be required for hardcoded metadata if regional metadata is preferred\r\n if (localMetadata) {\r\n if (\r\n localMetadata.source ===\r\n AuthorityMetadataSource.HARDCODED_VALUES\r\n ) {\r\n // If the user prefers to use an azure region replace the global endpoints with regional information.\r\n if (\r\n this.authorityOptions.azureRegionConfiguration?.azureRegion\r\n ) {\r\n if (localMetadata.metadata) {\r\n const hardcodedMetadata = await invokeAsync(\r\n this.updateMetadataWithRegionalInformation.bind(\r\n this\r\n ),\r\n PerformanceEvents.AuthorityUpdateMetadataWithRegionalInformation,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(localMetadata.metadata);\r\n CacheHelpers.updateAuthorityEndpointMetadata(\r\n metadataEntity,\r\n hardcodedMetadata,\r\n false\r\n );\r\n metadataEntity.canonical_authority =\r\n this.canonicalAuthority;\r\n }\r\n }\r\n }\r\n return localMetadata.source;\r\n }\r\n\r\n // Get metadata from network if local sources aren't available\r\n let metadata = await invokeAsync(\r\n this.getEndpointMetadataFromNetwork.bind(this),\r\n PerformanceEvents.AuthorityGetEndpointMetadataFromNetwork,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )();\r\n if (metadata) {\r\n // If the user prefers to use an azure region replace the global endpoints with regional information.\r\n if (this.authorityOptions.azureRegionConfiguration?.azureRegion) {\r\n metadata = await invokeAsync(\r\n this.updateMetadataWithRegionalInformation.bind(this),\r\n PerformanceEvents.AuthorityUpdateMetadataWithRegionalInformation,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(metadata);\r\n }\r\n\r\n CacheHelpers.updateAuthorityEndpointMetadata(\r\n metadataEntity,\r\n metadata,\r\n true\r\n );\r\n return AuthorityMetadataSource.NETWORK;\r\n } else {\r\n // Metadata could not be obtained from the config, cache, network or hardcoded values\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.openIdConfigError,\r\n this.defaultOpenIdConfigurationEndpoint\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Updates endpoint metadata from local sources and returns where the information was retrieved from and the metadata config\r\n * response if the source is hardcoded metadata\r\n * @param metadataEntity\r\n * @returns\r\n */\r\n private updateEndpointMetadataFromLocalSources(\r\n metadataEntity: AuthorityMetadataEntity\r\n ): {\r\n source: AuthorityMetadataSource;\r\n metadata?: OpenIdConfigResponse;\r\n } | null {\r\n this.logger.verbose(\r\n \"Attempting to get endpoint metadata from authority configuration\"\r\n );\r\n const configMetadata = this.getEndpointMetadataFromConfig();\r\n if (configMetadata) {\r\n this.logger.verbose(\r\n \"Found endpoint metadata in authority configuration\"\r\n );\r\n CacheHelpers.updateAuthorityEndpointMetadata(\r\n metadataEntity,\r\n configMetadata,\r\n false\r\n );\r\n return {\r\n source: AuthorityMetadataSource.CONFIG,\r\n };\r\n }\r\n\r\n this.logger.verbose(\r\n \"Did not find endpoint metadata in the config... Attempting to get endpoint metadata from the hardcoded values.\"\r\n );\r\n\r\n // skipAuthorityMetadataCache is used to bypass hardcoded authority metadata and force a network metadata cache lookup and network metadata request if no cached response is available.\r\n if (this.authorityOptions.skipAuthorityMetadataCache) {\r\n this.logger.verbose(\r\n \"Skipping hardcoded metadata cache since skipAuthorityMetadataCache is set to true. Attempting to get endpoint metadata from the network metadata cache.\"\r\n );\r\n } else {\r\n const hardcodedMetadata =\r\n this.getEndpointMetadataFromHardcodedValues();\r\n if (hardcodedMetadata) {\r\n CacheHelpers.updateAuthorityEndpointMetadata(\r\n metadataEntity,\r\n hardcodedMetadata,\r\n false\r\n );\r\n return {\r\n source: AuthorityMetadataSource.HARDCODED_VALUES,\r\n metadata: hardcodedMetadata,\r\n };\r\n } else {\r\n this.logger.verbose(\r\n \"Did not find endpoint metadata in hardcoded values... Attempting to get endpoint metadata from the network metadata cache.\"\r\n );\r\n }\r\n }\r\n\r\n // Check cached metadata entity expiration status\r\n const metadataEntityExpired =\r\n CacheHelpers.isAuthorityMetadataExpired(metadataEntity);\r\n if (\r\n this.isAuthoritySameType(metadataEntity) &&\r\n metadataEntity.endpointsFromNetwork &&\r\n !metadataEntityExpired\r\n ) {\r\n // No need to update\r\n this.logger.verbose(\"Found endpoint metadata in the cache.\");\r\n return { source: AuthorityMetadataSource.CACHE };\r\n } else if (metadataEntityExpired) {\r\n this.logger.verbose(\"The metadata entity is expired.\");\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Compares the number of url components after the domain to determine if the cached\r\n * authority metadata can be used for the requested authority. Protects against same domain different\r\n * authority such as login.microsoftonline.com/tenant and login.microsoftonline.com/tfp/tenant/policy\r\n * @param metadataEntity\r\n */\r\n private isAuthoritySameType(\r\n metadataEntity: AuthorityMetadataEntity\r\n ): boolean {\r\n const cachedAuthorityUrl = new UrlString(\r\n metadataEntity.canonical_authority\r\n );\r\n const cachedParts = cachedAuthorityUrl.getUrlComponents().PathSegments;\r\n\r\n return (\r\n cachedParts.length ===\r\n this.canonicalAuthorityUrlComponents.PathSegments.length\r\n );\r\n }\r\n\r\n /**\r\n * Parse authorityMetadata config option\r\n */\r\n private getEndpointMetadataFromConfig(): OpenIdConfigResponse | null {\r\n if (this.authorityOptions.authorityMetadata) {\r\n try {\r\n return JSON.parse(\r\n this.authorityOptions.authorityMetadata\r\n ) as OpenIdConfigResponse;\r\n } catch (e) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.invalidAuthorityMetadata\r\n );\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Gets OAuth endpoints from the given OpenID configuration endpoint.\r\n *\r\n * @param hasHardcodedMetadata boolean\r\n */\r\n private async getEndpointMetadataFromNetwork(): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.AuthorityGetEndpointMetadataFromNetwork,\r\n this.correlationId\r\n );\r\n\r\n const options: ImdsOptions = {};\r\n\r\n /*\r\n * TODO: Add a timeout if the authority exists in our library's\r\n * hardcoded list of metadata\r\n */\r\n\r\n const openIdConfigurationEndpoint =\r\n this.defaultOpenIdConfigurationEndpoint;\r\n this.logger.verbose(\r\n `Authority.getEndpointMetadataFromNetwork: attempting to retrieve OAuth endpoints from ${openIdConfigurationEndpoint}`\r\n );\r\n\r\n try {\r\n const response =\r\n await this.networkInterface.sendGetRequestAsync(\r\n openIdConfigurationEndpoint,\r\n options\r\n );\r\n const isValidResponse = isOpenIdConfigResponse(response.body);\r\n if (isValidResponse) {\r\n return response.body;\r\n } else {\r\n this.logger.verbose(\r\n `Authority.getEndpointMetadataFromNetwork: could not parse response as OpenID configuration`\r\n );\r\n return null;\r\n }\r\n } catch (e) {\r\n this.logger.verbose(\r\n `Authority.getEndpointMetadataFromNetwork: ${e}`\r\n );\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Get OAuth endpoints for common authorities.\r\n */\r\n private getEndpointMetadataFromHardcodedValues(): OpenIdConfigResponse | null {\r\n if (this.hostnameAndPort in EndpointMetadata) {\r\n return EndpointMetadata[this.hostnameAndPort];\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Update the retrieved metadata with regional information.\r\n * User selected Azure region will be used if configured.\r\n */\r\n private async updateMetadataWithRegionalInformation(\r\n metadata: OpenIdConfigResponse\r\n ): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.AuthorityUpdateMetadataWithRegionalInformation,\r\n this.correlationId\r\n );\r\n\r\n const userConfiguredAzureRegion =\r\n this.authorityOptions.azureRegionConfiguration?.azureRegion;\r\n\r\n if (userConfiguredAzureRegion) {\r\n if (\r\n userConfiguredAzureRegion !==\r\n Constants.AZURE_REGION_AUTO_DISCOVER_FLAG\r\n ) {\r\n this.regionDiscoveryMetadata.region_outcome =\r\n RegionDiscoveryOutcomes.CONFIGURED_NO_AUTO_DETECTION;\r\n this.regionDiscoveryMetadata.region_used =\r\n userConfiguredAzureRegion;\r\n return Authority.replaceWithRegionalInformation(\r\n metadata,\r\n userConfiguredAzureRegion\r\n );\r\n }\r\n\r\n const autodetectedRegionName = await invokeAsync(\r\n this.regionDiscovery.detectRegion.bind(this.regionDiscovery),\r\n PerformanceEvents.RegionDiscoveryDetectRegion,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(\r\n this.authorityOptions.azureRegionConfiguration\r\n ?.environmentRegion,\r\n this.regionDiscoveryMetadata\r\n );\r\n\r\n if (autodetectedRegionName) {\r\n this.regionDiscoveryMetadata.region_outcome =\r\n RegionDiscoveryOutcomes.AUTO_DETECTION_REQUESTED_SUCCESSFUL;\r\n this.regionDiscoveryMetadata.region_used =\r\n autodetectedRegionName;\r\n return Authority.replaceWithRegionalInformation(\r\n metadata,\r\n autodetectedRegionName\r\n );\r\n }\r\n\r\n this.regionDiscoveryMetadata.region_outcome =\r\n RegionDiscoveryOutcomes.AUTO_DETECTION_REQUESTED_FAILED;\r\n }\r\n\r\n return metadata;\r\n }\r\n\r\n /**\r\n * Updates the AuthorityMetadataEntity with new aliases, preferred_network and preferred_cache\r\n * and returns where the information was retrieved from\r\n * @param metadataEntity\r\n * @returns AuthorityMetadataSource\r\n */\r\n private async updateCloudDiscoveryMetadata(\r\n metadataEntity: AuthorityMetadataEntity\r\n ): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.AuthorityUpdateCloudDiscoveryMetadata,\r\n this.correlationId\r\n );\r\n const localMetadataSource =\r\n this.updateCloudDiscoveryMetadataFromLocalSources(metadataEntity);\r\n if (localMetadataSource) {\r\n return localMetadataSource;\r\n }\r\n\r\n // Fallback to network as metadata source\r\n const metadata = await invokeAsync(\r\n this.getCloudDiscoveryMetadataFromNetwork.bind(this),\r\n PerformanceEvents.AuthorityGetCloudDiscoveryMetadataFromNetwork,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )();\r\n\r\n if (metadata) {\r\n CacheHelpers.updateCloudDiscoveryMetadata(\r\n metadataEntity,\r\n metadata,\r\n true\r\n );\r\n return AuthorityMetadataSource.NETWORK;\r\n }\r\n\r\n // Metadata could not be obtained from the config, cache, network or hardcoded values\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.untrustedAuthority\r\n );\r\n }\r\n\r\n private updateCloudDiscoveryMetadataFromLocalSources(\r\n metadataEntity: AuthorityMetadataEntity\r\n ): AuthorityMetadataSource | null {\r\n this.logger.verbose(\r\n \"Attempting to get cloud discovery metadata from authority configuration\"\r\n );\r\n this.logger.verbosePii(\r\n `Known Authorities: ${\r\n this.authorityOptions.knownAuthorities ||\r\n Constants.NOT_APPLICABLE\r\n }`\r\n );\r\n this.logger.verbosePii(\r\n `Authority Metadata: ${\r\n this.authorityOptions.authorityMetadata ||\r\n Constants.NOT_APPLICABLE\r\n }`\r\n );\r\n this.logger.verbosePii(\r\n `Canonical Authority: ${\r\n metadataEntity.canonical_authority || Constants.NOT_APPLICABLE\r\n }`\r\n );\r\n const metadata = this.getCloudDiscoveryMetadataFromConfig();\r\n if (metadata) {\r\n this.logger.verbose(\r\n \"Found cloud discovery metadata in authority configuration\"\r\n );\r\n CacheHelpers.updateCloudDiscoveryMetadata(\r\n metadataEntity,\r\n metadata,\r\n false\r\n );\r\n return AuthorityMetadataSource.CONFIG;\r\n }\r\n\r\n // If the cached metadata came from config but that config was not passed to this instance, we must go to hardcoded values\r\n this.logger.verbose(\r\n \"Did not find cloud discovery metadata in the config... Attempting to get cloud discovery metadata from the hardcoded values.\"\r\n );\r\n\r\n if (this.options.skipAuthorityMetadataCache) {\r\n this.logger.verbose(\r\n \"Skipping hardcoded cloud discovery metadata cache since skipAuthorityMetadataCache is set to true. Attempting to get cloud discovery metadata from the network metadata cache.\"\r\n );\r\n } else {\r\n const hardcodedMetadata =\r\n getCloudDiscoveryMetadataFromHardcodedValues(\r\n this.hostnameAndPort\r\n );\r\n if (hardcodedMetadata) {\r\n this.logger.verbose(\r\n \"Found cloud discovery metadata from hardcoded values.\"\r\n );\r\n CacheHelpers.updateCloudDiscoveryMetadata(\r\n metadataEntity,\r\n hardcodedMetadata,\r\n false\r\n );\r\n return AuthorityMetadataSource.HARDCODED_VALUES;\r\n }\r\n\r\n this.logger.verbose(\r\n \"Did not find cloud discovery metadata in hardcoded values... Attempting to get cloud discovery metadata from the network metadata cache.\"\r\n );\r\n }\r\n\r\n const metadataEntityExpired =\r\n CacheHelpers.isAuthorityMetadataExpired(metadataEntity);\r\n if (\r\n this.isAuthoritySameType(metadataEntity) &&\r\n metadataEntity.aliasesFromNetwork &&\r\n !metadataEntityExpired\r\n ) {\r\n this.logger.verbose(\"Found cloud discovery metadata in the cache.\");\r\n // No need to update\r\n return AuthorityMetadataSource.CACHE;\r\n } else if (metadataEntityExpired) {\r\n this.logger.verbose(\"The metadata entity is expired.\");\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Parse cloudDiscoveryMetadata config or check knownAuthorities\r\n */\r\n private getCloudDiscoveryMetadataFromConfig(): CloudDiscoveryMetadata | null {\r\n // CIAM does not support cloud discovery metadata\r\n if (this.authorityType === AuthorityType.Ciam) {\r\n this.logger.verbose(\r\n \"CIAM authorities do not support cloud discovery metadata, generate the aliases from authority host.\"\r\n );\r\n return Authority.createCloudDiscoveryMetadataFromHost(\r\n this.hostnameAndPort\r\n );\r\n }\r\n\r\n // Check if network response was provided in config\r\n if (this.authorityOptions.cloudDiscoveryMetadata) {\r\n this.logger.verbose(\r\n \"The cloud discovery metadata has been provided as a network response, in the config.\"\r\n );\r\n try {\r\n this.logger.verbose(\r\n \"Attempting to parse the cloud discovery metadata.\"\r\n );\r\n const parsedResponse = JSON.parse(\r\n this.authorityOptions.cloudDiscoveryMetadata\r\n ) as CloudInstanceDiscoveryResponse;\r\n const metadata = getCloudDiscoveryMetadataFromNetworkResponse(\r\n parsedResponse.metadata,\r\n this.hostnameAndPort\r\n );\r\n this.logger.verbose(\"Parsed the cloud discovery metadata.\");\r\n if (metadata) {\r\n this.logger.verbose(\r\n \"There is returnable metadata attached to the parsed cloud discovery metadata.\"\r\n );\r\n return metadata;\r\n } else {\r\n this.logger.verbose(\r\n \"There is no metadata attached to the parsed cloud discovery metadata.\"\r\n );\r\n }\r\n } catch (e) {\r\n this.logger.verbose(\r\n \"Unable to parse the cloud discovery metadata. Throwing Invalid Cloud Discovery Metadata Error.\"\r\n );\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.invalidCloudDiscoveryMetadata\r\n );\r\n }\r\n }\r\n\r\n // If cloudDiscoveryMetadata is empty or does not contain the host, check knownAuthorities\r\n if (this.isInKnownAuthorities()) {\r\n this.logger.verbose(\r\n \"The host is included in knownAuthorities. Creating new cloud discovery metadata from the host.\"\r\n );\r\n return Authority.createCloudDiscoveryMetadataFromHost(\r\n this.hostnameAndPort\r\n );\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Called to get metadata from network if CloudDiscoveryMetadata was not populated by config\r\n *\r\n * @param hasHardcodedMetadata boolean\r\n */\r\n private async getCloudDiscoveryMetadataFromNetwork(): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.AuthorityGetCloudDiscoveryMetadataFromNetwork,\r\n this.correlationId\r\n );\r\n const instanceDiscoveryEndpoint = `${Constants.AAD_INSTANCE_DISCOVERY_ENDPT}${this.canonicalAuthority}oauth2/v2.0/authorize`;\r\n const options: ImdsOptions = {};\r\n\r\n /*\r\n * TODO: Add a timeout if the authority exists in our library's\r\n * hardcoded list of metadata\r\n */\r\n\r\n let match = null;\r\n try {\r\n const response = await this.networkInterface.sendGetRequestAsync<\r\n | CloudInstanceDiscoveryResponse\r\n | CloudInstanceDiscoveryErrorResponse\r\n >(instanceDiscoveryEndpoint, options);\r\n let typedResponseBody:\r\n | CloudInstanceDiscoveryResponse\r\n | CloudInstanceDiscoveryErrorResponse;\r\n let metadata: Array;\r\n if (isCloudInstanceDiscoveryResponse(response.body)) {\r\n typedResponseBody =\r\n response.body as CloudInstanceDiscoveryResponse;\r\n metadata = typedResponseBody.metadata;\r\n\r\n this.logger.verbosePii(\r\n `tenant_discovery_endpoint is: ${typedResponseBody.tenant_discovery_endpoint}`\r\n );\r\n } else if (isCloudInstanceDiscoveryErrorResponse(response.body)) {\r\n this.logger.warning(\r\n `A CloudInstanceDiscoveryErrorResponse was returned. The cloud instance discovery network request's status code is: ${response.status}`\r\n );\r\n\r\n typedResponseBody =\r\n response.body as CloudInstanceDiscoveryErrorResponse;\r\n if (typedResponseBody.error === Constants.INVALID_INSTANCE) {\r\n this.logger.error(\r\n \"The CloudInstanceDiscoveryErrorResponse error is invalid_instance.\"\r\n );\r\n return null;\r\n }\r\n\r\n this.logger.warning(\r\n `The CloudInstanceDiscoveryErrorResponse error is ${typedResponseBody.error}`\r\n );\r\n this.logger.warning(\r\n `The CloudInstanceDiscoveryErrorResponse error description is ${typedResponseBody.error_description}`\r\n );\r\n\r\n this.logger.warning(\r\n \"Setting the value of the CloudInstanceDiscoveryMetadata (returned from the network) to []\"\r\n );\r\n metadata = [];\r\n } else {\r\n this.logger.error(\r\n \"AAD did not return a CloudInstanceDiscoveryResponse or CloudInstanceDiscoveryErrorResponse\"\r\n );\r\n return null;\r\n }\r\n\r\n this.logger.verbose(\r\n \"Attempting to find a match between the developer's authority and the CloudInstanceDiscoveryMetadata returned from the network request.\"\r\n );\r\n match = getCloudDiscoveryMetadataFromNetworkResponse(\r\n metadata,\r\n this.hostnameAndPort\r\n );\r\n } catch (error) {\r\n if (error instanceof AuthError) {\r\n this.logger.error(\r\n `There was a network error while attempting to get the cloud discovery instance metadata.\\nError: ${error.errorCode}\\nError Description: ${error.errorMessage}`\r\n );\r\n } else {\r\n const typedError = error as Error;\r\n this.logger.error(\r\n `A non-MSALJS error was thrown while attempting to get the cloud instance discovery metadata.\\nError: ${typedError.name}\\nError Description: ${typedError.message}`\r\n );\r\n }\r\n\r\n return null;\r\n }\r\n\r\n // Custom Domain scenario, host is trusted because Instance Discovery call succeeded\r\n if (!match) {\r\n this.logger.warning(\r\n \"The developer's authority was not found within the CloudInstanceDiscoveryMetadata returned from the network request.\"\r\n );\r\n this.logger.verbose(\r\n \"Creating custom Authority for custom domain scenario.\"\r\n );\r\n\r\n match = Authority.createCloudDiscoveryMetadataFromHost(\r\n this.hostnameAndPort\r\n );\r\n }\r\n return match;\r\n }\r\n\r\n /**\r\n * Helper function to determine if this host is included in the knownAuthorities config option\r\n */\r\n private isInKnownAuthorities(): boolean {\r\n const matches = this.authorityOptions.knownAuthorities.filter(\r\n (authority) => {\r\n return (\r\n authority &&\r\n UrlString.getDomainFromUrl(authority).toLowerCase() ===\r\n this.hostnameAndPort\r\n );\r\n }\r\n );\r\n return matches.length > 0;\r\n }\r\n\r\n /**\r\n * helper function to populate the authority based on azureCloudOptions\r\n * @param authorityString\r\n * @param azureCloudOptions\r\n */\r\n static generateAuthority(\r\n authorityString: string,\r\n azureCloudOptions?: AzureCloudOptions\r\n ): string {\r\n let authorityAzureCloudInstance;\r\n\r\n if (\r\n azureCloudOptions &&\r\n azureCloudOptions.azureCloudInstance !== AzureCloudInstance.None\r\n ) {\r\n const tenant = azureCloudOptions.tenant\r\n ? azureCloudOptions.tenant\r\n : Constants.DEFAULT_COMMON_TENANT;\r\n authorityAzureCloudInstance = `${azureCloudOptions.azureCloudInstance}/${tenant}/`;\r\n }\r\n\r\n return authorityAzureCloudInstance\r\n ? authorityAzureCloudInstance\r\n : authorityString;\r\n }\r\n\r\n /**\r\n * Creates cloud discovery metadata object from a given host\r\n * @param host\r\n */\r\n static createCloudDiscoveryMetadataFromHost(\r\n host: string\r\n ): CloudDiscoveryMetadata {\r\n return {\r\n preferred_network: host,\r\n preferred_cache: host,\r\n aliases: [host],\r\n };\r\n }\r\n\r\n /**\r\n * helper function to generate environment from authority object\r\n */\r\n getPreferredCache(): string {\r\n if (this.managedIdentity) {\r\n return Constants.DEFAULT_AUTHORITY_HOST;\r\n } else if (this.discoveryComplete()) {\r\n return this.metadata.preferred_cache;\r\n } else {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.endpointResolutionError\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether or not the provided host is an alias of this authority instance\r\n * @param host\r\n */\r\n isAlias(host: string): boolean {\r\n return this.metadata.aliases.indexOf(host) > -1;\r\n }\r\n\r\n /**\r\n * Returns whether or not the provided host is an alias of a known Microsoft authority for purposes of endpoint discovery\r\n * @param host\r\n */\r\n isAliasOfKnownMicrosoftAuthority(host: string): boolean {\r\n return InstanceDiscoveryMetadataAliases.has(host);\r\n }\r\n\r\n /**\r\n * Checks whether the provided host is that of a public cloud authority\r\n *\r\n * @param authority string\r\n * @returns bool\r\n */\r\n static isPublicCloudAuthority(host: string): boolean {\r\n return Constants.KNOWN_PUBLIC_CLOUDS.indexOf(host) >= 0;\r\n }\r\n\r\n /**\r\n * Rebuild the authority string with the region\r\n *\r\n * @param host string\r\n * @param region string\r\n */\r\n static buildRegionalAuthorityString(\r\n host: string,\r\n region: string,\r\n queryString?: string\r\n ): string {\r\n // Create and validate a Url string object with the initial authority string\r\n const authorityUrlInstance = new UrlString(host);\r\n authorityUrlInstance.validateAsUri();\r\n\r\n const authorityUrlParts = authorityUrlInstance.getUrlComponents();\r\n\r\n let hostNameAndPort = `${region}.${authorityUrlParts.HostNameAndPort}`;\r\n\r\n if (this.isPublicCloudAuthority(authorityUrlParts.HostNameAndPort)) {\r\n hostNameAndPort = `${region}.${Constants.REGIONAL_AUTH_PUBLIC_CLOUD_SUFFIX}`;\r\n }\r\n\r\n // Include the query string portion of the url\r\n const url = UrlString.constructAuthorityUriFromObject({\r\n ...authorityUrlInstance.getUrlComponents(),\r\n HostNameAndPort: hostNameAndPort,\r\n }).urlString;\r\n\r\n // Add the query string if a query string was provided\r\n if (queryString) return `${url}?${queryString}`;\r\n\r\n return url;\r\n }\r\n\r\n /**\r\n * Replace the endpoints in the metadata object with their regional equivalents.\r\n *\r\n * @param metadata OpenIdConfigResponse\r\n * @param azureRegion string\r\n */\r\n static replaceWithRegionalInformation(\r\n metadata: OpenIdConfigResponse,\r\n azureRegion: string\r\n ): OpenIdConfigResponse {\r\n const regionalMetadata = { ...metadata };\r\n regionalMetadata.authorization_endpoint =\r\n Authority.buildRegionalAuthorityString(\r\n regionalMetadata.authorization_endpoint,\r\n azureRegion\r\n );\r\n\r\n regionalMetadata.token_endpoint =\r\n Authority.buildRegionalAuthorityString(\r\n regionalMetadata.token_endpoint,\r\n azureRegion\r\n );\r\n\r\n if (regionalMetadata.end_session_endpoint) {\r\n regionalMetadata.end_session_endpoint =\r\n Authority.buildRegionalAuthorityString(\r\n regionalMetadata.end_session_endpoint,\r\n azureRegion\r\n );\r\n }\r\n\r\n return regionalMetadata;\r\n }\r\n\r\n /**\r\n * Transform CIAM_AUTHORIY as per the below rules:\r\n * If no path segments found and it is a CIAM authority (hostname ends with .ciamlogin.com), then transform it\r\n *\r\n * NOTE: The transformation path should go away once STS supports CIAM with the format: `tenantIdorDomain.ciamlogin.com`\r\n * `ciamlogin.com` can also change in the future and we should accommodate the same\r\n *\r\n * @param authority\r\n */\r\n static transformCIAMAuthority(authority: string): string {\r\n let ciamAuthority = authority;\r\n const authorityUrl = new UrlString(authority);\r\n const authorityUrlComponents = authorityUrl.getUrlComponents();\r\n\r\n // check if transformation is needed\r\n if (\r\n authorityUrlComponents.PathSegments.length === 0 &&\r\n authorityUrlComponents.HostNameAndPort.endsWith(\r\n Constants.CIAM_AUTH_URL\r\n )\r\n ) {\r\n const tenantIdOrDomain =\r\n authorityUrlComponents.HostNameAndPort.split(\".\")[0];\r\n ciamAuthority = `${ciamAuthority}${tenantIdOrDomain}${Constants.AAD_TENANT_DOMAIN_SUFFIX}`;\r\n }\r\n\r\n return ciamAuthority;\r\n }\r\n}\r\n\r\n/**\r\n * Extract tenantId from authority\r\n */\r\nexport function getTenantFromAuthorityString(\r\n authority: string\r\n): string | undefined {\r\n const authorityUrl = new UrlString(authority);\r\n const authorityUrlComponents = authorityUrl.getUrlComponents();\r\n /**\r\n * For credential matching purposes, tenantId is the last path segment of the authority URL:\r\n * AAD Authority - domain/tenantId -> Credentials are cached with realm = tenantId\r\n * B2C Authority - domain/{tenantId}?/.../policy -> Credentials are cached with realm = policy\r\n * tenantId is downcased because B2C policies can have mixed case but tfp claim is downcased\r\n *\r\n * Note that we may not have any path segments in certain OIDC scenarios.\r\n */\r\n const tenantId =\r\n authorityUrlComponents.PathSegments.slice(-1)[0]?.toLowerCase();\r\n\r\n switch (tenantId) {\r\n case AADAuthorityConstants.COMMON:\r\n case AADAuthorityConstants.ORGANIZATIONS:\r\n case AADAuthorityConstants.CONSUMERS:\r\n return undefined;\r\n default:\r\n return tenantId;\r\n }\r\n}\r\n\r\nexport function formatAuthorityUri(authorityUri: string): string {\r\n return authorityUri.endsWith(Constants.FORWARD_SLASH)\r\n ? authorityUri\r\n : `${authorityUri}${Constants.FORWARD_SLASH}`;\r\n}\r\n\r\nexport function buildStaticAuthorityOptions(\r\n authOptions: Partial\r\n): StaticAuthorityOptions {\r\n const rawCloudDiscoveryMetadata = authOptions.cloudDiscoveryMetadata;\r\n let cloudDiscoveryMetadata: CloudInstanceDiscoveryResponse | undefined =\r\n undefined;\r\n if (rawCloudDiscoveryMetadata) {\r\n try {\r\n cloudDiscoveryMetadata = JSON.parse(rawCloudDiscoveryMetadata);\r\n } catch (e) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.invalidCloudDiscoveryMetadata\r\n );\r\n }\r\n }\r\n return {\r\n canonicalAuthority: authOptions.authority\r\n ? formatAuthorityUri(authOptions.authority)\r\n : undefined,\r\n knownAuthorities: authOptions.knownAuthorities,\r\n cloudDiscoveryMetadata: cloudDiscoveryMetadata,\r\n };\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { Authority, formatAuthorityUri } from \"./Authority.js\";\r\nimport { INetworkModule } from \"../network/INetworkModule.js\";\r\nimport {\r\n createClientAuthError,\r\n ClientAuthErrorCodes,\r\n} from \"../error/ClientAuthError.js\";\r\nimport { ICacheManager } from \"../cache/interface/ICacheManager.js\";\r\nimport { AuthorityOptions } from \"./AuthorityOptions.js\";\r\nimport { Logger } from \"../logger/Logger.js\";\r\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\r\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\r\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\r\n\r\n/**\r\n * Create an authority object of the correct type based on the url\r\n * Performs basic authority validation - checks to see if the authority is of a valid type (i.e. aad, b2c, adfs)\r\n *\r\n * Also performs endpoint discovery.\r\n *\r\n * @param authorityUri\r\n * @param networkClient\r\n * @param protocolMode\r\n * @internal\r\n */\r\nexport async function createDiscoveredInstance(\r\n authorityUri: string,\r\n networkClient: INetworkModule,\r\n cacheManager: ICacheManager,\r\n authorityOptions: AuthorityOptions,\r\n logger: Logger,\r\n correlationId: string,\r\n performanceClient?: IPerformanceClient\r\n): Promise {\r\n performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.AuthorityFactoryCreateDiscoveredInstance,\r\n correlationId\r\n );\r\n const authorityUriFinal = Authority.transformCIAMAuthority(\r\n formatAuthorityUri(authorityUri)\r\n );\r\n\r\n // Initialize authority and perform discovery endpoint check.\r\n const acquireTokenAuthority: Authority = new Authority(\r\n authorityUriFinal,\r\n networkClient,\r\n cacheManager,\r\n authorityOptions,\r\n logger,\r\n correlationId,\r\n performanceClient\r\n );\r\n\r\n try {\r\n await invokeAsync(\r\n acquireTokenAuthority.resolveEndpointsAsync.bind(\r\n acquireTokenAuthority\r\n ),\r\n PerformanceEvents.AuthorityResolveEndpointsAsync,\r\n logger,\r\n performanceClient,\r\n correlationId\r\n )();\r\n return acquireTokenAuthority;\r\n } catch (e) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.endpointResolutionError\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthError } from \"./AuthError.js\";\r\n\r\n/**\r\n * Error thrown when there is an error with the server code, for example, unavailability.\r\n */\r\nexport class ServerError extends AuthError {\r\n /**\r\n * Server error number;\r\n */\r\n readonly errorNo?: string;\r\n\r\n /**\r\n * Http status number;\r\n */\r\n readonly status?: number;\r\n\r\n constructor(\r\n errorCode?: string,\r\n errorMessage?: string,\r\n subError?: string,\r\n errorNo?: string,\r\n status?: number\r\n ) {\r\n super(errorCode, errorMessage, subError);\r\n this.name = \"ServerError\";\r\n this.errorNo = errorNo;\r\n this.status = status;\r\n\r\n Object.setPrototypeOf(this, ServerError.prototype);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { ShrOptions } from \"../crypto/SignedHttpRequest.js\";\r\nimport { BaseAuthRequest } from \"../request/BaseAuthRequest.js\";\r\nimport { AuthenticationScheme } from \"../utils/Constants.js\";\r\n\r\n/**\r\n * Type representing a unique request thumbprint.\r\n */\r\nexport type RequestThumbprint = {\r\n clientId: string;\r\n authority: string;\r\n scopes: Array;\r\n homeAccountIdentifier?: string;\r\n claims?: string;\r\n authenticationScheme?: AuthenticationScheme;\r\n resourceRequestMethod?: string;\r\n resourceRequestUri?: string;\r\n shrClaims?: string;\r\n sshKid?: string;\r\n shrOptions?: ShrOptions;\r\n embeddedClientId?: string;\r\n};\r\n\r\nexport function getRequestThumbprint(\r\n clientId: string,\r\n request: BaseAuthRequest,\r\n homeAccountId?: string\r\n): RequestThumbprint {\r\n return {\r\n clientId: clientId,\r\n authority: request.authority,\r\n scopes: request.scopes,\r\n homeAccountIdentifier: homeAccountId,\r\n claims: request.claims,\r\n authenticationScheme: request.authenticationScheme,\r\n resourceRequestMethod: request.resourceRequestMethod,\r\n resourceRequestUri: request.resourceRequestUri,\r\n shrClaims: request.shrClaims,\r\n sshKid: request.sshKid,\r\n embeddedClientId:\r\n request.embeddedClientId || request.tokenBodyParameters?.clientId,\r\n };\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { NetworkResponse } from \"./NetworkResponse.js\";\r\nimport { ServerAuthorizationTokenResponse } from \"../response/ServerAuthorizationTokenResponse.js\";\r\nimport {\r\n HeaderNames,\r\n ThrottlingConstants,\r\n Constants,\r\n} from \"../utils/Constants.js\";\r\nimport { CacheManager } from \"../cache/CacheManager.js\";\r\nimport { ServerError } from \"../error/ServerError.js\";\r\nimport {\r\n getRequestThumbprint,\r\n RequestThumbprint,\r\n} from \"./RequestThumbprint.js\";\r\nimport { ThrottlingEntity } from \"../cache/entities/ThrottlingEntity.js\";\r\nimport { BaseAuthRequest } from \"../request/BaseAuthRequest.js\";\r\n\r\n/** @internal */\r\nexport class ThrottlingUtils {\r\n /**\r\n * Prepares a RequestThumbprint to be stored as a key.\r\n * @param thumbprint\r\n */\r\n static generateThrottlingStorageKey(thumbprint: RequestThumbprint): string {\r\n return `${ThrottlingConstants.THROTTLING_PREFIX}.${JSON.stringify(\r\n thumbprint\r\n )}`;\r\n }\r\n\r\n /**\r\n * Performs necessary throttling checks before a network request.\r\n * @param cacheManager\r\n * @param thumbprint\r\n */\r\n static preProcess(\r\n cacheManager: CacheManager,\r\n thumbprint: RequestThumbprint,\r\n correlationId: string\r\n ): void {\r\n const key = ThrottlingUtils.generateThrottlingStorageKey(thumbprint);\r\n const value = cacheManager.getThrottlingCache(key);\r\n\r\n if (value) {\r\n if (value.throttleTime < Date.now()) {\r\n cacheManager.removeItem(key, correlationId);\r\n return;\r\n }\r\n throw new ServerError(\r\n value.errorCodes?.join(\" \") || Constants.EMPTY_STRING,\r\n value.errorMessage,\r\n value.subError\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Performs necessary throttling checks after a network request.\r\n * @param cacheManager\r\n * @param thumbprint\r\n * @param response\r\n */\r\n static postProcess(\r\n cacheManager: CacheManager,\r\n thumbprint: RequestThumbprint,\r\n response: NetworkResponse,\r\n correlationId: string\r\n ): void {\r\n if (\r\n ThrottlingUtils.checkResponseStatus(response) ||\r\n ThrottlingUtils.checkResponseForRetryAfter(response)\r\n ) {\r\n const thumbprintValue: ThrottlingEntity = {\r\n throttleTime: ThrottlingUtils.calculateThrottleTime(\r\n parseInt(response.headers[HeaderNames.RETRY_AFTER])\r\n ),\r\n error: response.body.error,\r\n errorCodes: response.body.error_codes,\r\n errorMessage: response.body.error_description,\r\n subError: response.body.suberror,\r\n };\r\n cacheManager.setThrottlingCache(\r\n ThrottlingUtils.generateThrottlingStorageKey(thumbprint),\r\n thumbprintValue,\r\n correlationId\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Checks a NetworkResponse object's status codes against 429 or 5xx\r\n * @param response\r\n */\r\n static checkResponseStatus(\r\n response: NetworkResponse\r\n ): boolean {\r\n return (\r\n response.status === 429 ||\r\n (response.status >= 500 && response.status < 600)\r\n );\r\n }\r\n\r\n /**\r\n * Checks a NetworkResponse object's RetryAfter header\r\n * @param response\r\n */\r\n static checkResponseForRetryAfter(\r\n response: NetworkResponse\r\n ): boolean {\r\n if (response.headers) {\r\n return (\r\n response.headers.hasOwnProperty(HeaderNames.RETRY_AFTER) &&\r\n (response.status < 200 || response.status >= 300)\r\n );\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Calculates the Unix-time value for a throttle to expire given throttleTime in seconds.\r\n * @param throttleTime\r\n */\r\n static calculateThrottleTime(throttleTime: number): number {\r\n const time = throttleTime <= 0 ? 0 : throttleTime;\r\n\r\n const currentSeconds = Date.now() / 1000;\r\n return Math.floor(\r\n Math.min(\r\n currentSeconds +\r\n (time || ThrottlingConstants.DEFAULT_THROTTLE_TIME_SECONDS),\r\n currentSeconds +\r\n ThrottlingConstants.DEFAULT_MAX_THROTTLE_TIME_SECONDS\r\n ) * 1000\r\n );\r\n }\r\n\r\n static removeThrottle(\r\n cacheManager: CacheManager,\r\n clientId: string,\r\n request: BaseAuthRequest,\r\n homeAccountIdentifier?: string\r\n ): void {\r\n const thumbprint = getRequestThumbprint(\r\n clientId,\r\n request,\r\n homeAccountIdentifier\r\n );\r\n const key = this.generateThrottlingStorageKey(thumbprint);\r\n cacheManager.removeItem(key, request.correlationId);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthError } from \"./AuthError.js\";\r\n\r\n/**\r\n * Represents network related errors\r\n */\r\nexport class NetworkError extends AuthError {\r\n error: AuthError;\r\n httpStatus?: number;\r\n responseHeaders?: Record;\r\n\r\n constructor(\r\n error: AuthError,\r\n httpStatus?: number,\r\n responseHeaders?: Record\r\n ) {\r\n super(error.errorCode, error.errorMessage, error.subError);\r\n\r\n Object.setPrototypeOf(this, NetworkError.prototype);\r\n this.name = \"NetworkError\";\r\n this.error = error;\r\n this.httpStatus = httpStatus;\r\n this.responseHeaders = responseHeaders;\r\n }\r\n}\r\n\r\n/**\r\n * Creates NetworkError object for a failed network request\r\n * @param error - Error to be thrown back to the caller\r\n * @param httpStatus - Status code of the network request\r\n * @param responseHeaders - Response headers of the network request, when available\r\n * @returns NetworkError object\r\n */\r\nexport function createNetworkError(\r\n error: AuthError,\r\n httpStatus?: number,\r\n responseHeaders?: Record,\r\n additionalError?: Error\r\n): NetworkError {\r\n error.errorMessage = `${error.errorMessage}, additionalErrorInfo: error.name:${additionalError?.name}, error.message:${additionalError?.message}`;\r\n return new NetworkError(error, httpStatus, responseHeaders);\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n ClientConfiguration,\r\n buildClientConfiguration,\r\n CommonClientConfiguration,\r\n} from \"../config/ClientConfiguration.js\";\r\nimport {\r\n INetworkModule,\r\n NetworkRequestOptions,\r\n} from \"../network/INetworkModule.js\";\r\nimport { NetworkResponse } from \"../network/NetworkResponse.js\";\r\nimport { ICrypto } from \"../crypto/ICrypto.js\";\r\nimport { Authority } from \"../authority/Authority.js\";\r\nimport { Logger } from \"../logger/Logger.js\";\r\nimport { Constants, HeaderNames } from \"../utils/Constants.js\";\r\nimport { ServerAuthorizationTokenResponse } from \"../response/ServerAuthorizationTokenResponse.js\";\r\nimport { CacheManager } from \"../cache/CacheManager.js\";\r\nimport { ServerTelemetryManager } from \"../telemetry/server/ServerTelemetryManager.js\";\r\nimport { RequestThumbprint } from \"../network/RequestThumbprint.js\";\r\nimport { version, name } from \"../packageMetadata.js\";\r\nimport { CcsCredential, CcsCredentialType } from \"../account/CcsCredential.js\";\r\nimport { buildClientInfoFromHomeAccountId } from \"../account/ClientInfo.js\";\r\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\r\nimport * as RequestParameterBuilder from \"../request/RequestParameterBuilder.js\";\r\nimport * as UrlUtils from \"../utils/UrlUtils.js\";\r\nimport { BaseAuthRequest } from \"../request/BaseAuthRequest.js\";\r\nimport { createDiscoveredInstance } from \"../authority/AuthorityFactory.js\";\r\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\r\nimport { ThrottlingUtils } from \"../network/ThrottlingUtils.js\";\r\nimport { AuthError } from \"../error/AuthError.js\";\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n} from \"../error/ClientAuthError.js\";\r\nimport { NetworkError } from \"../error/NetworkError.js\";\r\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\r\n\r\n/**\r\n * Base application class which will construct requests to send to and handle responses from the Microsoft STS using the authorization code flow.\r\n * @internal\r\n */\r\nexport abstract class BaseClient {\r\n // Logger object\r\n public logger: Logger;\r\n\r\n // Application config\r\n protected config: CommonClientConfiguration;\r\n\r\n // Crypto Interface\r\n protected cryptoUtils: ICrypto;\r\n\r\n // Storage Interface\r\n protected cacheManager: CacheManager;\r\n\r\n // Network Interface\r\n protected networkClient: INetworkModule;\r\n\r\n // Server Telemetry Manager\r\n protected serverTelemetryManager: ServerTelemetryManager | null;\r\n\r\n // Default authority object\r\n public authority: Authority;\r\n\r\n // Performance telemetry client\r\n protected performanceClient?: IPerformanceClient;\r\n\r\n protected constructor(\r\n configuration: ClientConfiguration,\r\n performanceClient?: IPerformanceClient\r\n ) {\r\n // Set the configuration\r\n this.config = buildClientConfiguration(configuration);\r\n\r\n // Initialize the logger\r\n this.logger = new Logger(this.config.loggerOptions, name, version);\r\n\r\n // Initialize crypto\r\n this.cryptoUtils = this.config.cryptoInterface;\r\n\r\n // Initialize storage interface\r\n this.cacheManager = this.config.storageInterface;\r\n\r\n // Set the network interface\r\n this.networkClient = this.config.networkInterface;\r\n\r\n // Set TelemetryManager\r\n this.serverTelemetryManager = this.config.serverTelemetryManager;\r\n\r\n // set Authority\r\n this.authority = this.config.authOptions.authority;\r\n\r\n // set performance telemetry client\r\n this.performanceClient = performanceClient;\r\n }\r\n\r\n /**\r\n * Creates default headers for requests to token endpoint\r\n */\r\n protected createTokenRequestHeaders(\r\n ccsCred?: CcsCredential\r\n ): Record {\r\n const headers: Record = {};\r\n headers[HeaderNames.CONTENT_TYPE] = Constants.URL_FORM_CONTENT_TYPE;\r\n if (!this.config.systemOptions.preventCorsPreflight && ccsCred) {\r\n switch (ccsCred.type) {\r\n case CcsCredentialType.HOME_ACCOUNT_ID:\r\n try {\r\n const clientInfo = buildClientInfoFromHomeAccountId(\r\n ccsCred.credential\r\n );\r\n headers[\r\n HeaderNames.CCS_HEADER\r\n ] = `Oid:${clientInfo.uid}@${clientInfo.utid}`;\r\n } catch (e) {\r\n this.logger.verbose(\r\n \"Could not parse home account ID for CCS Header: \" +\r\n e\r\n );\r\n }\r\n break;\r\n case CcsCredentialType.UPN:\r\n headers[\r\n HeaderNames.CCS_HEADER\r\n ] = `UPN: ${ccsCred.credential}`;\r\n break;\r\n }\r\n }\r\n return headers;\r\n }\r\n\r\n /**\r\n * Http post to token endpoint\r\n * @param tokenEndpoint\r\n * @param queryString\r\n * @param headers\r\n * @param thumbprint\r\n */\r\n protected async executePostToTokenEndpoint(\r\n tokenEndpoint: string,\r\n queryString: string,\r\n headers: Record,\r\n thumbprint: RequestThumbprint,\r\n correlationId: string,\r\n queuedEvent?: string\r\n ): Promise> {\r\n if (queuedEvent) {\r\n this.performanceClient?.addQueueMeasurement(\r\n queuedEvent,\r\n correlationId\r\n );\r\n }\r\n\r\n const response =\r\n await this.sendPostRequest(\r\n thumbprint,\r\n tokenEndpoint,\r\n { body: queryString, headers: headers },\r\n correlationId\r\n );\r\n\r\n if (\r\n this.config.serverTelemetryManager &&\r\n response.status < 500 &&\r\n response.status !== 429\r\n ) {\r\n // Telemetry data successfully logged by server, clear Telemetry cache\r\n this.config.serverTelemetryManager.clearTelemetryCache();\r\n }\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Wraps sendPostRequestAsync with necessary preflight and postflight logic\r\n * @param thumbprint - Request thumbprint for throttling\r\n * @param tokenEndpoint - Endpoint to make the POST to\r\n * @param options - Body and Headers to include on the POST request\r\n * @param correlationId - CorrelationId for telemetry\r\n */\r\n async sendPostRequest(\r\n thumbprint: RequestThumbprint,\r\n tokenEndpoint: string,\r\n options: NetworkRequestOptions,\r\n correlationId: string\r\n ): Promise> {\r\n ThrottlingUtils.preProcess(\r\n this.cacheManager,\r\n thumbprint,\r\n correlationId\r\n );\r\n\r\n let response;\r\n try {\r\n response = await invokeAsync(\r\n this.networkClient.sendPostRequestAsync.bind(\r\n this.networkClient\r\n ),\r\n PerformanceEvents.NetworkClientSendPostRequestAsync,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(tokenEndpoint, options);\r\n const responseHeaders = response.headers || {};\r\n this.performanceClient?.addFields(\r\n {\r\n refreshTokenSize: response.body.refresh_token?.length || 0,\r\n httpVerToken:\r\n responseHeaders[HeaderNames.X_MS_HTTP_VERSION] || \"\",\r\n requestId:\r\n responseHeaders[HeaderNames.X_MS_REQUEST_ID] || \"\",\r\n },\r\n correlationId\r\n );\r\n } catch (e) {\r\n if (e instanceof NetworkError) {\r\n const responseHeaders = e.responseHeaders;\r\n if (responseHeaders) {\r\n this.performanceClient?.addFields(\r\n {\r\n httpVerToken:\r\n responseHeaders[\r\n HeaderNames.X_MS_HTTP_VERSION\r\n ] || \"\",\r\n requestId:\r\n responseHeaders[HeaderNames.X_MS_REQUEST_ID] ||\r\n \"\",\r\n contentTypeHeader:\r\n responseHeaders[HeaderNames.CONTENT_TYPE] ||\r\n undefined,\r\n contentLengthHeader:\r\n responseHeaders[HeaderNames.CONTENT_LENGTH] ||\r\n undefined,\r\n httpStatus: e.httpStatus,\r\n },\r\n correlationId\r\n );\r\n }\r\n throw e.error;\r\n }\r\n if (e instanceof AuthError) {\r\n throw e;\r\n } else {\r\n throw createClientAuthError(ClientAuthErrorCodes.networkError);\r\n }\r\n }\r\n\r\n ThrottlingUtils.postProcess(\r\n this.cacheManager,\r\n thumbprint,\r\n response,\r\n correlationId\r\n );\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Updates the authority object of the client. Endpoint discovery must be completed.\r\n * @param updatedAuthority\r\n */\r\n async updateAuthority(\r\n cloudInstanceHostname: string,\r\n correlationId: string\r\n ): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.UpdateTokenEndpointAuthority,\r\n correlationId\r\n );\r\n const cloudInstanceAuthorityUri = `https://${cloudInstanceHostname}/${this.authority.tenant}/`;\r\n const cloudInstanceAuthority = await createDiscoveredInstance(\r\n cloudInstanceAuthorityUri,\r\n this.networkClient,\r\n this.cacheManager,\r\n this.authority.options,\r\n this.logger,\r\n correlationId,\r\n this.performanceClient\r\n );\r\n this.authority = cloudInstanceAuthority;\r\n }\r\n\r\n /**\r\n * Creates query string for the /token request\r\n * @param request\r\n */\r\n createTokenQueryParameters(request: BaseAuthRequest): string {\r\n const parameters = new Map();\r\n\r\n if (request.embeddedClientId) {\r\n RequestParameterBuilder.addBrokerParameters(\r\n parameters,\r\n this.config.authOptions.clientId,\r\n this.config.authOptions.redirectUri\r\n );\r\n }\r\n\r\n if (request.tokenQueryParameters) {\r\n RequestParameterBuilder.addExtraQueryParameters(\r\n parameters,\r\n request.tokenQueryParameters\r\n );\r\n }\r\n\r\n RequestParameterBuilder.addCorrelationId(\r\n parameters,\r\n request.correlationId\r\n );\r\n\r\n RequestParameterBuilder.instrumentBrokerParams(\r\n parameters,\r\n request.correlationId,\r\n this.performanceClient\r\n );\r\n return UrlUtils.mapToQueryString(parameters);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n/**\r\n * Type which describes Id Token claims known by MSAL.\r\n */\r\nexport type TokenClaims = {\r\n /**\r\n * Audience\r\n */\r\n aud?: string;\r\n /**\r\n * Issuer\r\n */\r\n iss?: string;\r\n /**\r\n * Issued at\r\n */\r\n iat?: number;\r\n /**\r\n * Not valid before\r\n */\r\n nbf?: number;\r\n /**\r\n * Immutable object identifier, this ID uniquely identifies the user across applications\r\n */\r\n oid?: string;\r\n /**\r\n * Immutable subject identifier, this is a pairwise identifier - it is unique to a particular application ID\r\n */\r\n sub?: string;\r\n /**\r\n * Users' tenant or '9188040d-6c67-4c5b-b112-36a304b66dad' for personal accounts.\r\n */\r\n tid?: string;\r\n /**\r\n * Trusted Framework Policy (B2C) The name of the policy that was used to acquire the ID token.\r\n */\r\n tfp?: string;\r\n /**\r\n * Authentication Context Class Reference (B2C) Used only with older policies.\r\n */\r\n acr?: string;\r\n ver?: string;\r\n upn?: string;\r\n preferred_username?: string;\r\n login_hint?: string;\r\n emails?: string[];\r\n name?: string;\r\n nonce?: string;\r\n /**\r\n * Expiration\r\n */\r\n exp?: number;\r\n home_oid?: string;\r\n sid?: string;\r\n cloud_instance_host_name?: string;\r\n cnf?: {\r\n kid: string;\r\n };\r\n x5c_ca?: string[];\r\n ts?: number;\r\n at?: string;\r\n u?: string;\r\n p?: string;\r\n m?: string;\r\n roles?: string[];\r\n amr?: string[];\r\n idp?: string;\r\n auth_time?: number;\r\n /**\r\n * \tRegion of the resource tenant\r\n */\r\n tenant_region_scope?: string;\r\n tenant_region_sub_scope?: string;\r\n};\r\n\r\n/**\r\n * Gets tenantId from available ID token claims to set as credential realm with the following precedence:\r\n * 1. tid - if the token is acquired from an Azure AD tenant tid will be present\r\n * 2. tfp - if the token is acquired from a modern B2C tenant tfp should be present\r\n * 3. acr - if the token is acquired from a legacy B2C tenant acr should be present\r\n * Downcased to match the realm case-insensitive comparison requirements\r\n * @param idTokenClaims\r\n * @returns\r\n */\r\nexport function getTenantIdFromIdTokenClaims(\r\n idTokenClaims?: TokenClaims\r\n): string | null {\r\n if (idTokenClaims) {\r\n const tenantId =\r\n idTokenClaims.tid || idTokenClaims.tfp || idTokenClaims.acr;\r\n return tenantId || null;\r\n }\r\n return null;\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { CacheAccountType } from \"../../utils/Constants.js\";\r\nimport type { Authority } from \"../../authority/Authority.js\";\r\nimport { ICrypto } from \"../../crypto/ICrypto.js\";\r\nimport { ClientInfo, buildClientInfo } from \"../../account/ClientInfo.js\";\r\nimport {\r\n AccountInfo,\r\n TenantProfile,\r\n buildTenantProfile,\r\n} from \"../../account/AccountInfo.js\";\r\nimport {\r\n createClientAuthError,\r\n ClientAuthErrorCodes,\r\n} from \"../../error/ClientAuthError.js\";\r\nimport { AuthorityType } from \"../../authority/AuthorityType.js\";\r\nimport { Logger } from \"../../logger/Logger.js\";\r\nimport {\r\n TokenClaims,\r\n getTenantIdFromIdTokenClaims,\r\n} from \"../../account/TokenClaims.js\";\r\nimport { ProtocolMode } from \"../../authority/ProtocolMode.js\";\r\n\r\n/**\r\n * Type that defines required and optional parameters for an Account field (based on universal cache schema implemented by all MSALs).\r\n *\r\n * Key : Value Schema\r\n *\r\n * Key: --\r\n *\r\n * Value Schema:\r\n * {\r\n * homeAccountId: home account identifier for the auth scheme,\r\n * environment: entity that issued the token, represented as a full host\r\n * realm: Full tenant or organizational identifier that the account belongs to\r\n * localAccountId: Original tenant-specific accountID, usually used for legacy cases\r\n * username: primary username that represents the user, usually corresponds to preferred_username in the v2 endpt\r\n * authorityType: Accounts authority type as a string\r\n * name: Full name for the account, including given name and family name,\r\n * lastModificationTime: last time this entity was modified in the cache\r\n * lastModificationApp:\r\n * nativeAccountId: Account identifier on the native device\r\n * tenantProfiles: Array of tenant profile objects for each tenant that the account has authenticated with in the browser\r\n * }\r\n * @internal\r\n */\r\nexport class AccountEntity {\r\n homeAccountId: string;\r\n environment: string;\r\n realm: string;\r\n localAccountId: string;\r\n username: string;\r\n authorityType: string;\r\n loginHint?: string;\r\n clientInfo?: string;\r\n name?: string;\r\n lastModificationTime?: string;\r\n lastModificationApp?: string;\r\n cloudGraphHostName?: string;\r\n msGraphHost?: string;\r\n nativeAccountId?: string;\r\n tenantProfiles?: Array;\r\n lastUpdatedAt: string;\r\n\r\n /**\r\n * Returns the AccountInfo interface for this account.\r\n */\r\n getAccountInfo(): AccountInfo {\r\n return {\r\n homeAccountId: this.homeAccountId,\r\n environment: this.environment,\r\n tenantId: this.realm,\r\n username: this.username,\r\n localAccountId: this.localAccountId,\r\n loginHint: this.loginHint,\r\n name: this.name,\r\n nativeAccountId: this.nativeAccountId,\r\n authorityType: this.authorityType,\r\n // Deserialize tenant profiles array into a Map\r\n tenantProfiles: new Map(\r\n (this.tenantProfiles || []).map((tenantProfile) => {\r\n return [tenantProfile.tenantId, tenantProfile];\r\n })\r\n ),\r\n };\r\n }\r\n\r\n /**\r\n * Returns true if the account entity is in single tenant format (outdated), false otherwise\r\n */\r\n isSingleTenant(): boolean {\r\n return !this.tenantProfiles;\r\n }\r\n\r\n /**\r\n * Build Account cache from IdToken, clientInfo and authority/policy. Associated with AAD.\r\n * @param accountDetails\r\n */\r\n static createAccount(\r\n accountDetails: {\r\n homeAccountId: string;\r\n idTokenClaims?: TokenClaims;\r\n clientInfo?: string;\r\n cloudGraphHostName?: string;\r\n msGraphHost?: string;\r\n environment?: string;\r\n nativeAccountId?: string;\r\n tenantProfiles?: Array;\r\n },\r\n authority: Authority,\r\n base64Decode?: (input: string) => string\r\n ): AccountEntity {\r\n const account: AccountEntity = new AccountEntity();\r\n\r\n if (authority.authorityType === AuthorityType.Adfs) {\r\n account.authorityType = CacheAccountType.ADFS_ACCOUNT_TYPE;\r\n } else if (authority.protocolMode === ProtocolMode.OIDC) {\r\n account.authorityType = CacheAccountType.GENERIC_ACCOUNT_TYPE;\r\n } else {\r\n account.authorityType = CacheAccountType.MSSTS_ACCOUNT_TYPE;\r\n }\r\n\r\n let clientInfo: ClientInfo | undefined;\r\n\r\n if (accountDetails.clientInfo && base64Decode) {\r\n clientInfo = buildClientInfo(\r\n accountDetails.clientInfo,\r\n base64Decode\r\n );\r\n }\r\n\r\n account.clientInfo = accountDetails.clientInfo;\r\n account.homeAccountId = accountDetails.homeAccountId;\r\n account.nativeAccountId = accountDetails.nativeAccountId;\r\n\r\n const env =\r\n accountDetails.environment ||\r\n (authority && authority.getPreferredCache());\r\n\r\n if (!env) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.invalidCacheEnvironment\r\n );\r\n }\r\n\r\n account.environment = env;\r\n // non AAD scenarios can have empty realm\r\n account.realm =\r\n clientInfo?.utid ||\r\n getTenantIdFromIdTokenClaims(accountDetails.idTokenClaims) ||\r\n \"\";\r\n\r\n // How do you account for MSA CID here?\r\n account.localAccountId =\r\n clientInfo?.uid ||\r\n accountDetails.idTokenClaims?.oid ||\r\n accountDetails.idTokenClaims?.sub ||\r\n \"\";\r\n\r\n /*\r\n * In B2C scenarios the emails claim is used instead of preferred_username and it is an array.\r\n * In most cases it will contain a single email. This field should not be relied upon if a custom\r\n * policy is configured to return more than 1 email.\r\n */\r\n const preferredUsername =\r\n accountDetails.idTokenClaims?.preferred_username ||\r\n accountDetails.idTokenClaims?.upn;\r\n const email = accountDetails.idTokenClaims?.emails\r\n ? accountDetails.idTokenClaims.emails[0]\r\n : null;\r\n\r\n account.username = preferredUsername || email || \"\";\r\n account.loginHint = accountDetails.idTokenClaims?.login_hint;\r\n account.name = accountDetails.idTokenClaims?.name || \"\";\r\n\r\n account.cloudGraphHostName = accountDetails.cloudGraphHostName;\r\n account.msGraphHost = accountDetails.msGraphHost;\r\n\r\n if (accountDetails.tenantProfiles) {\r\n account.tenantProfiles = accountDetails.tenantProfiles;\r\n } else {\r\n const tenantProfile = buildTenantProfile(\r\n accountDetails.homeAccountId,\r\n account.localAccountId,\r\n account.realm,\r\n accountDetails.idTokenClaims\r\n );\r\n account.tenantProfiles = [tenantProfile];\r\n }\r\n\r\n return account;\r\n }\r\n\r\n /**\r\n * Creates an AccountEntity object from AccountInfo\r\n * @param accountInfo\r\n * @param cloudGraphHostName\r\n * @param msGraphHost\r\n * @returns\r\n */\r\n static createFromAccountInfo(\r\n accountInfo: AccountInfo,\r\n cloudGraphHostName?: string,\r\n msGraphHost?: string\r\n ): AccountEntity {\r\n const account: AccountEntity = new AccountEntity();\r\n\r\n account.authorityType =\r\n accountInfo.authorityType || CacheAccountType.GENERIC_ACCOUNT_TYPE;\r\n account.homeAccountId = accountInfo.homeAccountId;\r\n account.localAccountId = accountInfo.localAccountId;\r\n account.nativeAccountId = accountInfo.nativeAccountId;\r\n\r\n account.realm = accountInfo.tenantId;\r\n account.environment = accountInfo.environment;\r\n\r\n account.username = accountInfo.username;\r\n account.name = accountInfo.name;\r\n account.loginHint = accountInfo.loginHint;\r\n\r\n account.cloudGraphHostName = cloudGraphHostName;\r\n account.msGraphHost = msGraphHost;\r\n // Serialize tenant profiles map into an array\r\n account.tenantProfiles = Array.from(\r\n accountInfo.tenantProfiles?.values() || []\r\n );\r\n\r\n return account;\r\n }\r\n\r\n /**\r\n * Generate HomeAccountId from server response\r\n * @param serverClientInfo\r\n * @param authType\r\n */\r\n static generateHomeAccountId(\r\n serverClientInfo: string,\r\n authType: AuthorityType,\r\n logger: Logger,\r\n cryptoObj: ICrypto,\r\n idTokenClaims?: TokenClaims\r\n ): string {\r\n // since ADFS/DSTS do not have tid and does not set client_info\r\n if (\r\n !(\r\n authType === AuthorityType.Adfs ||\r\n authType === AuthorityType.Dsts\r\n )\r\n ) {\r\n // for cases where there is clientInfo\r\n if (serverClientInfo) {\r\n try {\r\n const clientInfo = buildClientInfo(\r\n serverClientInfo,\r\n cryptoObj.base64Decode\r\n );\r\n if (clientInfo.uid && clientInfo.utid) {\r\n return `${clientInfo.uid}.${clientInfo.utid}`;\r\n }\r\n } catch (e) {}\r\n }\r\n logger.warning(\"No client info in response\");\r\n }\r\n\r\n // default to \"sub\" claim\r\n return idTokenClaims?.sub || \"\";\r\n }\r\n\r\n /**\r\n * Validates an entity: checks for all expected params\r\n * @param entity\r\n */\r\n static isAccountEntity(entity: object): boolean {\r\n if (!entity) {\r\n return false;\r\n }\r\n\r\n return (\r\n entity.hasOwnProperty(\"homeAccountId\") &&\r\n entity.hasOwnProperty(\"environment\") &&\r\n entity.hasOwnProperty(\"realm\") &&\r\n entity.hasOwnProperty(\"localAccountId\") &&\r\n entity.hasOwnProperty(\"username\") &&\r\n entity.hasOwnProperty(\"authorityType\")\r\n );\r\n }\r\n\r\n /**\r\n * Helper function to determine whether 2 accountInfo objects represent the same account\r\n * @param accountA\r\n * @param accountB\r\n * @param compareClaims - If set to true idTokenClaims will also be compared to determine account equality\r\n */\r\n static accountInfoIsEqual(\r\n accountA: AccountInfo | null,\r\n accountB: AccountInfo | null,\r\n compareClaims?: boolean\r\n ): boolean {\r\n if (!accountA || !accountB) {\r\n return false;\r\n }\r\n\r\n let claimsMatch = true; // default to true so as to not fail comparison below if compareClaims: false\r\n if (compareClaims) {\r\n const accountAClaims = (accountA.idTokenClaims ||\r\n {}) as TokenClaims;\r\n const accountBClaims = (accountB.idTokenClaims ||\r\n {}) as TokenClaims;\r\n\r\n // issued at timestamp and nonce are expected to change each time a new id token is acquired\r\n claimsMatch =\r\n accountAClaims.iat === accountBClaims.iat &&\r\n accountAClaims.nonce === accountBClaims.nonce;\r\n }\r\n\r\n return (\r\n accountA.homeAccountId === accountB.homeAccountId &&\r\n accountA.localAccountId === accountB.localAccountId &&\r\n accountA.username === accountB.username &&\r\n accountA.tenantId === accountB.tenantId &&\r\n accountA.loginHint === accountB.loginHint &&\r\n accountA.environment === accountB.environment &&\r\n accountA.nativeAccountId === accountB.nativeAccountId &&\r\n claimsMatch\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n// Codes defined by MSAL\r\nexport const noTokensFound = \"no_tokens_found\";\r\nexport const nativeAccountUnavailable = \"native_account_unavailable\";\r\nexport const refreshTokenExpired = \"refresh_token_expired\";\r\nexport const uxNotAllowed = \"ux_not_allowed\";\r\n\r\n// Codes potentially returned by server\r\nexport const interactionRequired = \"interaction_required\";\r\nexport const consentRequired = \"consent_required\";\r\nexport const loginRequired = \"login_required\";\r\nexport const badToken = \"bad_token\";\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { Constants } from \"../utils/Constants.js\";\r\nimport { AuthError } from \"./AuthError.js\";\r\nimport * as InteractionRequiredAuthErrorCodes from \"./InteractionRequiredAuthErrorCodes.js\";\r\nexport { InteractionRequiredAuthErrorCodes };\r\n\r\n/**\r\n * InteractionRequiredServerErrorMessage contains string constants used by error codes and messages returned by the server indicating interaction is required\r\n */\r\nexport const InteractionRequiredServerErrorMessage = [\r\n InteractionRequiredAuthErrorCodes.interactionRequired,\r\n InteractionRequiredAuthErrorCodes.consentRequired,\r\n InteractionRequiredAuthErrorCodes.loginRequired,\r\n InteractionRequiredAuthErrorCodes.badToken,\r\n InteractionRequiredAuthErrorCodes.uxNotAllowed,\r\n];\r\n\r\nexport const InteractionRequiredAuthSubErrorMessage = [\r\n \"message_only\",\r\n \"additional_action\",\r\n \"basic_action\",\r\n \"user_password_expired\",\r\n \"consent_required\",\r\n \"bad_token\",\r\n];\r\n\r\nconst InteractionRequiredAuthErrorMessages = {\r\n [InteractionRequiredAuthErrorCodes.noTokensFound]:\r\n \"No refresh token found in the cache. Please sign-in.\",\r\n [InteractionRequiredAuthErrorCodes.nativeAccountUnavailable]:\r\n \"The requested account is not available in the native broker. It may have been deleted or logged out. Please sign-in again using an interactive API.\",\r\n [InteractionRequiredAuthErrorCodes.refreshTokenExpired]:\r\n \"Refresh token has expired.\",\r\n [InteractionRequiredAuthErrorCodes.badToken]:\r\n \"Identity provider returned bad_token due to an expired or invalid refresh token. Please invoke an interactive API to resolve.\",\r\n [InteractionRequiredAuthErrorCodes.uxNotAllowed]:\r\n \"`canShowUI` flag in Edge was set to false. User interaction required on web page. Please invoke an interactive API to resolve.\",\r\n};\r\n\r\n/**\r\n * Interaction required errors defined by the SDK\r\n * @deprecated Use InteractionRequiredAuthErrorCodes instead\r\n */\r\nexport const InteractionRequiredAuthErrorMessage = {\r\n noTokensFoundError: {\r\n code: InteractionRequiredAuthErrorCodes.noTokensFound,\r\n desc: InteractionRequiredAuthErrorMessages[\r\n InteractionRequiredAuthErrorCodes.noTokensFound\r\n ],\r\n },\r\n native_account_unavailable: {\r\n code: InteractionRequiredAuthErrorCodes.nativeAccountUnavailable,\r\n desc: InteractionRequiredAuthErrorMessages[\r\n InteractionRequiredAuthErrorCodes.nativeAccountUnavailable\r\n ],\r\n },\r\n bad_token: {\r\n code: InteractionRequiredAuthErrorCodes.badToken,\r\n desc: InteractionRequiredAuthErrorMessages[\r\n InteractionRequiredAuthErrorCodes.badToken\r\n ],\r\n },\r\n};\r\n\r\n/**\r\n * Error thrown when user interaction is required.\r\n */\r\nexport class InteractionRequiredAuthError extends AuthError {\r\n /**\r\n * The time the error occured at\r\n */\r\n timestamp: string;\r\n\r\n /**\r\n * TraceId associated with the error\r\n */\r\n traceId: string;\r\n\r\n /**\r\n * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/claims-challenge.md\r\n *\r\n * A string with extra claims needed for the token request to succeed\r\n * web site: redirect the user to the authorization page and set the extra claims\r\n * web api: include the claims in the WWW-Authenticate header that are sent back to the client so that it knows to request a token with the extra claims\r\n * desktop application or browser context: include the claims when acquiring the token interactively\r\n * app to app context (client_credentials): include the claims in the AcquireTokenByClientCredential request\r\n */\r\n claims: string;\r\n\r\n /**\r\n * Server error number;\r\n */\r\n readonly errorNo?: string;\r\n\r\n constructor(\r\n errorCode?: string,\r\n errorMessage?: string,\r\n subError?: string,\r\n timestamp?: string,\r\n traceId?: string,\r\n correlationId?: string,\r\n claims?: string,\r\n errorNo?: string\r\n ) {\r\n super(errorCode, errorMessage, subError);\r\n Object.setPrototypeOf(this, InteractionRequiredAuthError.prototype);\r\n\r\n this.timestamp = timestamp || Constants.EMPTY_STRING;\r\n this.traceId = traceId || Constants.EMPTY_STRING;\r\n this.correlationId = correlationId || Constants.EMPTY_STRING;\r\n this.claims = claims || Constants.EMPTY_STRING;\r\n this.name = \"InteractionRequiredAuthError\";\r\n this.errorNo = errorNo;\r\n }\r\n}\r\n\r\n/**\r\n * Helper function used to determine if an error thrown by the server requires interaction to resolve\r\n * @param errorCode\r\n * @param errorString\r\n * @param subError\r\n */\r\nexport function isInteractionRequiredError(\r\n errorCode?: string,\r\n errorString?: string,\r\n subError?: string\r\n): boolean {\r\n const isInteractionRequiredErrorCode =\r\n !!errorCode &&\r\n InteractionRequiredServerErrorMessage.indexOf(errorCode) > -1;\r\n const isInteractionRequiredSubError =\r\n !!subError &&\r\n InteractionRequiredAuthSubErrorMessage.indexOf(subError) > -1;\r\n const isInteractionRequiredErrorDesc =\r\n !!errorString &&\r\n InteractionRequiredServerErrorMessage.some((irErrorCode) => {\r\n return errorString.indexOf(irErrorCode) > -1;\r\n });\r\n\r\n return (\r\n isInteractionRequiredErrorCode ||\r\n isInteractionRequiredErrorDesc ||\r\n isInteractionRequiredSubError\r\n );\r\n}\r\n\r\n/**\r\n * Creates an InteractionRequiredAuthError\r\n */\r\nexport function createInteractionRequiredAuthError(\r\n errorCode: string\r\n): InteractionRequiredAuthError {\r\n return new InteractionRequiredAuthError(\r\n errorCode,\r\n InteractionRequiredAuthErrorMessages[errorCode]\r\n );\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { Constants } from \"./Constants.js\";\r\nimport { ICrypto } from \"../crypto/ICrypto.js\";\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n} from \"../error/ClientAuthError.js\";\r\n\r\n/**\r\n * Type which defines the object that is stringified, encoded and sent in the state value.\r\n * Contains the following:\r\n * - id - unique identifier for this request\r\n * - ts - timestamp for the time the request was made. Used to ensure that token expiration is not calculated incorrectly.\r\n * - platformState - string value sent from the platform.\r\n */\r\nexport type LibraryStateObject = {\r\n id: string;\r\n meta?: Record;\r\n};\r\n\r\n/**\r\n * Type which defines the stringified and encoded object sent to the service in the authorize request.\r\n */\r\nexport type RequestStateObject = {\r\n userRequestState: string;\r\n libraryState: LibraryStateObject;\r\n};\r\n\r\n/**\r\n * Class which provides helpers for OAuth 2.0 protocol specific values\r\n */\r\nexport class ProtocolUtils {\r\n /**\r\n * Appends user state with random guid, or returns random guid.\r\n * @param userState\r\n * @param randomGuid\r\n */\r\n static setRequestState(\r\n cryptoObj: ICrypto,\r\n userState?: string,\r\n meta?: Record\r\n ): string {\r\n const libraryState = ProtocolUtils.generateLibraryState(\r\n cryptoObj,\r\n meta\r\n );\r\n return userState\r\n ? `${libraryState}${Constants.RESOURCE_DELIM}${userState}`\r\n : libraryState;\r\n }\r\n\r\n /**\r\n * Generates the state value used by the common library.\r\n * @param randomGuid\r\n * @param cryptoObj\r\n */\r\n static generateLibraryState(\r\n cryptoObj: ICrypto,\r\n meta?: Record\r\n ): string {\r\n if (!cryptoObj) {\r\n throw createClientAuthError(ClientAuthErrorCodes.noCryptoObject);\r\n }\r\n\r\n // Create a state object containing a unique id and the timestamp of the request creation\r\n const stateObj: LibraryStateObject = {\r\n id: cryptoObj.createNewGuid(),\r\n };\r\n\r\n if (meta) {\r\n stateObj.meta = meta;\r\n }\r\n\r\n const stateString = JSON.stringify(stateObj);\r\n\r\n return cryptoObj.base64Encode(stateString);\r\n }\r\n\r\n /**\r\n * Parses the state into the RequestStateObject, which contains the LibraryState info and the state passed by the user.\r\n * @param state\r\n * @param cryptoObj\r\n */\r\n static parseRequestState(\r\n cryptoObj: ICrypto,\r\n state: string\r\n ): RequestStateObject {\r\n if (!cryptoObj) {\r\n throw createClientAuthError(ClientAuthErrorCodes.noCryptoObject);\r\n }\r\n\r\n if (!state) {\r\n throw createClientAuthError(ClientAuthErrorCodes.invalidState);\r\n }\r\n\r\n try {\r\n // Split the state between library state and user passed state and decode them separately\r\n const splitState = state.split(Constants.RESOURCE_DELIM);\r\n const libraryState = splitState[0];\r\n const userState =\r\n splitState.length > 1\r\n ? splitState.slice(1).join(Constants.RESOURCE_DELIM)\r\n : Constants.EMPTY_STRING;\r\n const libraryStateString = cryptoObj.base64Decode(libraryState);\r\n const libraryStateObj = JSON.parse(\r\n libraryStateString\r\n ) as LibraryStateObject;\r\n return {\r\n userRequestState: userState || Constants.EMPTY_STRING,\r\n libraryState: libraryStateObj,\r\n };\r\n } catch (e) {\r\n throw createClientAuthError(ClientAuthErrorCodes.invalidState);\r\n }\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { ICrypto, SignedHttpRequestParameters } from \"./ICrypto.js\";\r\nimport * as TimeUtils from \"../utils/TimeUtils.js\";\r\nimport { UrlString } from \"../url/UrlString.js\";\r\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\r\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\r\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\r\nimport { Logger } from \"../logger/Logger.js\";\r\n\r\n/**\r\n * See eSTS docs for more info.\r\n * - A kid element, with the value containing an RFC 7638-compliant JWK thumbprint that is base64 encoded.\r\n * - xms_ksl element, representing the storage location of the key's secret component on the client device. One of two values:\r\n * - sw: software storage\r\n * - uhw: hardware storage\r\n */\r\ntype ReqCnf = {\r\n kid: string;\r\n xms_ksl: KeyLocation;\r\n};\r\n\r\nexport type ReqCnfData = {\r\n kid: string;\r\n reqCnfString: string;\r\n};\r\n\r\nconst KeyLocation = {\r\n SW: \"sw\",\r\n UHW: \"uhw\",\r\n} as const;\r\nexport type KeyLocation = (typeof KeyLocation)[keyof typeof KeyLocation];\r\n\r\n/** @internal */\r\nexport class PopTokenGenerator {\r\n private cryptoUtils: ICrypto;\r\n private performanceClient?: IPerformanceClient;\r\n\r\n constructor(cryptoUtils: ICrypto, performanceClient?: IPerformanceClient) {\r\n this.cryptoUtils = cryptoUtils;\r\n this.performanceClient = performanceClient;\r\n }\r\n\r\n /**\r\n * Generates the req_cnf validated at the RP in the POP protocol for SHR parameters\r\n * and returns an object containing the keyid, the full req_cnf string and the req_cnf string hash\r\n * @param request\r\n * @returns\r\n */\r\n async generateCnf(\r\n request: SignedHttpRequestParameters,\r\n logger: Logger\r\n ): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.PopTokenGenerateCnf,\r\n request.correlationId\r\n );\r\n\r\n const reqCnf = await invokeAsync(\r\n this.generateKid.bind(this),\r\n PerformanceEvents.PopTokenGenerateCnf,\r\n logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(request);\r\n const reqCnfString: string = this.cryptoUtils.base64UrlEncode(\r\n JSON.stringify(reqCnf)\r\n );\r\n\r\n return {\r\n kid: reqCnf.kid,\r\n reqCnfString,\r\n };\r\n }\r\n\r\n /**\r\n * Generates key_id for a SHR token request\r\n * @param request\r\n * @returns\r\n */\r\n async generateKid(request: SignedHttpRequestParameters): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.PopTokenGenerateKid,\r\n request.correlationId\r\n );\r\n\r\n const kidThumbprint = await this.cryptoUtils.getPublicKeyThumbprint(\r\n request\r\n );\r\n\r\n return {\r\n kid: kidThumbprint,\r\n xms_ksl: KeyLocation.SW,\r\n };\r\n }\r\n\r\n /**\r\n * Signs the POP access_token with the local generated key-pair\r\n * @param accessToken\r\n * @param request\r\n * @returns\r\n */\r\n async signPopToken(\r\n accessToken: string,\r\n keyId: string,\r\n request: SignedHttpRequestParameters\r\n ): Promise {\r\n return this.signPayload(accessToken, keyId, request);\r\n }\r\n\r\n /**\r\n * Utility function to generate the signed JWT for an access_token\r\n * @param payload\r\n * @param kid\r\n * @param request\r\n * @param claims\r\n * @returns\r\n */\r\n async signPayload(\r\n payload: string,\r\n keyId: string,\r\n request: SignedHttpRequestParameters,\r\n claims?: object\r\n ): Promise {\r\n // Deconstruct request to extract SHR parameters\r\n const {\r\n resourceRequestMethod,\r\n resourceRequestUri,\r\n shrClaims,\r\n shrNonce,\r\n shrOptions,\r\n } = request;\r\n\r\n const resourceUrlString = resourceRequestUri\r\n ? new UrlString(resourceRequestUri)\r\n : undefined;\r\n const resourceUrlComponents = resourceUrlString?.getUrlComponents();\r\n return this.cryptoUtils.signJwt(\r\n {\r\n at: payload,\r\n ts: TimeUtils.nowSeconds(),\r\n m: resourceRequestMethod?.toUpperCase(),\r\n u: resourceUrlComponents?.HostNameAndPort,\r\n nonce: shrNonce || this.cryptoUtils.createNewGuid(),\r\n p: resourceUrlComponents?.AbsolutePath,\r\n q: resourceUrlComponents?.QueryString\r\n ? [[], resourceUrlComponents.QueryString]\r\n : undefined,\r\n client_claims: shrClaims || undefined,\r\n ...claims,\r\n },\r\n keyId,\r\n shrOptions,\r\n request.correlationId\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { ISerializableTokenCache } from \"../interface/ISerializableTokenCache.js\";\r\n\r\n/**\r\n * This class instance helps track the memory changes facilitating\r\n * decisions to read from and write to the persistent cache\r\n */ export class TokenCacheContext {\r\n /**\r\n * boolean indicating cache change\r\n */\r\n hasChanged: boolean;\r\n /**\r\n * serializable token cache interface\r\n */\r\n cache: ISerializableTokenCache;\r\n\r\n constructor(tokenCache: ISerializableTokenCache, hasChanged: boolean) {\r\n this.cache = tokenCache;\r\n this.hasChanged = hasChanged;\r\n }\r\n\r\n /**\r\n * boolean which indicates the changes in cache\r\n */\r\n get cacheHasChanged(): boolean {\r\n return this.hasChanged;\r\n }\r\n\r\n /**\r\n * function to retrieve the token cache\r\n */\r\n get tokenCache(): ISerializableTokenCache {\r\n return this.cache;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { ServerAuthorizationTokenResponse } from \"./ServerAuthorizationTokenResponse.js\";\r\nimport { ICrypto } from \"../crypto/ICrypto.js\";\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n} from \"../error/ClientAuthError.js\";\r\nimport { Logger } from \"../logger/Logger.js\";\r\nimport { ServerError } from \"../error/ServerError.js\";\r\nimport { ScopeSet } from \"../request/ScopeSet.js\";\r\nimport { AuthenticationResult } from \"./AuthenticationResult.js\";\r\nimport { AccountEntity } from \"../cache/entities/AccountEntity.js\";\r\nimport { Authority } from \"../authority/Authority.js\";\r\nimport { IdTokenEntity } from \"../cache/entities/IdTokenEntity.js\";\r\nimport { AccessTokenEntity } from \"../cache/entities/AccessTokenEntity.js\";\r\nimport { RefreshTokenEntity } from \"../cache/entities/RefreshTokenEntity.js\";\r\nimport {\r\n InteractionRequiredAuthError,\r\n isInteractionRequiredError,\r\n} from \"../error/InteractionRequiredAuthError.js\";\r\nimport { CacheRecord } from \"../cache/entities/CacheRecord.js\";\r\nimport { CacheManager } from \"../cache/CacheManager.js\";\r\nimport { ProtocolUtils, RequestStateObject } from \"../utils/ProtocolUtils.js\";\r\nimport {\r\n AuthenticationScheme,\r\n Constants,\r\n THE_FAMILY_ID,\r\n HttpStatus,\r\n} from \"../utils/Constants.js\";\r\nimport { PopTokenGenerator } from \"../crypto/PopTokenGenerator.js\";\r\nimport { AppMetadataEntity } from \"../cache/entities/AppMetadataEntity.js\";\r\nimport { ICachePlugin } from \"../cache/interface/ICachePlugin.js\";\r\nimport { TokenCacheContext } from \"../cache/persistence/TokenCacheContext.js\";\r\nimport { ISerializableTokenCache } from \"../cache/interface/ISerializableTokenCache.js\";\r\nimport { AuthorizationCodePayload } from \"./AuthorizationCodePayload.js\";\r\nimport { BaseAuthRequest } from \"../request/BaseAuthRequest.js\";\r\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\r\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\r\nimport { checkMaxAge, extractTokenClaims } from \"../account/AuthToken.js\";\r\nimport {\r\n TokenClaims,\r\n getTenantIdFromIdTokenClaims,\r\n} from \"../account/TokenClaims.js\";\r\nimport {\r\n AccountInfo,\r\n buildTenantProfile,\r\n updateAccountTenantProfileData,\r\n} from \"../account/AccountInfo.js\";\r\nimport * as CacheHelpers from \"../cache/utils/CacheHelpers.js\";\r\nimport * as TimeUtils from \"../utils/TimeUtils.js\";\r\n\r\n/**\r\n * Class that handles response parsing.\r\n * @internal\r\n */\r\nexport class ResponseHandler {\r\n private clientId: string;\r\n private cacheStorage: CacheManager;\r\n private cryptoObj: ICrypto;\r\n private logger: Logger;\r\n private homeAccountIdentifier: string;\r\n private serializableCache: ISerializableTokenCache | null;\r\n private persistencePlugin: ICachePlugin | null;\r\n private performanceClient?: IPerformanceClient;\r\n\r\n constructor(\r\n clientId: string,\r\n cacheStorage: CacheManager,\r\n cryptoObj: ICrypto,\r\n logger: Logger,\r\n serializableCache: ISerializableTokenCache | null,\r\n persistencePlugin: ICachePlugin | null,\r\n performanceClient?: IPerformanceClient\r\n ) {\r\n this.clientId = clientId;\r\n this.cacheStorage = cacheStorage;\r\n this.cryptoObj = cryptoObj;\r\n this.logger = logger;\r\n this.serializableCache = serializableCache;\r\n this.persistencePlugin = persistencePlugin;\r\n this.performanceClient = performanceClient;\r\n }\r\n\r\n /**\r\n * Function which validates server authorization token response.\r\n * @param serverResponse\r\n * @param refreshAccessToken\r\n */\r\n validateTokenResponse(\r\n serverResponse: ServerAuthorizationTokenResponse,\r\n refreshAccessToken?: boolean\r\n ): void {\r\n // Check for error\r\n if (\r\n serverResponse.error ||\r\n serverResponse.error_description ||\r\n serverResponse.suberror\r\n ) {\r\n const errString = `Error(s): ${\r\n serverResponse.error_codes || Constants.NOT_AVAILABLE\r\n } - Timestamp: ${\r\n serverResponse.timestamp || Constants.NOT_AVAILABLE\r\n } - Description: ${\r\n serverResponse.error_description || Constants.NOT_AVAILABLE\r\n } - Correlation ID: ${\r\n serverResponse.correlation_id || Constants.NOT_AVAILABLE\r\n } - Trace ID: ${\r\n serverResponse.trace_id || Constants.NOT_AVAILABLE\r\n }`;\r\n const serverErrorNo = serverResponse.error_codes?.length\r\n ? serverResponse.error_codes[0]\r\n : undefined;\r\n const serverError = new ServerError(\r\n serverResponse.error,\r\n errString,\r\n serverResponse.suberror,\r\n serverErrorNo,\r\n serverResponse.status\r\n );\r\n\r\n // check if 500 error\r\n if (\r\n refreshAccessToken &&\r\n serverResponse.status &&\r\n serverResponse.status >= HttpStatus.SERVER_ERROR_RANGE_START &&\r\n serverResponse.status <= HttpStatus.SERVER_ERROR_RANGE_END\r\n ) {\r\n this.logger.warning(\r\n `executeTokenRequest:validateTokenResponse - AAD is currently unavailable and the access token is unable to be refreshed.\\n${serverError}`\r\n );\r\n\r\n // don't throw an exception, but alert the user via a log that the token was unable to be refreshed\r\n return;\r\n // check if 400 error\r\n } else if (\r\n refreshAccessToken &&\r\n serverResponse.status &&\r\n serverResponse.status >= HttpStatus.CLIENT_ERROR_RANGE_START &&\r\n serverResponse.status <= HttpStatus.CLIENT_ERROR_RANGE_END\r\n ) {\r\n this.logger.warning(\r\n `executeTokenRequest:validateTokenResponse - AAD is currently available but is unable to refresh the access token.\\n${serverError}`\r\n );\r\n\r\n // don't throw an exception, but alert the user via a log that the token was unable to be refreshed\r\n return;\r\n }\r\n\r\n if (\r\n isInteractionRequiredError(\r\n serverResponse.error,\r\n serverResponse.error_description,\r\n serverResponse.suberror\r\n )\r\n ) {\r\n throw new InteractionRequiredAuthError(\r\n serverResponse.error,\r\n serverResponse.error_description,\r\n serverResponse.suberror,\r\n serverResponse.timestamp || Constants.EMPTY_STRING,\r\n serverResponse.trace_id || Constants.EMPTY_STRING,\r\n serverResponse.correlation_id || Constants.EMPTY_STRING,\r\n serverResponse.claims || Constants.EMPTY_STRING,\r\n serverErrorNo\r\n );\r\n }\r\n\r\n throw serverError;\r\n }\r\n }\r\n\r\n /**\r\n * Returns a constructed token response based on given string. Also manages the cache updates and cleanups.\r\n * @param serverTokenResponse\r\n * @param authority\r\n */\r\n async handleServerTokenResponse(\r\n serverTokenResponse: ServerAuthorizationTokenResponse,\r\n authority: Authority,\r\n reqTimestamp: number,\r\n request: BaseAuthRequest,\r\n authCodePayload?: AuthorizationCodePayload,\r\n userAssertionHash?: string,\r\n handlingRefreshTokenResponse?: boolean,\r\n forceCacheRefreshTokenResponse?: boolean,\r\n serverRequestId?: string\r\n ): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.HandleServerTokenResponse,\r\n serverTokenResponse.correlation_id\r\n );\r\n\r\n // create an idToken object (not entity)\r\n let idTokenClaims: TokenClaims | undefined;\r\n if (serverTokenResponse.id_token) {\r\n idTokenClaims = extractTokenClaims(\r\n serverTokenResponse.id_token || Constants.EMPTY_STRING,\r\n this.cryptoObj.base64Decode\r\n );\r\n\r\n // token nonce check (TODO: Add a warning if no nonce is given?)\r\n if (authCodePayload && authCodePayload.nonce) {\r\n if (idTokenClaims.nonce !== authCodePayload.nonce) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.nonceMismatch\r\n );\r\n }\r\n }\r\n\r\n // token max_age check\r\n if (request.maxAge || request.maxAge === 0) {\r\n const authTime = idTokenClaims.auth_time;\r\n if (!authTime) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.authTimeNotFound\r\n );\r\n }\r\n\r\n checkMaxAge(authTime, request.maxAge);\r\n }\r\n }\r\n\r\n // generate homeAccountId\r\n this.homeAccountIdentifier = AccountEntity.generateHomeAccountId(\r\n serverTokenResponse.client_info || Constants.EMPTY_STRING,\r\n authority.authorityType,\r\n this.logger,\r\n this.cryptoObj,\r\n idTokenClaims\r\n );\r\n\r\n // save the response tokens\r\n let requestStateObj: RequestStateObject | undefined;\r\n if (!!authCodePayload && !!authCodePayload.state) {\r\n requestStateObj = ProtocolUtils.parseRequestState(\r\n this.cryptoObj,\r\n authCodePayload.state\r\n );\r\n }\r\n\r\n // Add keyId from request to serverTokenResponse if defined\r\n serverTokenResponse.key_id =\r\n serverTokenResponse.key_id || request.sshKid || undefined;\r\n\r\n const cacheRecord = this.generateCacheRecord(\r\n serverTokenResponse,\r\n authority,\r\n reqTimestamp,\r\n request,\r\n idTokenClaims,\r\n userAssertionHash,\r\n authCodePayload\r\n );\r\n let cacheContext;\r\n try {\r\n if (this.persistencePlugin && this.serializableCache) {\r\n this.logger.verbose(\r\n \"Persistence enabled, calling beforeCacheAccess\"\r\n );\r\n cacheContext = new TokenCacheContext(\r\n this.serializableCache,\r\n true\r\n );\r\n await this.persistencePlugin.beforeCacheAccess(cacheContext);\r\n }\r\n /*\r\n * When saving a refreshed tokens to the cache, it is expected that the account that was used is present in the cache.\r\n * If not present, we should return null, as it's the case that another application called removeAccount in between\r\n * the calls to getAllAccounts and acquireTokenSilent. We should not overwrite that removal, unless explicitly flagged by\r\n * the developer, as in the case of refresh token flow used in ADAL Node to MSAL Node migration.\r\n */\r\n if (\r\n handlingRefreshTokenResponse &&\r\n !forceCacheRefreshTokenResponse &&\r\n cacheRecord.account\r\n ) {\r\n const key = this.cacheStorage.generateAccountKey(\r\n cacheRecord.account.getAccountInfo()\r\n );\r\n const account = this.cacheStorage.getAccount(\r\n key,\r\n request.correlationId\r\n );\r\n if (!account) {\r\n this.logger.warning(\r\n \"Account used to refresh tokens not in persistence, refreshed tokens will not be stored in the cache\"\r\n );\r\n return await ResponseHandler.generateAuthenticationResult(\r\n this.cryptoObj,\r\n authority,\r\n cacheRecord,\r\n false,\r\n request,\r\n idTokenClaims,\r\n requestStateObj,\r\n undefined,\r\n serverRequestId\r\n );\r\n }\r\n }\r\n await this.cacheStorage.saveCacheRecord(\r\n cacheRecord,\r\n request.correlationId,\r\n request.storeInCache\r\n );\r\n } finally {\r\n if (\r\n this.persistencePlugin &&\r\n this.serializableCache &&\r\n cacheContext\r\n ) {\r\n this.logger.verbose(\r\n \"Persistence enabled, calling afterCacheAccess\"\r\n );\r\n await this.persistencePlugin.afterCacheAccess(cacheContext);\r\n }\r\n }\r\n\r\n return ResponseHandler.generateAuthenticationResult(\r\n this.cryptoObj,\r\n authority,\r\n cacheRecord,\r\n false,\r\n request,\r\n idTokenClaims,\r\n requestStateObj,\r\n serverTokenResponse,\r\n serverRequestId\r\n );\r\n }\r\n\r\n /**\r\n * Generates CacheRecord\r\n * @param serverTokenResponse\r\n * @param idTokenObj\r\n * @param authority\r\n */\r\n private generateCacheRecord(\r\n serverTokenResponse: ServerAuthorizationTokenResponse,\r\n authority: Authority,\r\n reqTimestamp: number,\r\n request: BaseAuthRequest,\r\n idTokenClaims?: TokenClaims,\r\n userAssertionHash?: string,\r\n authCodePayload?: AuthorizationCodePayload\r\n ): CacheRecord {\r\n const env = authority.getPreferredCache();\r\n if (!env) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.invalidCacheEnvironment\r\n );\r\n }\r\n\r\n const claimsTenantId = getTenantIdFromIdTokenClaims(idTokenClaims);\r\n\r\n // IdToken: non AAD scenarios can have empty realm\r\n let cachedIdToken: IdTokenEntity | undefined;\r\n let cachedAccount: AccountEntity | undefined;\r\n if (serverTokenResponse.id_token && !!idTokenClaims) {\r\n cachedIdToken = CacheHelpers.createIdTokenEntity(\r\n this.homeAccountIdentifier,\r\n env,\r\n serverTokenResponse.id_token,\r\n this.clientId,\r\n claimsTenantId || \"\"\r\n );\r\n\r\n cachedAccount = buildAccountToCache(\r\n this.cacheStorage,\r\n authority,\r\n this.homeAccountIdentifier,\r\n this.cryptoObj.base64Decode,\r\n request.correlationId,\r\n idTokenClaims,\r\n serverTokenResponse.client_info,\r\n env,\r\n claimsTenantId,\r\n authCodePayload,\r\n undefined, // nativeAccountId\r\n this.logger\r\n );\r\n }\r\n\r\n // AccessToken\r\n let cachedAccessToken: AccessTokenEntity | null = null;\r\n if (serverTokenResponse.access_token) {\r\n // If scopes not returned in server response, use request scopes\r\n const responseScopes = serverTokenResponse.scope\r\n ? ScopeSet.fromString(serverTokenResponse.scope)\r\n : new ScopeSet(request.scopes || []);\r\n\r\n /*\r\n * Use timestamp calculated before request\r\n * Server may return timestamps as strings, parse to numbers if so.\r\n */\r\n const expiresIn: number =\r\n (typeof serverTokenResponse.expires_in === \"string\"\r\n ? parseInt(serverTokenResponse.expires_in, 10)\r\n : serverTokenResponse.expires_in) || 0;\r\n const extExpiresIn: number =\r\n (typeof serverTokenResponse.ext_expires_in === \"string\"\r\n ? parseInt(serverTokenResponse.ext_expires_in, 10)\r\n : serverTokenResponse.ext_expires_in) || 0;\r\n const refreshIn: number | undefined =\r\n (typeof serverTokenResponse.refresh_in === \"string\"\r\n ? parseInt(serverTokenResponse.refresh_in, 10)\r\n : serverTokenResponse.refresh_in) || undefined;\r\n const tokenExpirationSeconds = reqTimestamp + expiresIn;\r\n const extendedTokenExpirationSeconds =\r\n tokenExpirationSeconds + extExpiresIn;\r\n const refreshOnSeconds =\r\n refreshIn && refreshIn > 0\r\n ? reqTimestamp + refreshIn\r\n : undefined;\r\n\r\n // non AAD scenarios can have empty realm\r\n cachedAccessToken = CacheHelpers.createAccessTokenEntity(\r\n this.homeAccountIdentifier,\r\n env,\r\n serverTokenResponse.access_token,\r\n this.clientId,\r\n claimsTenantId || authority.tenant || \"\",\r\n responseScopes.printScopes(),\r\n tokenExpirationSeconds,\r\n extendedTokenExpirationSeconds,\r\n this.cryptoObj.base64Decode,\r\n refreshOnSeconds,\r\n serverTokenResponse.token_type,\r\n userAssertionHash,\r\n serverTokenResponse.key_id,\r\n request.claims,\r\n request.requestedClaimsHash\r\n );\r\n }\r\n\r\n // refreshToken\r\n let cachedRefreshToken: RefreshTokenEntity | null = null;\r\n if (serverTokenResponse.refresh_token) {\r\n let rtExpiresOn: number | undefined;\r\n if (serverTokenResponse.refresh_token_expires_in) {\r\n const rtExpiresIn: number =\r\n typeof serverTokenResponse.refresh_token_expires_in ===\r\n \"string\"\r\n ? parseInt(\r\n serverTokenResponse.refresh_token_expires_in,\r\n 10\r\n )\r\n : serverTokenResponse.refresh_token_expires_in;\r\n rtExpiresOn = reqTimestamp + rtExpiresIn;\r\n }\r\n cachedRefreshToken = CacheHelpers.createRefreshTokenEntity(\r\n this.homeAccountIdentifier,\r\n env,\r\n serverTokenResponse.refresh_token,\r\n this.clientId,\r\n serverTokenResponse.foci,\r\n userAssertionHash,\r\n rtExpiresOn\r\n );\r\n }\r\n\r\n // appMetadata\r\n let cachedAppMetadata: AppMetadataEntity | null = null;\r\n if (serverTokenResponse.foci) {\r\n cachedAppMetadata = {\r\n clientId: this.clientId,\r\n environment: env,\r\n familyId: serverTokenResponse.foci,\r\n };\r\n }\r\n\r\n return {\r\n account: cachedAccount,\r\n idToken: cachedIdToken,\r\n accessToken: cachedAccessToken,\r\n refreshToken: cachedRefreshToken,\r\n appMetadata: cachedAppMetadata,\r\n };\r\n }\r\n\r\n /**\r\n * Creates an @AuthenticationResult from @CacheRecord , @IdToken , and a boolean that states whether or not the result is from cache.\r\n *\r\n * Optionally takes a state string that is set as-is in the response.\r\n *\r\n * @param cacheRecord\r\n * @param idTokenObj\r\n * @param fromTokenCache\r\n * @param stateString\r\n */\r\n static async generateAuthenticationResult(\r\n cryptoObj: ICrypto,\r\n authority: Authority,\r\n cacheRecord: CacheRecord,\r\n fromTokenCache: boolean,\r\n request: BaseAuthRequest,\r\n idTokenClaims?: TokenClaims,\r\n requestState?: RequestStateObject,\r\n serverTokenResponse?: ServerAuthorizationTokenResponse,\r\n requestId?: string\r\n ): Promise {\r\n let accessToken: string = Constants.EMPTY_STRING;\r\n let responseScopes: Array = [];\r\n let expiresOn: Date | null = null;\r\n let extExpiresOn: Date | undefined;\r\n let refreshOn: Date | undefined;\r\n let familyId: string = Constants.EMPTY_STRING;\r\n\r\n if (cacheRecord.accessToken) {\r\n /*\r\n * if the request object has `popKid` property, `signPopToken` will be set to false and\r\n * the token will be returned unsigned\r\n */\r\n if (\r\n cacheRecord.accessToken.tokenType ===\r\n AuthenticationScheme.POP &&\r\n !request.popKid\r\n ) {\r\n const popTokenGenerator: PopTokenGenerator =\r\n new PopTokenGenerator(cryptoObj);\r\n const { secret, keyId } = cacheRecord.accessToken;\r\n\r\n if (!keyId) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.keyIdMissing\r\n );\r\n }\r\n\r\n accessToken = await popTokenGenerator.signPopToken(\r\n secret,\r\n keyId,\r\n request\r\n );\r\n } else {\r\n accessToken = cacheRecord.accessToken.secret;\r\n }\r\n responseScopes = ScopeSet.fromString(\r\n cacheRecord.accessToken.target\r\n ).asArray();\r\n // Access token expiresOn cached in seconds, converting to Date for AuthenticationResult\r\n expiresOn = TimeUtils.toDateFromSeconds(\r\n cacheRecord.accessToken.expiresOn\r\n );\r\n extExpiresOn = TimeUtils.toDateFromSeconds(\r\n cacheRecord.accessToken.extendedExpiresOn\r\n );\r\n if (cacheRecord.accessToken.refreshOn) {\r\n refreshOn = TimeUtils.toDateFromSeconds(\r\n cacheRecord.accessToken.refreshOn\r\n );\r\n }\r\n }\r\n\r\n if (cacheRecord.appMetadata) {\r\n familyId =\r\n cacheRecord.appMetadata.familyId === THE_FAMILY_ID\r\n ? THE_FAMILY_ID\r\n : \"\";\r\n }\r\n const uid = idTokenClaims?.oid || idTokenClaims?.sub || \"\";\r\n const tid = idTokenClaims?.tid || \"\";\r\n\r\n // for hybrid + native bridge enablement, send back the native account Id\r\n if (serverTokenResponse?.spa_accountid && !!cacheRecord.account) {\r\n cacheRecord.account.nativeAccountId =\r\n serverTokenResponse?.spa_accountid;\r\n }\r\n\r\n const accountInfo: AccountInfo | null = cacheRecord.account\r\n ? updateAccountTenantProfileData(\r\n cacheRecord.account.getAccountInfo(),\r\n undefined, // tenantProfile optional\r\n idTokenClaims,\r\n cacheRecord.idToken?.secret\r\n )\r\n : null;\r\n\r\n return {\r\n authority: authority.canonicalAuthority,\r\n uniqueId: uid,\r\n tenantId: tid,\r\n scopes: responseScopes,\r\n account: accountInfo,\r\n idToken: cacheRecord?.idToken?.secret || \"\",\r\n idTokenClaims: idTokenClaims || {},\r\n accessToken: accessToken,\r\n fromCache: fromTokenCache,\r\n expiresOn: expiresOn,\r\n extExpiresOn: extExpiresOn,\r\n refreshOn: refreshOn,\r\n correlationId: request.correlationId,\r\n requestId: requestId || Constants.EMPTY_STRING,\r\n familyId: familyId,\r\n tokenType:\r\n cacheRecord.accessToken?.tokenType || Constants.EMPTY_STRING,\r\n state: requestState\r\n ? requestState.userRequestState\r\n : Constants.EMPTY_STRING,\r\n cloudGraphHostName:\r\n cacheRecord.account?.cloudGraphHostName ||\r\n Constants.EMPTY_STRING,\r\n msGraphHost:\r\n cacheRecord.account?.msGraphHost || Constants.EMPTY_STRING,\r\n code: serverTokenResponse?.spa_code,\r\n fromNativeBroker: false,\r\n };\r\n }\r\n}\r\n\r\nexport function buildAccountToCache(\r\n cacheStorage: CacheManager,\r\n authority: Authority,\r\n homeAccountId: string,\r\n base64Decode: (input: string) => string,\r\n correlationId: string,\r\n idTokenClaims?: TokenClaims,\r\n clientInfo?: string,\r\n environment?: string,\r\n claimsTenantId?: string | null,\r\n authCodePayload?: AuthorizationCodePayload,\r\n nativeAccountId?: string,\r\n logger?: Logger\r\n): AccountEntity {\r\n logger?.verbose(\"setCachedAccount called\");\r\n\r\n // Check if base account is already cached\r\n const accountKeys = cacheStorage.getAccountKeys();\r\n const baseAccountKey = accountKeys.find((accountKey: string) => {\r\n return accountKey.startsWith(homeAccountId);\r\n });\r\n\r\n let cachedAccount: AccountEntity | null = null;\r\n if (baseAccountKey) {\r\n cachedAccount = cacheStorage.getAccount(baseAccountKey, correlationId);\r\n }\r\n\r\n const baseAccount =\r\n cachedAccount ||\r\n AccountEntity.createAccount(\r\n {\r\n homeAccountId,\r\n idTokenClaims,\r\n clientInfo,\r\n environment,\r\n cloudGraphHostName: authCodePayload?.cloud_graph_host_name,\r\n msGraphHost: authCodePayload?.msgraph_host,\r\n nativeAccountId: nativeAccountId,\r\n },\r\n authority,\r\n base64Decode\r\n );\r\n\r\n const tenantProfiles = baseAccount.tenantProfiles || [];\r\n const tenantId = claimsTenantId || baseAccount.realm;\r\n if (\r\n tenantId &&\r\n !tenantProfiles.find((tenantProfile) => {\r\n return tenantProfile.tenantId === tenantId;\r\n })\r\n ) {\r\n const newTenantProfile = buildTenantProfile(\r\n homeAccountId,\r\n baseAccount.localAccountId,\r\n tenantId,\r\n idTokenClaims\r\n );\r\n tenantProfiles.push(newTenantProfile);\r\n }\r\n baseAccount.tenantProfiles = tenantProfiles;\r\n\r\n return baseAccount;\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n ClientAssertionCallback,\r\n ClientAssertionConfig,\r\n} from \"../account/ClientCredentials.js\";\r\n\r\nexport async function getClientAssertion(\r\n clientAssertion: string | ClientAssertionCallback,\r\n clientId: string,\r\n tokenEndpoint?: string\r\n): Promise {\r\n if (typeof clientAssertion === \"string\") {\r\n return clientAssertion;\r\n } else {\r\n const config: ClientAssertionConfig = {\r\n clientId: clientId,\r\n tokenEndpoint: tokenEndpoint,\r\n };\r\n return clientAssertion(config);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { BaseClient } from \"./BaseClient.js\";\r\nimport { CommonAuthorizationCodeRequest } from \"../request/CommonAuthorizationCodeRequest.js\";\r\nimport { Authority } from \"../authority/Authority.js\";\r\nimport * as RequestParameterBuilder from \"../request/RequestParameterBuilder.js\";\r\nimport * as UrlUtils from \"../utils/UrlUtils.js\";\r\nimport {\r\n GrantType,\r\n AuthenticationScheme,\r\n Separators,\r\n HeaderNames,\r\n} from \"../utils/Constants.js\";\r\nimport * as AADServerParamKeys from \"../constants/AADServerParamKeys.js\";\r\nimport {\r\n ClientConfiguration,\r\n isOidcProtocolMode,\r\n} from \"../config/ClientConfiguration.js\";\r\nimport { ServerAuthorizationTokenResponse } from \"../response/ServerAuthorizationTokenResponse.js\";\r\nimport { NetworkResponse } from \"../network/NetworkResponse.js\";\r\nimport { ResponseHandler } from \"../response/ResponseHandler.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { StringUtils } from \"../utils/StringUtils.js\";\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n} from \"../error/ClientAuthError.js\";\r\nimport { UrlString } from \"../url/UrlString.js\";\r\nimport { CommonEndSessionRequest } from \"../request/CommonEndSessionRequest.js\";\r\nimport { PopTokenGenerator } from \"../crypto/PopTokenGenerator.js\";\r\nimport { AuthorizationCodePayload } from \"../response/AuthorizationCodePayload.js\";\r\nimport * as TimeUtils from \"../utils/TimeUtils.js\";\r\nimport {\r\n buildClientInfoFromHomeAccountId,\r\n buildClientInfo,\r\n} from \"../account/ClientInfo.js\";\r\nimport { CcsCredentialType, CcsCredential } from \"../account/CcsCredential.js\";\r\nimport {\r\n createClientConfigurationError,\r\n ClientConfigurationErrorCodes,\r\n} from \"../error/ClientConfigurationError.js\";\r\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\r\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\r\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\r\nimport { ClientAssertion } from \"../account/ClientCredentials.js\";\r\nimport { getClientAssertion } from \"../utils/ClientAssertionUtils.js\";\r\nimport { getRequestThumbprint } from \"../network/RequestThumbprint.js\";\r\n\r\n/**\r\n * Oauth2.0 Authorization Code client\r\n * @internal\r\n */\r\nexport class AuthorizationCodeClient extends BaseClient {\r\n // Flag to indicate if client is for hybrid spa auth code redemption\r\n protected includeRedirectUri: boolean = true;\r\n private oidcDefaultScopes;\r\n\r\n constructor(\r\n configuration: ClientConfiguration,\r\n performanceClient?: IPerformanceClient\r\n ) {\r\n super(configuration, performanceClient);\r\n this.oidcDefaultScopes =\r\n this.config.authOptions.authority.options.OIDCOptions?.defaultScopes;\r\n }\r\n\r\n /**\r\n * API to acquire a token in exchange of 'authorization_code` acquired by the user in the first leg of the\r\n * authorization_code_grant\r\n * @param request\r\n */\r\n async acquireToken(\r\n request: CommonAuthorizationCodeRequest,\r\n authCodePayload?: AuthorizationCodePayload\r\n ): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.AuthClientAcquireToken,\r\n request.correlationId\r\n );\r\n\r\n if (!request.code) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.requestCannotBeMade\r\n );\r\n }\r\n\r\n const reqTimestamp = TimeUtils.nowSeconds();\r\n const response = await invokeAsync(\r\n this.executeTokenRequest.bind(this),\r\n PerformanceEvents.AuthClientExecuteTokenRequest,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(this.authority, request);\r\n\r\n // Retrieve requestId from response headers\r\n const requestId = response.headers?.[HeaderNames.X_MS_REQUEST_ID];\r\n\r\n const responseHandler = new ResponseHandler(\r\n this.config.authOptions.clientId,\r\n this.cacheManager,\r\n this.cryptoUtils,\r\n this.logger,\r\n this.config.serializableCache,\r\n this.config.persistencePlugin,\r\n this.performanceClient\r\n );\r\n\r\n // Validate response. This function throws a server error if an error is returned by the server.\r\n responseHandler.validateTokenResponse(response.body);\r\n\r\n return invokeAsync(\r\n responseHandler.handleServerTokenResponse.bind(responseHandler),\r\n PerformanceEvents.HandleServerTokenResponse,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(\r\n response.body,\r\n this.authority,\r\n reqTimestamp,\r\n request,\r\n authCodePayload,\r\n undefined,\r\n undefined,\r\n undefined,\r\n requestId\r\n );\r\n }\r\n\r\n /**\r\n * Used to log out the current user, and redirect the user to the postLogoutRedirectUri.\r\n * Default behaviour is to redirect the user to `window.location.href`.\r\n * @param authorityUri\r\n */\r\n getLogoutUri(logoutRequest: CommonEndSessionRequest): string {\r\n // Throw error if logoutRequest is null/undefined\r\n if (!logoutRequest) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.logoutRequestEmpty\r\n );\r\n }\r\n const queryString = this.createLogoutUrlQueryString(logoutRequest);\r\n\r\n // Construct logout URI\r\n return UrlString.appendQueryString(\r\n this.authority.endSessionEndpoint,\r\n queryString\r\n );\r\n }\r\n\r\n /**\r\n * Executes POST request to token endpoint\r\n * @param authority\r\n * @param request\r\n */\r\n private async executeTokenRequest(\r\n authority: Authority,\r\n request: CommonAuthorizationCodeRequest\r\n ): Promise> {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.AuthClientExecuteTokenRequest,\r\n request.correlationId\r\n );\r\n\r\n const queryParametersString = this.createTokenQueryParameters(request);\r\n const endpoint = UrlString.appendQueryString(\r\n authority.tokenEndpoint,\r\n queryParametersString\r\n );\r\n\r\n const requestBody = await invokeAsync(\r\n this.createTokenRequestBody.bind(this),\r\n PerformanceEvents.AuthClientCreateTokenRequestBody,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(request);\r\n\r\n let ccsCredential: CcsCredential | undefined = undefined;\r\n if (request.clientInfo) {\r\n try {\r\n const clientInfo = buildClientInfo(\r\n request.clientInfo,\r\n this.cryptoUtils.base64Decode\r\n );\r\n ccsCredential = {\r\n credential: `${clientInfo.uid}${Separators.CLIENT_INFO_SEPARATOR}${clientInfo.utid}`,\r\n type: CcsCredentialType.HOME_ACCOUNT_ID,\r\n };\r\n } catch (e) {\r\n this.logger.verbose(\r\n \"Could not parse client info for CCS Header: \" + e\r\n );\r\n }\r\n }\r\n const headers: Record = this.createTokenRequestHeaders(\r\n ccsCredential || request.ccsCredential\r\n );\r\n\r\n const thumbprint = getRequestThumbprint(\r\n this.config.authOptions.clientId,\r\n request\r\n );\r\n\r\n return invokeAsync(\r\n this.executePostToTokenEndpoint.bind(this),\r\n PerformanceEvents.AuthorizationCodeClientExecutePostToTokenEndpoint,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(\r\n endpoint,\r\n requestBody,\r\n headers,\r\n thumbprint,\r\n request.correlationId,\r\n PerformanceEvents.AuthorizationCodeClientExecutePostToTokenEndpoint\r\n );\r\n }\r\n\r\n /**\r\n * Generates a map for all the params to be sent to the service\r\n * @param request\r\n */\r\n private async createTokenRequestBody(\r\n request: CommonAuthorizationCodeRequest\r\n ): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.AuthClientCreateTokenRequestBody,\r\n request.correlationId\r\n );\r\n\r\n const parameters = new Map();\r\n\r\n RequestParameterBuilder.addClientId(\r\n parameters,\r\n request.embeddedClientId ||\r\n request.tokenBodyParameters?.[AADServerParamKeys.CLIENT_ID] ||\r\n this.config.authOptions.clientId\r\n );\r\n\r\n /*\r\n * For hybrid spa flow, there will be a code but no verifier\r\n * In this scenario, don't include redirect uri as auth code will not be bound to redirect URI\r\n */\r\n if (!this.includeRedirectUri) {\r\n // Just validate\r\n if (!request.redirectUri) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.redirectUriEmpty\r\n );\r\n }\r\n } else {\r\n // Validate and include redirect uri\r\n RequestParameterBuilder.addRedirectUri(\r\n parameters,\r\n request.redirectUri\r\n );\r\n }\r\n\r\n // Add scope array, parameter builder will add default scopes and dedupe\r\n RequestParameterBuilder.addScopes(\r\n parameters,\r\n request.scopes,\r\n true,\r\n this.oidcDefaultScopes\r\n );\r\n\r\n // add code: user set, not validated\r\n RequestParameterBuilder.addAuthorizationCode(parameters, request.code);\r\n\r\n // Add library metadata\r\n RequestParameterBuilder.addLibraryInfo(\r\n parameters,\r\n this.config.libraryInfo\r\n );\r\n RequestParameterBuilder.addApplicationTelemetry(\r\n parameters,\r\n this.config.telemetry.application\r\n );\r\n RequestParameterBuilder.addThrottling(parameters);\r\n\r\n if (this.serverTelemetryManager && !isOidcProtocolMode(this.config)) {\r\n RequestParameterBuilder.addServerTelemetry(\r\n parameters,\r\n this.serverTelemetryManager\r\n );\r\n }\r\n\r\n // add code_verifier if passed\r\n if (request.codeVerifier) {\r\n RequestParameterBuilder.addCodeVerifier(\r\n parameters,\r\n request.codeVerifier\r\n );\r\n }\r\n\r\n if (this.config.clientCredentials.clientSecret) {\r\n RequestParameterBuilder.addClientSecret(\r\n parameters,\r\n this.config.clientCredentials.clientSecret\r\n );\r\n }\r\n\r\n if (this.config.clientCredentials.clientAssertion) {\r\n const clientAssertion: ClientAssertion =\r\n this.config.clientCredentials.clientAssertion;\r\n\r\n RequestParameterBuilder.addClientAssertion(\r\n parameters,\r\n await getClientAssertion(\r\n clientAssertion.assertion,\r\n this.config.authOptions.clientId,\r\n request.resourceRequestUri\r\n )\r\n );\r\n RequestParameterBuilder.addClientAssertionType(\r\n parameters,\r\n clientAssertion.assertionType\r\n );\r\n }\r\n\r\n RequestParameterBuilder.addGrantType(\r\n parameters,\r\n GrantType.AUTHORIZATION_CODE_GRANT\r\n );\r\n RequestParameterBuilder.addClientInfo(parameters);\r\n\r\n if (request.authenticationScheme === AuthenticationScheme.POP) {\r\n const popTokenGenerator = new PopTokenGenerator(\r\n this.cryptoUtils,\r\n this.performanceClient\r\n );\r\n\r\n let reqCnfData;\r\n if (!request.popKid) {\r\n const generatedReqCnfData = await invokeAsync(\r\n popTokenGenerator.generateCnf.bind(popTokenGenerator),\r\n PerformanceEvents.PopTokenGenerateCnf,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(request, this.logger);\r\n reqCnfData = generatedReqCnfData.reqCnfString;\r\n } else {\r\n reqCnfData = this.cryptoUtils.encodeKid(request.popKid);\r\n }\r\n\r\n // SPA PoP requires full Base64Url encoded req_cnf string (unhashed)\r\n RequestParameterBuilder.addPopToken(parameters, reqCnfData);\r\n } else if (request.authenticationScheme === AuthenticationScheme.SSH) {\r\n if (request.sshJwk) {\r\n RequestParameterBuilder.addSshJwk(parameters, request.sshJwk);\r\n } else {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.missingSshJwk\r\n );\r\n }\r\n }\r\n\r\n if (\r\n !StringUtils.isEmptyObj(request.claims) ||\r\n (this.config.authOptions.clientCapabilities &&\r\n this.config.authOptions.clientCapabilities.length > 0)\r\n ) {\r\n RequestParameterBuilder.addClaims(\r\n parameters,\r\n request.claims,\r\n this.config.authOptions.clientCapabilities\r\n );\r\n }\r\n\r\n let ccsCred: CcsCredential | undefined = undefined;\r\n if (request.clientInfo) {\r\n try {\r\n const clientInfo = buildClientInfo(\r\n request.clientInfo,\r\n this.cryptoUtils.base64Decode\r\n );\r\n ccsCred = {\r\n credential: `${clientInfo.uid}${Separators.CLIENT_INFO_SEPARATOR}${clientInfo.utid}`,\r\n type: CcsCredentialType.HOME_ACCOUNT_ID,\r\n };\r\n } catch (e) {\r\n this.logger.verbose(\r\n \"Could not parse client info for CCS Header: \" + e\r\n );\r\n }\r\n } else {\r\n ccsCred = request.ccsCredential;\r\n }\r\n\r\n // Adds these as parameters in the request instead of headers to prevent CORS preflight request\r\n if (this.config.systemOptions.preventCorsPreflight && ccsCred) {\r\n switch (ccsCred.type) {\r\n case CcsCredentialType.HOME_ACCOUNT_ID:\r\n try {\r\n const clientInfo = buildClientInfoFromHomeAccountId(\r\n ccsCred.credential\r\n );\r\n RequestParameterBuilder.addCcsOid(\r\n parameters,\r\n clientInfo\r\n );\r\n } catch (e) {\r\n this.logger.verbose(\r\n \"Could not parse home account ID for CCS Header: \" +\r\n e\r\n );\r\n }\r\n break;\r\n case CcsCredentialType.UPN:\r\n RequestParameterBuilder.addCcsUpn(\r\n parameters,\r\n ccsCred.credential\r\n );\r\n break;\r\n }\r\n }\r\n\r\n if (request.embeddedClientId) {\r\n RequestParameterBuilder.addBrokerParameters(\r\n parameters,\r\n this.config.authOptions.clientId,\r\n this.config.authOptions.redirectUri\r\n );\r\n }\r\n\r\n if (request.tokenBodyParameters) {\r\n RequestParameterBuilder.addExtraQueryParameters(\r\n parameters,\r\n request.tokenBodyParameters\r\n );\r\n }\r\n\r\n // Add hybrid spa parameters if not already provided\r\n if (\r\n request.enableSpaAuthorizationCode &&\r\n (!request.tokenBodyParameters ||\r\n !request.tokenBodyParameters[\r\n AADServerParamKeys.RETURN_SPA_CODE\r\n ])\r\n ) {\r\n RequestParameterBuilder.addExtraQueryParameters(parameters, {\r\n [AADServerParamKeys.RETURN_SPA_CODE]: \"1\",\r\n });\r\n }\r\n\r\n RequestParameterBuilder.instrumentBrokerParams(\r\n parameters,\r\n request.correlationId,\r\n this.performanceClient\r\n );\r\n return UrlUtils.mapToQueryString(parameters);\r\n }\r\n\r\n /**\r\n * This API validates the `EndSessionRequest` and creates a URL\r\n * @param request\r\n */\r\n private createLogoutUrlQueryString(\r\n request: CommonEndSessionRequest\r\n ): string {\r\n const parameters = new Map();\r\n\r\n if (request.postLogoutRedirectUri) {\r\n RequestParameterBuilder.addPostLogoutRedirectUri(\r\n parameters,\r\n request.postLogoutRedirectUri\r\n );\r\n }\r\n\r\n if (request.correlationId) {\r\n RequestParameterBuilder.addCorrelationId(\r\n parameters,\r\n request.correlationId\r\n );\r\n }\r\n\r\n if (request.idTokenHint) {\r\n RequestParameterBuilder.addIdTokenHint(\r\n parameters,\r\n request.idTokenHint\r\n );\r\n }\r\n\r\n if (request.state) {\r\n RequestParameterBuilder.addState(parameters, request.state);\r\n }\r\n\r\n if (request.logoutHint) {\r\n RequestParameterBuilder.addLogoutHint(\r\n parameters,\r\n request.logoutHint\r\n );\r\n }\r\n\r\n if (request.extraQueryParameters) {\r\n RequestParameterBuilder.addExtraQueryParameters(\r\n parameters,\r\n request.extraQueryParameters\r\n );\r\n }\r\n\r\n if (this.config.authOptions.instanceAware) {\r\n RequestParameterBuilder.addInstanceAware(parameters);\r\n }\r\n\r\n return UrlUtils.mapToQueryString(\r\n parameters,\r\n this.config.authOptions.encodeExtraQueryParams,\r\n request.extraQueryParameters\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n ClientConfiguration,\r\n isOidcProtocolMode,\r\n} from \"../config/ClientConfiguration.js\";\r\nimport { BaseClient } from \"./BaseClient.js\";\r\nimport { CommonRefreshTokenRequest } from \"../request/CommonRefreshTokenRequest.js\";\r\nimport { Authority } from \"../authority/Authority.js\";\r\nimport { ServerAuthorizationTokenResponse } from \"../response/ServerAuthorizationTokenResponse.js\";\r\nimport * as RequestParameterBuilder from \"../request/RequestParameterBuilder.js\";\r\nimport * as UrlUtils from \"../utils/UrlUtils.js\";\r\nimport {\r\n GrantType,\r\n AuthenticationScheme,\r\n Errors,\r\n HeaderNames,\r\n} from \"../utils/Constants.js\";\r\nimport * as AADServerParamKeys from \"../constants/AADServerParamKeys.js\";\r\nimport { ResponseHandler } from \"../response/ResponseHandler.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { PopTokenGenerator } from \"../crypto/PopTokenGenerator.js\";\r\nimport { StringUtils } from \"../utils/StringUtils.js\";\r\nimport { NetworkResponse } from \"../network/NetworkResponse.js\";\r\nimport { CommonSilentFlowRequest } from \"../request/CommonSilentFlowRequest.js\";\r\nimport {\r\n createClientConfigurationError,\r\n ClientConfigurationErrorCodes,\r\n} from \"../error/ClientConfigurationError.js\";\r\nimport {\r\n createClientAuthError,\r\n ClientAuthErrorCodes,\r\n} from \"../error/ClientAuthError.js\";\r\nimport { ServerError } from \"../error/ServerError.js\";\r\nimport * as TimeUtils from \"../utils/TimeUtils.js\";\r\nimport { UrlString } from \"../url/UrlString.js\";\r\nimport { CcsCredentialType } from \"../account/CcsCredential.js\";\r\nimport { buildClientInfoFromHomeAccountId } from \"../account/ClientInfo.js\";\r\nimport {\r\n InteractionRequiredAuthError,\r\n InteractionRequiredAuthErrorCodes,\r\n createInteractionRequiredAuthError,\r\n} from \"../error/InteractionRequiredAuthError.js\";\r\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\r\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\r\nimport { invoke, invokeAsync } from \"../utils/FunctionWrappers.js\";\r\nimport { ClientAssertion } from \"../account/ClientCredentials.js\";\r\nimport { getClientAssertion } from \"../utils/ClientAssertionUtils.js\";\r\nimport { getRequestThumbprint } from \"../network/RequestThumbprint.js\";\r\n\r\nconst DEFAULT_REFRESH_TOKEN_EXPIRATION_OFFSET_SECONDS = 300; // 5 Minutes\r\n\r\n/**\r\n * OAuth2.0 refresh token client\r\n * @internal\r\n */\r\nexport class RefreshTokenClient extends BaseClient {\r\n constructor(\r\n configuration: ClientConfiguration,\r\n performanceClient?: IPerformanceClient\r\n ) {\r\n super(configuration, performanceClient);\r\n }\r\n public async acquireToken(\r\n request: CommonRefreshTokenRequest\r\n ): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.RefreshTokenClientAcquireToken,\r\n request.correlationId\r\n );\r\n\r\n const reqTimestamp = TimeUtils.nowSeconds();\r\n const response = await invokeAsync(\r\n this.executeTokenRequest.bind(this),\r\n PerformanceEvents.RefreshTokenClientExecuteTokenRequest,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(request, this.authority);\r\n\r\n // Retrieve requestId from response headers\r\n const requestId = response.headers?.[HeaderNames.X_MS_REQUEST_ID];\r\n const responseHandler = new ResponseHandler(\r\n this.config.authOptions.clientId,\r\n this.cacheManager,\r\n this.cryptoUtils,\r\n this.logger,\r\n this.config.serializableCache,\r\n this.config.persistencePlugin\r\n );\r\n responseHandler.validateTokenResponse(response.body);\r\n\r\n return invokeAsync(\r\n responseHandler.handleServerTokenResponse.bind(responseHandler),\r\n PerformanceEvents.HandleServerTokenResponse,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(\r\n response.body,\r\n this.authority,\r\n reqTimestamp,\r\n request,\r\n undefined,\r\n undefined,\r\n true,\r\n request.forceCache,\r\n requestId\r\n );\r\n }\r\n\r\n /**\r\n * Gets cached refresh token and attaches to request, then calls acquireToken API\r\n * @param request\r\n */\r\n public async acquireTokenByRefreshToken(\r\n request: CommonSilentFlowRequest\r\n ): Promise {\r\n // Cannot renew token if no request object is given.\r\n if (!request) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.tokenRequestEmpty\r\n );\r\n }\r\n\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.RefreshTokenClientAcquireTokenByRefreshToken,\r\n request.correlationId\r\n );\r\n\r\n // We currently do not support silent flow for account === null use cases; This will be revisited for confidential flow usecases\r\n if (!request.account) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.noAccountInSilentRequest\r\n );\r\n }\r\n\r\n // try checking if FOCI is enabled for the given application\r\n const isFOCI = this.cacheManager.isAppMetadataFOCI(\r\n request.account.environment\r\n );\r\n\r\n // if the app is part of the family, retrive a Family refresh token if present and make a refreshTokenRequest\r\n if (isFOCI) {\r\n try {\r\n return await invokeAsync(\r\n this.acquireTokenWithCachedRefreshToken.bind(this),\r\n PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(request, true);\r\n } catch (e) {\r\n const noFamilyRTInCache =\r\n e instanceof InteractionRequiredAuthError &&\r\n e.errorCode ===\r\n InteractionRequiredAuthErrorCodes.noTokensFound;\r\n const clientMismatchErrorWithFamilyRT =\r\n e instanceof ServerError &&\r\n e.errorCode === Errors.INVALID_GRANT_ERROR &&\r\n e.subError === Errors.CLIENT_MISMATCH_ERROR;\r\n\r\n // if family Refresh Token (FRT) cache acquisition fails or if client_mismatch error is seen with FRT, reattempt with application Refresh Token (ART)\r\n if (noFamilyRTInCache || clientMismatchErrorWithFamilyRT) {\r\n return invokeAsync(\r\n this.acquireTokenWithCachedRefreshToken.bind(this),\r\n PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(request, false);\r\n // throw in all other cases\r\n } else {\r\n throw e;\r\n }\r\n }\r\n }\r\n // fall back to application refresh token acquisition\r\n return invokeAsync(\r\n this.acquireTokenWithCachedRefreshToken.bind(this),\r\n PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(request, false);\r\n }\r\n\r\n /**\r\n * makes a network call to acquire tokens by exchanging RefreshToken available in userCache; throws if refresh token is not cached\r\n * @param request\r\n */\r\n private async acquireTokenWithCachedRefreshToken(\r\n request: CommonSilentFlowRequest,\r\n foci: boolean\r\n ) {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.RefreshTokenClientAcquireTokenWithCachedRefreshToken,\r\n request.correlationId\r\n );\r\n\r\n // fetches family RT or application RT based on FOCI value\r\n const refreshToken = invoke(\r\n this.cacheManager.getRefreshToken.bind(this.cacheManager),\r\n PerformanceEvents.CacheManagerGetRefreshToken,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(\r\n request.account,\r\n foci,\r\n request.correlationId,\r\n undefined,\r\n this.performanceClient\r\n );\r\n\r\n if (!refreshToken) {\r\n throw createInteractionRequiredAuthError(\r\n InteractionRequiredAuthErrorCodes.noTokensFound\r\n );\r\n }\r\n\r\n if (\r\n refreshToken.expiresOn &&\r\n TimeUtils.isTokenExpired(\r\n refreshToken.expiresOn,\r\n request.refreshTokenExpirationOffsetSeconds ||\r\n DEFAULT_REFRESH_TOKEN_EXPIRATION_OFFSET_SECONDS\r\n )\r\n ) {\r\n this.performanceClient?.addFields(\r\n { rtExpiresOnMs: Number(refreshToken.expiresOn) },\r\n request.correlationId\r\n );\r\n throw createInteractionRequiredAuthError(\r\n InteractionRequiredAuthErrorCodes.refreshTokenExpired\r\n );\r\n }\r\n // attach cached RT size to the current measurement\r\n\r\n const refreshTokenRequest: CommonRefreshTokenRequest = {\r\n ...request,\r\n refreshToken: refreshToken.secret,\r\n authenticationScheme:\r\n request.authenticationScheme || AuthenticationScheme.BEARER,\r\n ccsCredential: {\r\n credential: request.account.homeAccountId,\r\n type: CcsCredentialType.HOME_ACCOUNT_ID,\r\n },\r\n };\r\n\r\n try {\r\n return await invokeAsync(\r\n this.acquireToken.bind(this),\r\n PerformanceEvents.RefreshTokenClientAcquireToken,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(refreshTokenRequest);\r\n } catch (e) {\r\n if (e instanceof InteractionRequiredAuthError) {\r\n this.performanceClient?.addFields(\r\n { rtExpiresOnMs: Number(refreshToken.expiresOn) },\r\n request.correlationId\r\n );\r\n\r\n if (e.subError === InteractionRequiredAuthErrorCodes.badToken) {\r\n // Remove bad refresh token from cache\r\n this.logger.verbose(\r\n \"acquireTokenWithRefreshToken: bad refresh token, removing from cache\"\r\n );\r\n const badRefreshTokenKey =\r\n this.cacheManager.generateCredentialKey(refreshToken);\r\n this.cacheManager.removeRefreshToken(\r\n badRefreshTokenKey,\r\n request.correlationId\r\n );\r\n }\r\n }\r\n\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Constructs the network message and makes a NW call to the underlying secure token service\r\n * @param request\r\n * @param authority\r\n */\r\n private async executeTokenRequest(\r\n request: CommonRefreshTokenRequest,\r\n authority: Authority\r\n ): Promise> {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.RefreshTokenClientExecuteTokenRequest,\r\n request.correlationId\r\n );\r\n\r\n const queryParametersString = this.createTokenQueryParameters(request);\r\n const endpoint = UrlString.appendQueryString(\r\n authority.tokenEndpoint,\r\n queryParametersString\r\n );\r\n\r\n const requestBody = await invokeAsync(\r\n this.createTokenRequestBody.bind(this),\r\n PerformanceEvents.RefreshTokenClientCreateTokenRequestBody,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(request);\r\n const headers: Record = this.createTokenRequestHeaders(\r\n request.ccsCredential\r\n );\r\n\r\n const thumbprint = getRequestThumbprint(\r\n this.config.authOptions.clientId,\r\n request\r\n );\r\n\r\n return invokeAsync(\r\n this.executePostToTokenEndpoint.bind(this),\r\n PerformanceEvents.RefreshTokenClientExecutePostToTokenEndpoint,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(\r\n endpoint,\r\n requestBody,\r\n headers,\r\n thumbprint,\r\n request.correlationId,\r\n PerformanceEvents.RefreshTokenClientExecutePostToTokenEndpoint\r\n );\r\n }\r\n\r\n /**\r\n * Helper function to create the token request body\r\n * @param request\r\n */\r\n private async createTokenRequestBody(\r\n request: CommonRefreshTokenRequest\r\n ): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.RefreshTokenClientCreateTokenRequestBody,\r\n request.correlationId\r\n );\r\n\r\n const parameters = new Map();\r\n\r\n RequestParameterBuilder.addClientId(\r\n parameters,\r\n request.embeddedClientId ||\r\n request.tokenBodyParameters?.[AADServerParamKeys.CLIENT_ID] ||\r\n this.config.authOptions.clientId\r\n );\r\n\r\n if (request.redirectUri) {\r\n RequestParameterBuilder.addRedirectUri(\r\n parameters,\r\n request.redirectUri\r\n );\r\n }\r\n\r\n RequestParameterBuilder.addScopes(\r\n parameters,\r\n request.scopes,\r\n true,\r\n this.config.authOptions.authority.options.OIDCOptions?.defaultScopes\r\n );\r\n\r\n RequestParameterBuilder.addGrantType(\r\n parameters,\r\n GrantType.REFRESH_TOKEN_GRANT\r\n );\r\n\r\n RequestParameterBuilder.addClientInfo(parameters);\r\n\r\n RequestParameterBuilder.addLibraryInfo(\r\n parameters,\r\n this.config.libraryInfo\r\n );\r\n RequestParameterBuilder.addApplicationTelemetry(\r\n parameters,\r\n this.config.telemetry.application\r\n );\r\n RequestParameterBuilder.addThrottling(parameters);\r\n\r\n if (this.serverTelemetryManager && !isOidcProtocolMode(this.config)) {\r\n RequestParameterBuilder.addServerTelemetry(\r\n parameters,\r\n this.serverTelemetryManager\r\n );\r\n }\r\n\r\n RequestParameterBuilder.addRefreshToken(\r\n parameters,\r\n request.refreshToken\r\n );\r\n\r\n if (this.config.clientCredentials.clientSecret) {\r\n RequestParameterBuilder.addClientSecret(\r\n parameters,\r\n this.config.clientCredentials.clientSecret\r\n );\r\n }\r\n\r\n if (this.config.clientCredentials.clientAssertion) {\r\n const clientAssertion: ClientAssertion =\r\n this.config.clientCredentials.clientAssertion;\r\n\r\n RequestParameterBuilder.addClientAssertion(\r\n parameters,\r\n await getClientAssertion(\r\n clientAssertion.assertion,\r\n this.config.authOptions.clientId,\r\n request.resourceRequestUri\r\n )\r\n );\r\n RequestParameterBuilder.addClientAssertionType(\r\n parameters,\r\n clientAssertion.assertionType\r\n );\r\n }\r\n\r\n if (request.authenticationScheme === AuthenticationScheme.POP) {\r\n const popTokenGenerator = new PopTokenGenerator(\r\n this.cryptoUtils,\r\n this.performanceClient\r\n );\r\n\r\n let reqCnfData;\r\n if (!request.popKid) {\r\n const generatedReqCnfData = await invokeAsync(\r\n popTokenGenerator.generateCnf.bind(popTokenGenerator),\r\n PerformanceEvents.PopTokenGenerateCnf,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(request, this.logger);\r\n\r\n reqCnfData = generatedReqCnfData.reqCnfString;\r\n } else {\r\n reqCnfData = this.cryptoUtils.encodeKid(request.popKid);\r\n }\r\n\r\n // SPA PoP requires full Base64Url encoded req_cnf string (unhashed)\r\n RequestParameterBuilder.addPopToken(parameters, reqCnfData);\r\n } else if (request.authenticationScheme === AuthenticationScheme.SSH) {\r\n if (request.sshJwk) {\r\n RequestParameterBuilder.addSshJwk(parameters, request.sshJwk);\r\n } else {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.missingSshJwk\r\n );\r\n }\r\n }\r\n\r\n if (\r\n !StringUtils.isEmptyObj(request.claims) ||\r\n (this.config.authOptions.clientCapabilities &&\r\n this.config.authOptions.clientCapabilities.length > 0)\r\n ) {\r\n RequestParameterBuilder.addClaims(\r\n parameters,\r\n request.claims,\r\n this.config.authOptions.clientCapabilities\r\n );\r\n }\r\n\r\n if (\r\n this.config.systemOptions.preventCorsPreflight &&\r\n request.ccsCredential\r\n ) {\r\n switch (request.ccsCredential.type) {\r\n case CcsCredentialType.HOME_ACCOUNT_ID:\r\n try {\r\n const clientInfo = buildClientInfoFromHomeAccountId(\r\n request.ccsCredential.credential\r\n );\r\n RequestParameterBuilder.addCcsOid(\r\n parameters,\r\n clientInfo\r\n );\r\n } catch (e) {\r\n this.logger.verbose(\r\n \"Could not parse home account ID for CCS Header: \" +\r\n e\r\n );\r\n }\r\n break;\r\n case CcsCredentialType.UPN:\r\n RequestParameterBuilder.addCcsUpn(\r\n parameters,\r\n request.ccsCredential.credential\r\n );\r\n break;\r\n }\r\n }\r\n\r\n if (request.embeddedClientId) {\r\n RequestParameterBuilder.addBrokerParameters(\r\n parameters,\r\n this.config.authOptions.clientId,\r\n this.config.authOptions.redirectUri\r\n );\r\n }\r\n\r\n if (request.tokenBodyParameters) {\r\n RequestParameterBuilder.addExtraQueryParameters(\r\n parameters,\r\n request.tokenBodyParameters\r\n );\r\n }\r\n\r\n RequestParameterBuilder.instrumentBrokerParams(\r\n parameters,\r\n request.correlationId,\r\n this.performanceClient\r\n );\r\n return UrlUtils.mapToQueryString(parameters);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { BaseClient } from \"./BaseClient.js\";\r\nimport { ClientConfiguration } from \"../config/ClientConfiguration.js\";\r\nimport { CommonSilentFlowRequest } from \"../request/CommonSilentFlowRequest.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport * as TimeUtils from \"../utils/TimeUtils.js\";\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n} from \"../error/ClientAuthError.js\";\r\nimport { ResponseHandler } from \"../response/ResponseHandler.js\";\r\nimport { CacheRecord } from \"../cache/entities/CacheRecord.js\";\r\nimport { CacheOutcome } from \"../utils/Constants.js\";\r\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\r\nimport { StringUtils } from \"../utils/StringUtils.js\";\r\nimport { checkMaxAge, extractTokenClaims } from \"../account/AuthToken.js\";\r\nimport { TokenClaims } from \"../account/TokenClaims.js\";\r\nimport { PerformanceEvents } from \"../telemetry/performance/PerformanceEvent.js\";\r\nimport { invokeAsync } from \"../utils/FunctionWrappers.js\";\r\nimport { getTenantFromAuthorityString } from \"../authority/Authority.js\";\r\n\r\n/** @internal */\r\nexport class SilentFlowClient extends BaseClient {\r\n constructor(\r\n configuration: ClientConfiguration,\r\n performanceClient?: IPerformanceClient\r\n ) {\r\n super(configuration, performanceClient);\r\n }\r\n\r\n /**\r\n * Retrieves token from cache or throws an error if it must be refreshed.\r\n * @param request\r\n */\r\n async acquireCachedToken(\r\n request: CommonSilentFlowRequest\r\n ): Promise<[AuthenticationResult, CacheOutcome]> {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.SilentFlowClientAcquireCachedToken,\r\n request.correlationId\r\n );\r\n let lastCacheOutcome: CacheOutcome = CacheOutcome.NOT_APPLICABLE;\r\n\r\n if (\r\n request.forceRefresh ||\r\n (!this.config.cacheOptions.claimsBasedCachingEnabled &&\r\n !StringUtils.isEmptyObj(request.claims))\r\n ) {\r\n // Must refresh due to present force_refresh flag.\r\n this.setCacheOutcome(\r\n CacheOutcome.FORCE_REFRESH_OR_CLAIMS,\r\n request.correlationId\r\n );\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.tokenRefreshRequired\r\n );\r\n }\r\n\r\n // We currently do not support silent flow for account === null use cases; This will be revisited for confidential flow usecases\r\n if (!request.account) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.noAccountInSilentRequest\r\n );\r\n }\r\n\r\n const requestTenantId =\r\n request.account.tenantId ||\r\n getTenantFromAuthorityString(request.authority);\r\n const tokenKeys = this.cacheManager.getTokenKeys();\r\n const cachedAccessToken = this.cacheManager.getAccessToken(\r\n request.account,\r\n request,\r\n tokenKeys,\r\n requestTenantId\r\n );\r\n\r\n if (!cachedAccessToken) {\r\n // must refresh due to non-existent access_token\r\n this.setCacheOutcome(\r\n CacheOutcome.NO_CACHED_ACCESS_TOKEN,\r\n request.correlationId\r\n );\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.tokenRefreshRequired\r\n );\r\n } else if (\r\n TimeUtils.wasClockTurnedBack(cachedAccessToken.cachedAt) ||\r\n TimeUtils.isTokenExpired(\r\n cachedAccessToken.expiresOn,\r\n this.config.systemOptions.tokenRenewalOffsetSeconds\r\n )\r\n ) {\r\n // must refresh due to the expires_in value\r\n this.setCacheOutcome(\r\n CacheOutcome.CACHED_ACCESS_TOKEN_EXPIRED,\r\n request.correlationId\r\n );\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.tokenRefreshRequired\r\n );\r\n } else if (\r\n cachedAccessToken.refreshOn &&\r\n TimeUtils.isTokenExpired(cachedAccessToken.refreshOn, 0)\r\n ) {\r\n // must refresh (in the background) due to the refresh_in value\r\n lastCacheOutcome = CacheOutcome.PROACTIVELY_REFRESHED;\r\n\r\n // don't throw ClientAuthError.createRefreshRequiredError(), return cached token instead\r\n }\r\n\r\n const environment =\r\n request.authority || this.authority.getPreferredCache();\r\n const cacheRecord: CacheRecord = {\r\n account: this.cacheManager.getAccount(\r\n this.cacheManager.generateAccountKey(request.account),\r\n request.correlationId\r\n ),\r\n accessToken: cachedAccessToken,\r\n idToken: this.cacheManager.getIdToken(\r\n request.account,\r\n request.correlationId,\r\n tokenKeys,\r\n requestTenantId,\r\n this.performanceClient\r\n ),\r\n refreshToken: null,\r\n appMetadata:\r\n this.cacheManager.readAppMetadataFromCache(environment),\r\n };\r\n\r\n this.setCacheOutcome(lastCacheOutcome, request.correlationId);\r\n\r\n if (this.config.serverTelemetryManager) {\r\n this.config.serverTelemetryManager.incrementCacheHits();\r\n }\r\n\r\n return [\r\n await invokeAsync(\r\n this.generateResultFromCacheRecord.bind(this),\r\n PerformanceEvents.SilentFlowClientGenerateResultFromCacheRecord,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(cacheRecord, request),\r\n lastCacheOutcome,\r\n ];\r\n }\r\n\r\n private setCacheOutcome(\r\n cacheOutcome: CacheOutcome,\r\n correlationId: string\r\n ): void {\r\n this.serverTelemetryManager?.setCacheOutcome(cacheOutcome);\r\n this.performanceClient?.addFields(\r\n {\r\n cacheOutcome: cacheOutcome,\r\n },\r\n correlationId\r\n );\r\n if (cacheOutcome !== CacheOutcome.NOT_APPLICABLE) {\r\n this.logger.info(\r\n `Token refresh is required due to cache outcome: ${cacheOutcome}`\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Helper function to build response object from the CacheRecord\r\n * @param cacheRecord\r\n */\r\n private async generateResultFromCacheRecord(\r\n cacheRecord: CacheRecord,\r\n request: CommonSilentFlowRequest\r\n ): Promise {\r\n this.performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.SilentFlowClientGenerateResultFromCacheRecord,\r\n request.correlationId\r\n );\r\n let idTokenClaims: TokenClaims | undefined;\r\n if (cacheRecord.idToken) {\r\n idTokenClaims = extractTokenClaims(\r\n cacheRecord.idToken.secret,\r\n this.config.cryptoInterface.base64Decode\r\n );\r\n }\r\n\r\n // token max_age check\r\n if (request.maxAge || request.maxAge === 0) {\r\n const authTime = idTokenClaims?.auth_time;\r\n if (!authTime) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.authTimeNotFound\r\n );\r\n }\r\n\r\n checkMaxAge(authTime, request.maxAge);\r\n }\r\n\r\n return ResponseHandler.generateAuthenticationResult(\r\n this.cryptoUtils,\r\n this.authority,\r\n cacheRecord,\r\n true,\r\n request,\r\n idTokenClaims\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n} from \"../error/ClientAuthError.js\";\r\nimport { NetworkResponse } from \"./NetworkResponse.js\";\r\n\r\n/**\r\n * Options allowed by network request APIs.\r\n */\r\nexport type NetworkRequestOptions = {\r\n headers?: Record;\r\n body?: string;\r\n};\r\n\r\n/**\r\n * Client network interface to send backend requests.\r\n * @interface\r\n */\r\nexport interface INetworkModule {\r\n /**\r\n * Interface function for async network \"GET\" requests. Based on the Fetch standard: https://fetch.spec.whatwg.org/\r\n * @param url\r\n * @param requestParams\r\n * @param enableCaching\r\n */\r\n sendGetRequestAsync(\r\n url: string,\r\n options?: NetworkRequestOptions,\r\n timeout?: number\r\n ): Promise>;\r\n\r\n /**\r\n * Interface function for async network \"POST\" requests. Based on the Fetch standard: https://fetch.spec.whatwg.org/\r\n * @param url\r\n * @param requestParams\r\n * @param enableCaching\r\n */\r\n sendPostRequestAsync(\r\n url: string,\r\n options?: NetworkRequestOptions\r\n ): Promise>;\r\n}\r\n\r\nexport const StubbedNetworkModule: INetworkModule = {\r\n sendGetRequestAsync: () => {\r\n return Promise.reject(\r\n createClientAuthError(ClientAuthErrorCodes.methodNotImplemented)\r\n );\r\n },\r\n sendPostRequestAsync: () => {\r\n return Promise.reject(\r\n createClientAuthError(ClientAuthErrorCodes.methodNotImplemented)\r\n );\r\n },\r\n};\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { CommonAuthorizationUrlRequest } from \"../request/CommonAuthorizationUrlRequest.js\";\r\nimport * as RequestParameterBuilder from \"../request/RequestParameterBuilder.js\";\r\nimport { IPerformanceClient } from \"../telemetry/performance/IPerformanceClient.js\";\r\nimport * as AADServerParamKeys from \"../constants/AADServerParamKeys.js\";\r\nimport { AuthOptions } from \"../config/ClientConfiguration.js\";\r\nimport { PromptValue } from \"../utils/Constants.js\";\r\nimport { AccountInfo } from \"../account/AccountInfo.js\";\r\nimport { Logger } from \"../logger/Logger.js\";\r\nimport { buildClientInfoFromHomeAccountId } from \"../account/ClientInfo.js\";\r\nimport { Authority } from \"../authority/Authority.js\";\r\nimport { mapToQueryString } from \"../utils/UrlUtils.js\";\r\nimport { UrlString } from \"../url/UrlString.js\";\r\nimport { AuthorizationCodePayload } from \"../response/AuthorizationCodePayload.js\";\r\nimport { AuthorizeResponse } from \"../response/AuthorizeResponse.js\";\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n} from \"../error/ClientAuthError.js\";\r\nimport {\r\n InteractionRequiredAuthError,\r\n isInteractionRequiredError,\r\n} from \"../error/InteractionRequiredAuthError.js\";\r\nimport { ServerError } from \"../error/ServerError.js\";\r\nimport { StringDict } from \"../utils/MsalTypes.js\";\r\n\r\n/**\r\n * Returns map of parameters that are applicable to all calls to /authorize whether using PKCE or EAR\r\n * @param config\r\n * @param request\r\n * @param logger\r\n * @param performanceClient\r\n * @returns\r\n */\r\nexport function getStandardAuthorizeRequestParameters(\r\n authOptions: AuthOptions,\r\n request: CommonAuthorizationUrlRequest,\r\n logger: Logger,\r\n performanceClient?: IPerformanceClient\r\n): Map {\r\n // generate the correlationId if not set by the user and add\r\n const correlationId = request.correlationId;\r\n\r\n const parameters = new Map();\r\n\r\n RequestParameterBuilder.addClientId(\r\n parameters,\r\n request.embeddedClientId ||\r\n request.extraQueryParameters?.[AADServerParamKeys.CLIENT_ID] ||\r\n authOptions.clientId\r\n );\r\n\r\n const requestScopes = [\r\n ...(request.scopes || []),\r\n ...(request.extraScopesToConsent || []),\r\n ];\r\n RequestParameterBuilder.addScopes(\r\n parameters,\r\n requestScopes,\r\n true,\r\n authOptions.authority.options.OIDCOptions?.defaultScopes\r\n );\r\n\r\n RequestParameterBuilder.addRedirectUri(parameters, request.redirectUri);\r\n\r\n RequestParameterBuilder.addCorrelationId(parameters, correlationId);\r\n\r\n // add response_mode. If not passed in it defaults to query.\r\n RequestParameterBuilder.addResponseMode(parameters, request.responseMode);\r\n\r\n // add client_info=1\r\n RequestParameterBuilder.addClientInfo(parameters);\r\n\r\n if (request.prompt) {\r\n RequestParameterBuilder.addPrompt(parameters, request.prompt);\r\n performanceClient?.addFields({ prompt: request.prompt }, correlationId);\r\n }\r\n\r\n if (request.domainHint) {\r\n RequestParameterBuilder.addDomainHint(parameters, request.domainHint);\r\n performanceClient?.addFields(\r\n { domainHintFromRequest: true },\r\n correlationId\r\n );\r\n }\r\n\r\n // Add sid or loginHint with preference for login_hint claim (in request) -> sid -> loginHint (upn/email) -> username of AccountInfo object\r\n if (request.prompt !== PromptValue.SELECT_ACCOUNT) {\r\n // AAD will throw if prompt=select_account is passed with an account hint\r\n if (request.sid && request.prompt === PromptValue.NONE) {\r\n // SessionID is only used in silent calls\r\n logger.verbose(\r\n \"createAuthCodeUrlQueryString: Prompt is none, adding sid from request\"\r\n );\r\n RequestParameterBuilder.addSid(parameters, request.sid);\r\n performanceClient?.addFields(\r\n { sidFromRequest: true },\r\n correlationId\r\n );\r\n } else if (request.account) {\r\n const accountSid = extractAccountSid(request.account);\r\n let accountLoginHintClaim = extractLoginHint(request.account);\r\n\r\n if (accountLoginHintClaim && request.domainHint) {\r\n logger.warning(\r\n `AuthorizationCodeClient.createAuthCodeUrlQueryString: \"domainHint\" param is set, skipping opaque \"login_hint\" claim. Please consider not passing domainHint`\r\n );\r\n accountLoginHintClaim = null;\r\n }\r\n\r\n // If login_hint claim is present, use it over sid/username\r\n if (accountLoginHintClaim) {\r\n logger.verbose(\r\n \"createAuthCodeUrlQueryString: login_hint claim present on account\"\r\n );\r\n RequestParameterBuilder.addLoginHint(\r\n parameters,\r\n accountLoginHintClaim\r\n );\r\n performanceClient?.addFields(\r\n { loginHintFromClaim: true },\r\n correlationId\r\n );\r\n try {\r\n const clientInfo = buildClientInfoFromHomeAccountId(\r\n request.account.homeAccountId\r\n );\r\n RequestParameterBuilder.addCcsOid(parameters, clientInfo);\r\n } catch (e) {\r\n logger.verbose(\r\n \"createAuthCodeUrlQueryString: Could not parse home account ID for CCS Header\"\r\n );\r\n }\r\n } else if (accountSid && request.prompt === PromptValue.NONE) {\r\n /*\r\n * If account and loginHint are provided, we will check account first for sid before adding loginHint\r\n * SessionId is only used in silent calls\r\n */\r\n logger.verbose(\r\n \"createAuthCodeUrlQueryString: Prompt is none, adding sid from account\"\r\n );\r\n RequestParameterBuilder.addSid(parameters, accountSid);\r\n performanceClient?.addFields(\r\n { sidFromClaim: true },\r\n correlationId\r\n );\r\n try {\r\n const clientInfo = buildClientInfoFromHomeAccountId(\r\n request.account.homeAccountId\r\n );\r\n RequestParameterBuilder.addCcsOid(parameters, clientInfo);\r\n } catch (e) {\r\n logger.verbose(\r\n \"createAuthCodeUrlQueryString: Could not parse home account ID for CCS Header\"\r\n );\r\n }\r\n } else if (request.loginHint) {\r\n logger.verbose(\r\n \"createAuthCodeUrlQueryString: Adding login_hint from request\"\r\n );\r\n RequestParameterBuilder.addLoginHint(\r\n parameters,\r\n request.loginHint\r\n );\r\n RequestParameterBuilder.addCcsUpn(\r\n parameters,\r\n request.loginHint\r\n );\r\n performanceClient?.addFields(\r\n { loginHintFromRequest: true },\r\n correlationId\r\n );\r\n } else if (request.account.username) {\r\n // Fallback to account username if provided\r\n logger.verbose(\r\n \"createAuthCodeUrlQueryString: Adding login_hint from account\"\r\n );\r\n RequestParameterBuilder.addLoginHint(\r\n parameters,\r\n request.account.username\r\n );\r\n performanceClient?.addFields(\r\n { loginHintFromUpn: true },\r\n correlationId\r\n );\r\n try {\r\n const clientInfo = buildClientInfoFromHomeAccountId(\r\n request.account.homeAccountId\r\n );\r\n RequestParameterBuilder.addCcsOid(parameters, clientInfo);\r\n } catch (e) {\r\n logger.verbose(\r\n \"createAuthCodeUrlQueryString: Could not parse home account ID for CCS Header\"\r\n );\r\n }\r\n }\r\n } else if (request.loginHint) {\r\n logger.verbose(\r\n \"createAuthCodeUrlQueryString: No account, adding login_hint from request\"\r\n );\r\n RequestParameterBuilder.addLoginHint(parameters, request.loginHint);\r\n RequestParameterBuilder.addCcsUpn(parameters, request.loginHint);\r\n performanceClient?.addFields(\r\n { loginHintFromRequest: true },\r\n correlationId\r\n );\r\n }\r\n } else {\r\n logger.verbose(\r\n \"createAuthCodeUrlQueryString: Prompt is select_account, ignoring account hints\"\r\n );\r\n }\r\n\r\n if (request.nonce) {\r\n RequestParameterBuilder.addNonce(parameters, request.nonce);\r\n }\r\n\r\n if (request.state) {\r\n RequestParameterBuilder.addState(parameters, request.state);\r\n }\r\n\r\n if (\r\n request.claims ||\r\n (authOptions.clientCapabilities &&\r\n authOptions.clientCapabilities.length > 0)\r\n ) {\r\n RequestParameterBuilder.addClaims(\r\n parameters,\r\n request.claims,\r\n authOptions.clientCapabilities\r\n );\r\n }\r\n\r\n if (request.embeddedClientId) {\r\n RequestParameterBuilder.addBrokerParameters(\r\n parameters,\r\n authOptions.clientId,\r\n authOptions.redirectUri\r\n );\r\n }\r\n\r\n // If extraQueryParameters includes instance_aware its value will be added when extraQueryParameters are added\r\n if (\r\n authOptions.instanceAware &&\r\n (!request.extraQueryParameters ||\r\n !Object.keys(request.extraQueryParameters).includes(\r\n AADServerParamKeys.INSTANCE_AWARE\r\n ))\r\n ) {\r\n RequestParameterBuilder.addInstanceAware(parameters);\r\n }\r\n\r\n return parameters;\r\n}\r\n\r\n/**\r\n * Returns authorize endpoint with given request parameters in the query string\r\n * @param authority\r\n * @param requestParameters\r\n * @returns\r\n */\r\nexport function getAuthorizeUrl(\r\n authority: Authority,\r\n requestParameters: Map,\r\n encodeParams?: boolean,\r\n extraQueryParameters?: StringDict | undefined\r\n): string {\r\n const queryString = mapToQueryString(\r\n requestParameters,\r\n encodeParams,\r\n extraQueryParameters\r\n );\r\n return UrlString.appendQueryString(\r\n authority.authorizationEndpoint,\r\n queryString\r\n );\r\n}\r\n\r\n/**\r\n * Handles the hash fragment response from public client code request. Returns a code response used by\r\n * the client to exchange for a token in acquireToken.\r\n * @param serverParams\r\n * @param cachedState\r\n */\r\nexport function getAuthorizationCodePayload(\r\n serverParams: AuthorizeResponse,\r\n cachedState: string\r\n): AuthorizationCodePayload {\r\n // Get code response\r\n validateAuthorizationResponse(serverParams, cachedState);\r\n\r\n // throw when there is no auth code in the response\r\n if (!serverParams.code) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.authorizationCodeMissingFromServerResponse\r\n );\r\n }\r\n\r\n return serverParams as AuthorizationCodePayload;\r\n}\r\n\r\n/**\r\n * Function which validates server authorization code response.\r\n * @param serverResponseHash\r\n * @param requestState\r\n */\r\nexport function validateAuthorizationResponse(\r\n serverResponse: AuthorizeResponse,\r\n requestState: string\r\n): void {\r\n if (!serverResponse.state || !requestState) {\r\n throw serverResponse.state\r\n ? createClientAuthError(\r\n ClientAuthErrorCodes.stateNotFound,\r\n \"Cached State\"\r\n )\r\n : createClientAuthError(\r\n ClientAuthErrorCodes.stateNotFound,\r\n \"Server State\"\r\n );\r\n }\r\n\r\n let decodedServerResponseState: string;\r\n let decodedRequestState: string;\r\n\r\n try {\r\n decodedServerResponseState = decodeURIComponent(serverResponse.state);\r\n } catch (e) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.invalidState,\r\n serverResponse.state\r\n );\r\n }\r\n\r\n try {\r\n decodedRequestState = decodeURIComponent(requestState);\r\n } catch (e) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.invalidState,\r\n serverResponse.state\r\n );\r\n }\r\n\r\n if (decodedServerResponseState !== decodedRequestState) {\r\n throw createClientAuthError(ClientAuthErrorCodes.stateMismatch);\r\n }\r\n\r\n // Check for error\r\n if (\r\n serverResponse.error ||\r\n serverResponse.error_description ||\r\n serverResponse.suberror\r\n ) {\r\n const serverErrorNo = parseServerErrorNo(serverResponse);\r\n if (\r\n isInteractionRequiredError(\r\n serverResponse.error,\r\n serverResponse.error_description,\r\n serverResponse.suberror\r\n )\r\n ) {\r\n throw new InteractionRequiredAuthError(\r\n serverResponse.error || \"\",\r\n serverResponse.error_description,\r\n serverResponse.suberror,\r\n serverResponse.timestamp || \"\",\r\n serverResponse.trace_id || \"\",\r\n serverResponse.correlation_id || \"\",\r\n serverResponse.claims || \"\",\r\n serverErrorNo\r\n );\r\n }\r\n\r\n throw new ServerError(\r\n serverResponse.error || \"\",\r\n serverResponse.error_description,\r\n serverResponse.suberror,\r\n serverErrorNo\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Get server error No from the error_uri\r\n * @param serverResponse\r\n * @returns\r\n */\r\nfunction parseServerErrorNo(\r\n serverResponse: AuthorizeResponse\r\n): string | undefined {\r\n const errorCodePrefix = \"code=\";\r\n const errorCodePrefixIndex =\r\n serverResponse.error_uri?.lastIndexOf(errorCodePrefix);\r\n return errorCodePrefixIndex && errorCodePrefixIndex >= 0\r\n ? serverResponse.error_uri?.substring(\r\n errorCodePrefixIndex + errorCodePrefix.length\r\n )\r\n : undefined;\r\n}\r\n\r\n/**\r\n * Helper to get sid from account. Returns null if idTokenClaims are not present or sid is not present.\r\n * @param account\r\n */\r\nfunction extractAccountSid(account: AccountInfo): string | null {\r\n return account.idTokenClaims?.sid || null;\r\n}\r\n\r\nfunction extractLoginHint(account: AccountInfo): string | null {\r\n return account.loginHint || account.idTokenClaims?.login_hint || null;\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n createClientConfigurationError,\r\n ClientConfigurationErrorCodes,\r\n} from \"../error/ClientConfigurationError.js\";\r\nimport { Constants, HeaderNames } from \"../utils/Constants.js\";\r\n\r\ntype WWWAuthenticateChallenges = {\r\n nonce?: string;\r\n};\r\n\r\ntype AuthenticationInfoChallenges = {\r\n nextnonce?: string;\r\n};\r\n\r\n/**\r\n * This is a helper class that parses supported HTTP response authentication headers to extract and return\r\n * header challenge values that can be used outside the basic authorization flows.\r\n */\r\nexport class AuthenticationHeaderParser {\r\n private headers: Record;\r\n\r\n constructor(headers: Record) {\r\n this.headers = headers;\r\n }\r\n\r\n /**\r\n * This method parses the SHR nonce value out of either the Authentication-Info or WWW-Authenticate authentication headers.\r\n * @returns\r\n */\r\n getShrNonce(): string {\r\n // Attempt to parse nonce from Authentiacation-Info\r\n const authenticationInfo = this.headers[HeaderNames.AuthenticationInfo];\r\n if (authenticationInfo) {\r\n const authenticationInfoChallenges =\r\n this.parseChallenges(\r\n authenticationInfo\r\n );\r\n if (authenticationInfoChallenges.nextnonce) {\r\n return authenticationInfoChallenges.nextnonce;\r\n }\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.invalidAuthenticationHeader\r\n );\r\n }\r\n\r\n // Attempt to parse nonce from WWW-Authenticate\r\n const wwwAuthenticate = this.headers[HeaderNames.WWWAuthenticate];\r\n if (wwwAuthenticate) {\r\n const wwwAuthenticateChallenges =\r\n this.parseChallenges(\r\n wwwAuthenticate\r\n );\r\n if (wwwAuthenticateChallenges.nonce) {\r\n return wwwAuthenticateChallenges.nonce;\r\n }\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.invalidAuthenticationHeader\r\n );\r\n }\r\n\r\n // If neither header is present, throw missing headers error\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.missingNonceAuthenticationHeader\r\n );\r\n }\r\n\r\n /**\r\n * Parses an HTTP header's challenge set into a key/value map.\r\n * @param header\r\n * @returns\r\n */\r\n private parseChallenges(header: string): T {\r\n const schemeSeparator = header.indexOf(\" \");\r\n const challenges = header.substr(schemeSeparator + 1).split(\",\");\r\n const challengeMap = {} as T;\r\n\r\n challenges.forEach((challenge: string) => {\r\n const [key, value] = challenge.split(\"=\");\r\n // Remove escaped quotation marks (', \") from challenge string to keep only the challenge value\r\n challengeMap[key] = unescape(\r\n value.replace(/['\"]+/g, Constants.EMPTY_STRING)\r\n );\r\n });\r\n\r\n return challengeMap;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n SERVER_TELEM_CONSTANTS,\r\n Separators,\r\n CacheOutcome,\r\n Constants,\r\n RegionDiscoverySources,\r\n RegionDiscoveryOutcomes,\r\n} from \"../../utils/Constants.js\";\r\nimport { CacheManager } from \"../../cache/CacheManager.js\";\r\nimport { AuthError } from \"../../error/AuthError.js\";\r\nimport { ServerTelemetryRequest } from \"./ServerTelemetryRequest.js\";\r\nimport { ServerTelemetryEntity } from \"../../cache/entities/ServerTelemetryEntity.js\";\r\nimport { RegionDiscoveryMetadata } from \"../../authority/RegionDiscoveryMetadata.js\";\r\n\r\nconst skuGroupSeparator = \",\";\r\nconst skuValueSeparator = \"|\";\r\n\r\ntype SkuParams = {\r\n libraryName?: string;\r\n libraryVersion?: string;\r\n extensionName?: string;\r\n extensionVersion?: string;\r\n skus?: string;\r\n};\r\n\r\nfunction makeExtraSkuString(params: SkuParams): string {\r\n const {\r\n skus,\r\n libraryName,\r\n libraryVersion,\r\n extensionName,\r\n extensionVersion,\r\n } = params;\r\n const skuMap: Map = new Map([\r\n [0, [libraryName, libraryVersion]],\r\n [2, [extensionName, extensionVersion]],\r\n ]);\r\n let skuArr: string[] = [];\r\n\r\n if (skus?.length) {\r\n skuArr = skus.split(skuGroupSeparator);\r\n\r\n // Ignore invalid input sku param\r\n if (skuArr.length < 4) {\r\n return skus;\r\n }\r\n } else {\r\n skuArr = Array.from({ length: 4 }, () => skuValueSeparator);\r\n }\r\n\r\n skuMap.forEach((value, key) => {\r\n if (value.length === 2 && value[0]?.length && value[1]?.length) {\r\n setSku({\r\n skuArr,\r\n index: key,\r\n skuName: value[0],\r\n skuVersion: value[1],\r\n });\r\n }\r\n });\r\n\r\n return skuArr.join(skuGroupSeparator);\r\n}\r\n\r\nfunction setSku(params: {\r\n skuArr: string[];\r\n index: number;\r\n skuName: string;\r\n skuVersion: string;\r\n}): void {\r\n const { skuArr, index, skuName, skuVersion } = params;\r\n if (index >= skuArr.length) {\r\n return;\r\n }\r\n skuArr[index] = [skuName, skuVersion].join(skuValueSeparator);\r\n}\r\n\r\n/** @internal */\r\nexport class ServerTelemetryManager {\r\n private cacheManager: CacheManager;\r\n private apiId: number;\r\n private correlationId: string;\r\n private telemetryCacheKey: string;\r\n private wrapperSKU: String;\r\n private wrapperVer: String;\r\n private regionUsed: string | undefined;\r\n private regionSource: RegionDiscoverySources | undefined;\r\n private regionOutcome: RegionDiscoveryOutcomes | undefined;\r\n private cacheOutcome: CacheOutcome = CacheOutcome.NOT_APPLICABLE;\r\n\r\n constructor(\r\n telemetryRequest: ServerTelemetryRequest,\r\n cacheManager: CacheManager\r\n ) {\r\n this.cacheManager = cacheManager;\r\n this.apiId = telemetryRequest.apiId;\r\n this.correlationId = telemetryRequest.correlationId;\r\n this.wrapperSKU = telemetryRequest.wrapperSKU || Constants.EMPTY_STRING;\r\n this.wrapperVer = telemetryRequest.wrapperVer || Constants.EMPTY_STRING;\r\n\r\n this.telemetryCacheKey =\r\n SERVER_TELEM_CONSTANTS.CACHE_KEY +\r\n Separators.CACHE_KEY_SEPARATOR +\r\n telemetryRequest.clientId;\r\n }\r\n\r\n /**\r\n * API to add MSER Telemetry to request\r\n */\r\n generateCurrentRequestHeaderValue(): string {\r\n const request = `${this.apiId}${SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR}${this.cacheOutcome}`;\r\n const platformFieldsArr = [this.wrapperSKU, this.wrapperVer];\r\n const nativeBrokerErrorCode = this.getNativeBrokerErrorCode();\r\n if (nativeBrokerErrorCode?.length) {\r\n platformFieldsArr.push(`broker_error=${nativeBrokerErrorCode}`);\r\n }\r\n const platformFields = platformFieldsArr.join(\r\n SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR\r\n );\r\n const regionDiscoveryFields = this.getRegionDiscoveryFields();\r\n const requestWithRegionDiscoveryFields = [\r\n request,\r\n regionDiscoveryFields,\r\n ].join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR);\r\n\r\n return [\r\n SERVER_TELEM_CONSTANTS.SCHEMA_VERSION,\r\n requestWithRegionDiscoveryFields,\r\n platformFields,\r\n ].join(SERVER_TELEM_CONSTANTS.CATEGORY_SEPARATOR);\r\n }\r\n\r\n /**\r\n * API to add MSER Telemetry for the last failed request\r\n */\r\n generateLastRequestHeaderValue(): string {\r\n const lastRequests = this.getLastRequests();\r\n\r\n const maxErrors = ServerTelemetryManager.maxErrorsToSend(lastRequests);\r\n const failedRequests = lastRequests.failedRequests\r\n .slice(0, 2 * maxErrors)\r\n .join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR);\r\n const errors = lastRequests.errors\r\n .slice(0, maxErrors)\r\n .join(SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR);\r\n const errorCount = lastRequests.errors.length;\r\n\r\n // Indicate whether this header contains all data or partial data\r\n const overflow =\r\n maxErrors < errorCount\r\n ? SERVER_TELEM_CONSTANTS.OVERFLOW_TRUE\r\n : SERVER_TELEM_CONSTANTS.OVERFLOW_FALSE;\r\n const platformFields = [errorCount, overflow].join(\r\n SERVER_TELEM_CONSTANTS.VALUE_SEPARATOR\r\n );\r\n\r\n return [\r\n SERVER_TELEM_CONSTANTS.SCHEMA_VERSION,\r\n lastRequests.cacheHits,\r\n failedRequests,\r\n errors,\r\n platformFields,\r\n ].join(SERVER_TELEM_CONSTANTS.CATEGORY_SEPARATOR);\r\n }\r\n\r\n /**\r\n * API to cache token failures for MSER data capture\r\n * @param error\r\n */\r\n cacheFailedRequest(error: unknown): void {\r\n const lastRequests = this.getLastRequests();\r\n if (\r\n lastRequests.errors.length >=\r\n SERVER_TELEM_CONSTANTS.MAX_CACHED_ERRORS\r\n ) {\r\n // Remove a cached error to make room, first in first out\r\n lastRequests.failedRequests.shift(); // apiId\r\n lastRequests.failedRequests.shift(); // correlationId\r\n lastRequests.errors.shift();\r\n }\r\n\r\n lastRequests.failedRequests.push(this.apiId, this.correlationId);\r\n\r\n if (error instanceof Error && !!error && error.toString()) {\r\n if (error instanceof AuthError) {\r\n if (error.subError) {\r\n lastRequests.errors.push(error.subError);\r\n } else if (error.errorCode) {\r\n lastRequests.errors.push(error.errorCode);\r\n } else {\r\n lastRequests.errors.push(error.toString());\r\n }\r\n } else {\r\n lastRequests.errors.push(error.toString());\r\n }\r\n } else {\r\n lastRequests.errors.push(SERVER_TELEM_CONSTANTS.UNKNOWN_ERROR);\r\n }\r\n\r\n this.cacheManager.setServerTelemetry(\r\n this.telemetryCacheKey,\r\n lastRequests,\r\n this.correlationId\r\n );\r\n\r\n return;\r\n }\r\n\r\n /**\r\n * Update server telemetry cache entry by incrementing cache hit counter\r\n */\r\n incrementCacheHits(): number {\r\n const lastRequests = this.getLastRequests();\r\n lastRequests.cacheHits += 1;\r\n\r\n this.cacheManager.setServerTelemetry(\r\n this.telemetryCacheKey,\r\n lastRequests,\r\n this.correlationId\r\n );\r\n return lastRequests.cacheHits;\r\n }\r\n\r\n /**\r\n * Get the server telemetry entity from cache or initialize a new one\r\n */\r\n getLastRequests(): ServerTelemetryEntity {\r\n const initialValue: ServerTelemetryEntity = {\r\n failedRequests: [],\r\n errors: [],\r\n cacheHits: 0,\r\n };\r\n const lastRequests = this.cacheManager.getServerTelemetry(\r\n this.telemetryCacheKey\r\n ) as ServerTelemetryEntity;\r\n\r\n return lastRequests || initialValue;\r\n }\r\n\r\n /**\r\n * Remove server telemetry cache entry\r\n */\r\n clearTelemetryCache(): void {\r\n const lastRequests = this.getLastRequests();\r\n const numErrorsFlushed =\r\n ServerTelemetryManager.maxErrorsToSend(lastRequests);\r\n const errorCount = lastRequests.errors.length;\r\n if (numErrorsFlushed === errorCount) {\r\n // All errors were sent on last request, clear Telemetry cache\r\n this.cacheManager.removeItem(\r\n this.telemetryCacheKey,\r\n this.correlationId\r\n );\r\n } else {\r\n // Partial data was flushed to server, construct a new telemetry cache item with errors that were not flushed\r\n const serverTelemEntity: ServerTelemetryEntity = {\r\n failedRequests: lastRequests.failedRequests.slice(\r\n numErrorsFlushed * 2\r\n ), // failedRequests contains 2 items for each error\r\n errors: lastRequests.errors.slice(numErrorsFlushed),\r\n cacheHits: 0,\r\n };\r\n\r\n this.cacheManager.setServerTelemetry(\r\n this.telemetryCacheKey,\r\n serverTelemEntity,\r\n this.correlationId\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Returns the maximum number of errors that can be flushed to the server in the next network request\r\n * @param serverTelemetryEntity\r\n */\r\n static maxErrorsToSend(\r\n serverTelemetryEntity: ServerTelemetryEntity\r\n ): number {\r\n let i;\r\n let maxErrors = 0;\r\n let dataSize = 0;\r\n const errorCount = serverTelemetryEntity.errors.length;\r\n for (i = 0; i < errorCount; i++) {\r\n // failedRequests parameter contains pairs of apiId and correlationId, multiply index by 2 to preserve pairs\r\n const apiId =\r\n serverTelemetryEntity.failedRequests[2 * i] ||\r\n Constants.EMPTY_STRING;\r\n const correlationId =\r\n serverTelemetryEntity.failedRequests[2 * i + 1] ||\r\n Constants.EMPTY_STRING;\r\n const errorCode =\r\n serverTelemetryEntity.errors[i] || Constants.EMPTY_STRING;\r\n\r\n // Count number of characters that would be added to header, each character is 1 byte. Add 3 at the end to account for separators\r\n dataSize +=\r\n apiId.toString().length +\r\n correlationId.toString().length +\r\n errorCode.length +\r\n 3;\r\n\r\n if (dataSize < SERVER_TELEM_CONSTANTS.MAX_LAST_HEADER_BYTES) {\r\n // Adding this entry to the header would still keep header size below the limit\r\n maxErrors += 1;\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n return maxErrors;\r\n }\r\n\r\n /**\r\n * Get the region discovery fields\r\n *\r\n * @returns string\r\n */\r\n getRegionDiscoveryFields(): string {\r\n const regionDiscoveryFields: string[] = [];\r\n\r\n regionDiscoveryFields.push(this.regionUsed || Constants.EMPTY_STRING);\r\n regionDiscoveryFields.push(this.regionSource || Constants.EMPTY_STRING);\r\n regionDiscoveryFields.push(\r\n this.regionOutcome || Constants.EMPTY_STRING\r\n );\r\n\r\n return regionDiscoveryFields.join(\",\");\r\n }\r\n\r\n /**\r\n * Update the region discovery metadata\r\n *\r\n * @param regionDiscoveryMetadata\r\n * @returns void\r\n */\r\n updateRegionDiscoveryMetadata(\r\n regionDiscoveryMetadata: RegionDiscoveryMetadata\r\n ): void {\r\n this.regionUsed = regionDiscoveryMetadata.region_used;\r\n this.regionSource = regionDiscoveryMetadata.region_source;\r\n this.regionOutcome = regionDiscoveryMetadata.region_outcome;\r\n }\r\n\r\n /**\r\n * Set cache outcome\r\n */\r\n setCacheOutcome(cacheOutcome: CacheOutcome): void {\r\n this.cacheOutcome = cacheOutcome;\r\n }\r\n\r\n setNativeBrokerErrorCode(errorCode: string): void {\r\n const lastRequests = this.getLastRequests();\r\n lastRequests.nativeBrokerErrorCode = errorCode;\r\n this.cacheManager.setServerTelemetry(\r\n this.telemetryCacheKey,\r\n lastRequests,\r\n this.correlationId\r\n );\r\n }\r\n\r\n getNativeBrokerErrorCode(): string | undefined {\r\n return this.getLastRequests().nativeBrokerErrorCode;\r\n }\r\n\r\n clearNativeBrokerErrorCode(): void {\r\n const lastRequests = this.getLastRequests();\r\n delete lastRequests.nativeBrokerErrorCode;\r\n this.cacheManager.setServerTelemetry(\r\n this.telemetryCacheKey,\r\n lastRequests,\r\n this.correlationId\r\n );\r\n }\r\n\r\n static makeExtraSkuString(params: SkuParams): string {\r\n return makeExtraSkuString(params);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport const missingKidError = \"missing_kid_error\";\r\nexport const missingAlgError = \"missing_alg_error\";\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthError } from \"./AuthError.js\";\r\nimport * as JoseHeaderErrorCodes from \"./JoseHeaderErrorCodes.js\";\r\nexport { JoseHeaderErrorCodes };\r\n\r\nexport const JoseHeaderErrorMessages = {\r\n [JoseHeaderErrorCodes.missingKidError]:\r\n \"The JOSE Header for the requested JWT, JWS or JWK object requires a keyId to be configured as the 'kid' header claim. No 'kid' value was provided.\",\r\n [JoseHeaderErrorCodes.missingAlgError]:\r\n \"The JOSE Header for the requested JWT, JWS or JWK object requires an algorithm to be specified as the 'alg' header claim. No 'alg' value was provided.\",\r\n};\r\n\r\n/**\r\n * Error thrown when there is an error in the client code running on the browser.\r\n */\r\nexport class JoseHeaderError extends AuthError {\r\n constructor(errorCode: string, errorMessage?: string) {\r\n super(errorCode, errorMessage);\r\n this.name = \"JoseHeaderError\";\r\n\r\n Object.setPrototypeOf(this, JoseHeaderError.prototype);\r\n }\r\n}\r\n\r\n/** Returns JoseHeaderError object */\r\nexport function createJoseHeaderError(code: string): JoseHeaderError {\r\n return new JoseHeaderError(code, JoseHeaderErrorMessages[code]);\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n JoseHeaderErrorCodes,\r\n createJoseHeaderError,\r\n} from \"../error/JoseHeaderError.js\";\r\nimport { JsonWebTokenTypes } from \"../utils/Constants.js\";\r\n\r\nexport type JoseHeaderOptions = {\r\n typ?: JsonWebTokenTypes;\r\n alg?: string;\r\n kid?: string;\r\n};\r\n\r\n/** @internal */\r\nexport class JoseHeader {\r\n public typ?: JsonWebTokenTypes;\r\n public alg?: string;\r\n public kid?: string;\r\n\r\n constructor(options: JoseHeaderOptions) {\r\n this.typ = options.typ;\r\n this.alg = options.alg;\r\n this.kid = options.kid;\r\n }\r\n\r\n /**\r\n * Builds SignedHttpRequest formatted JOSE Header from the\r\n * JOSE Header options provided or previously set on the object and returns\r\n * the stringified header object.\r\n * Throws if keyId or algorithm aren't provided since they are required for Access Token Binding.\r\n * @param shrHeaderOptions\r\n * @returns\r\n */\r\n static getShrHeaderString(shrHeaderOptions: JoseHeaderOptions): string {\r\n // KeyID is required on the SHR header\r\n if (!shrHeaderOptions.kid) {\r\n throw createJoseHeaderError(JoseHeaderErrorCodes.missingKidError);\r\n }\r\n\r\n // Alg is required on the SHR header\r\n if (!shrHeaderOptions.alg) {\r\n throw createJoseHeaderError(JoseHeaderErrorCodes.missingAlgError);\r\n }\r\n\r\n const shrHeader = new JoseHeader({\r\n // Access Token PoP headers must have type pop, but the type header can be overriden for special cases\r\n typ: shrHeaderOptions.typ || JsonWebTokenTypes.Pop,\r\n kid: shrHeaderOptions.kid,\r\n alg: shrHeaderOptions.alg,\r\n });\r\n\r\n return JSON.stringify(shrHeader);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { ApplicationTelemetry } from \"../../config/ClientConfiguration.js\";\r\nimport { Logger } from \"../../logger/Logger.js\";\r\nimport {\r\n InProgressPerformanceEvent,\r\n IPerformanceClient,\r\n PerformanceCallbackFunction,\r\n QueueMeasurement,\r\n} from \"./IPerformanceClient.js\";\r\nimport {\r\n IntFields,\r\n PerformanceEvent,\r\n PerformanceEventAbbreviations,\r\n PerformanceEventContext,\r\n PerformanceEvents,\r\n PerformanceEventStackedContext,\r\n PerformanceEventStatus,\r\n} from \"./PerformanceEvent.js\";\r\nimport { IPerformanceMeasurement } from \"./IPerformanceMeasurement.js\";\r\nimport { StubPerformanceMeasurement } from \"./StubPerformanceClient.js\";\r\nimport { AuthError } from \"../../error/AuthError.js\";\r\nimport { CacheError } from \"../../error/CacheError.js\";\r\nimport { ServerError } from \"../../error/ServerError.js\";\r\nimport { InteractionRequiredAuthError } from \"../../error/InteractionRequiredAuthError.js\";\r\n\r\nexport interface PreQueueEvent {\r\n name: PerformanceEvents;\r\n time: number;\r\n}\r\n\r\n/**\r\n * Starts context by adding payload to the stack\r\n * @param event {PerformanceEvent}\r\n * @param abbreviations {Map} event name abbreviations\r\n * @param stack {?PerformanceEventStackedContext[]} stack\r\n */\r\nexport function startContext(\r\n event: PerformanceEvent,\r\n abbreviations: Map,\r\n stack?: PerformanceEventStackedContext[]\r\n): void {\r\n if (!stack) {\r\n return;\r\n }\r\n\r\n stack.push({\r\n name: abbreviations.get(event.name) || event.name,\r\n });\r\n}\r\n\r\n/**\r\n * Ends context by removing payload from the stack and returning parent or self, if stack is empty, payload\r\n *\r\n * @param event {PerformanceEvent}\r\n * @param abbreviations {Map} event name abbreviations\r\n * @param stack {?PerformanceEventStackedContext[]} stack\r\n * @param error {?unknown} error\r\n */\r\nexport function endContext(\r\n event: PerformanceEvent,\r\n abbreviations: Map,\r\n stack?: PerformanceEventStackedContext[],\r\n error?: unknown\r\n): PerformanceEventContext | undefined {\r\n if (!stack?.length) {\r\n return;\r\n }\r\n\r\n const peek = (stack: PerformanceEventStackedContext[]) => {\r\n return stack.length ? stack[stack.length - 1] : undefined;\r\n };\r\n\r\n const abbrEventName = abbreviations.get(event.name) || event.name;\r\n const top = peek(stack);\r\n if (top?.name !== abbrEventName) {\r\n return;\r\n }\r\n\r\n const current = stack?.pop();\r\n if (!current) {\r\n return;\r\n }\r\n\r\n const errorCode =\r\n error instanceof AuthError\r\n ? error.errorCode\r\n : error instanceof Error\r\n ? error.name\r\n : undefined;\r\n const subErr = error instanceof AuthError ? error.subError : undefined;\r\n\r\n if (errorCode && current.childErr !== errorCode) {\r\n current.err = errorCode;\r\n if (subErr) {\r\n current.subErr = subErr;\r\n }\r\n }\r\n\r\n delete current.name;\r\n delete current.childErr;\r\n\r\n const context: PerformanceEventContext = {\r\n ...current,\r\n dur: event.durationMs,\r\n };\r\n\r\n if (!event.success) {\r\n context.fail = 1;\r\n }\r\n\r\n const parent = peek(stack);\r\n if (!parent) {\r\n return { [abbrEventName]: context };\r\n }\r\n\r\n if (errorCode) {\r\n parent.childErr = errorCode;\r\n }\r\n\r\n let childName: string;\r\n if (!parent[abbrEventName]) {\r\n childName = abbrEventName;\r\n } else {\r\n const siblings = Object.keys(parent).filter((key) =>\r\n key.startsWith(abbrEventName)\r\n ).length;\r\n childName = `${abbrEventName}_${siblings + 1}`;\r\n }\r\n parent[childName] = context;\r\n return parent;\r\n}\r\n\r\n/**\r\n * Adds error name and stack trace to the telemetry event\r\n * @param error {Error}\r\n * @param logger {Logger}\r\n * @param event {PerformanceEvent}\r\n * @param stackMaxSize {number} max error stack size to capture\r\n */\r\nexport function addError(\r\n error: unknown,\r\n logger: Logger,\r\n event: PerformanceEvent,\r\n stackMaxSize: number = 5\r\n): void {\r\n if (!(error instanceof Error)) {\r\n logger.trace(\r\n \"PerformanceClient.addErrorStack: Input error is not instance of Error\",\r\n event.correlationId\r\n );\r\n return;\r\n } else if (error instanceof AuthError) {\r\n event.errorCode = error.errorCode;\r\n event.subErrorCode = error.subError;\r\n if (\r\n error instanceof ServerError ||\r\n error instanceof InteractionRequiredAuthError\r\n ) {\r\n event.serverErrorNo = error.errorNo;\r\n }\r\n return;\r\n } else if (error instanceof CacheError) {\r\n event.errorCode = error.errorCode;\r\n return;\r\n } else if (event.errorStack?.length) {\r\n logger.trace(\r\n \"PerformanceClient.addErrorStack: Stack already exist\",\r\n event.correlationId\r\n );\r\n return;\r\n } else if (!error.stack?.length) {\r\n logger.trace(\r\n \"PerformanceClient.addErrorStack: Input stack is empty\",\r\n event.correlationId\r\n );\r\n return;\r\n }\r\n\r\n if (error.stack) {\r\n event.errorStack = compactStack(error.stack, stackMaxSize);\r\n }\r\n event.errorName = error.name;\r\n}\r\n\r\n/**\r\n * Compacts error stack into array by fetching N first entries\r\n * @param stack {string} error stack\r\n * @param stackMaxSize {number} max error stack size to capture\r\n * @returns {string[]}\r\n */\r\nexport function compactStack(stack: string, stackMaxSize: number): string[] {\r\n if (stackMaxSize < 0) {\r\n return [];\r\n }\r\n\r\n const stackArr = stack.split(\"\\n\") || [];\r\n\r\n const res = [];\r\n\r\n // Check for a handful of known, common runtime errors and log them (with redaction where applicable).\r\n const firstLine = stackArr[0];\r\n if (\r\n firstLine.startsWith(\"TypeError: Cannot read property\") ||\r\n firstLine.startsWith(\"TypeError: Cannot read properties of\") ||\r\n firstLine.startsWith(\"TypeError: Cannot set property\") ||\r\n firstLine.startsWith(\"TypeError: Cannot set properties of\") ||\r\n firstLine.endsWith(\"is not a function\")\r\n ) {\r\n // These types of errors are not at risk of leaking PII. They will indicate unavailable APIs\r\n res.push(compactStackLine(firstLine));\r\n } else if (\r\n firstLine.startsWith(\"SyntaxError\") ||\r\n firstLine.startsWith(\"TypeError\")\r\n ) {\r\n // Prevent unintentional leaking of arbitrary info by redacting contents between both single and double quotes\r\n res.push(\r\n compactStackLine(\r\n // Example: SyntaxError: Unexpected token 'e', \"test\" is not valid JSON -> SyntaxError: Unexpected token , is not valid JSON\r\n firstLine.replace(/['].*[']|[\"].*[\"]/g, \"\")\r\n )\r\n );\r\n }\r\n\r\n // Get top N stack lines\r\n for (let ix = 1; ix < stackArr.length; ix++) {\r\n if (res.length >= stackMaxSize) {\r\n break;\r\n }\r\n const line = stackArr[ix];\r\n res.push(compactStackLine(line));\r\n }\r\n return res;\r\n}\r\n\r\n/**\r\n * Compacts error stack line by shortening file path\r\n * Example: https://localhost/msal-common/src/authority/Authority.js:100:1 -> Authority.js:100:1\r\n * @param line {string} stack line\r\n * @returns {string}\r\n */\r\nexport function compactStackLine(line: string): string {\r\n const filePathIx = line.lastIndexOf(\" \") + 1;\r\n if (filePathIx < 1) {\r\n return line;\r\n }\r\n const filePath = line.substring(filePathIx);\r\n\r\n let fileNameIx = filePath.lastIndexOf(\"/\");\r\n fileNameIx = fileNameIx < 0 ? filePath.lastIndexOf(\"\\\\\") : fileNameIx;\r\n\r\n if (fileNameIx >= 0) {\r\n return (\r\n line.substring(0, filePathIx) +\r\n \"(\" +\r\n filePath.substring(fileNameIx + 1) +\r\n (filePath.charAt(filePath.length - 1) === \")\" ? \"\" : \")\")\r\n ).trimStart();\r\n }\r\n\r\n return line.trimStart();\r\n}\r\n\r\nexport abstract class PerformanceClient implements IPerformanceClient {\r\n protected authority: string;\r\n protected libraryName: string;\r\n protected libraryVersion: string;\r\n protected applicationTelemetry: ApplicationTelemetry;\r\n protected clientId: string;\r\n protected logger: Logger;\r\n protected callbacks: Map;\r\n\r\n /**\r\n * Multiple events with the same correlation id.\r\n * @protected\r\n * @type {Map}\r\n */\r\n protected eventsByCorrelationId: Map;\r\n\r\n /**\r\n * Map of pre-queue times by correlation Id\r\n *\r\n * @protected\r\n * @type {Map}\r\n */\r\n protected preQueueTimeByCorrelationId: Map;\r\n\r\n /**\r\n * Map of queue measurements by correlation Id\r\n *\r\n * @protected\r\n * @type {Map>}\r\n */\r\n protected queueMeasurements: Map>;\r\n\r\n protected intFields: Set;\r\n\r\n /**\r\n * Map of stacked events by correlation id.\r\n *\r\n * @protected\r\n */\r\n protected eventStack: Map;\r\n\r\n /**\r\n * Event name abbreviations\r\n *\r\n * @protected\r\n */\r\n protected abbreviations: Map;\r\n\r\n /**\r\n * Creates an instance of PerformanceClient,\r\n * an abstract class containing core performance telemetry logic.\r\n *\r\n * @constructor\r\n * @param {string} clientId Client ID of the application\r\n * @param {string} authority Authority used by the application\r\n * @param {Logger} logger Logger used by the application\r\n * @param {string} libraryName Name of the library\r\n * @param {string} libraryVersion Version of the library\r\n * @param {ApplicationTelemetry} applicationTelemetry application name and version\r\n * @param {Set} intFields integer fields to be truncated\r\n * @param {Map} abbreviations event name abbreviations\r\n */\r\n constructor(\r\n clientId: string,\r\n authority: string,\r\n logger: Logger,\r\n libraryName: string,\r\n libraryVersion: string,\r\n applicationTelemetry: ApplicationTelemetry,\r\n intFields?: Set,\r\n abbreviations?: Map\r\n ) {\r\n this.authority = authority;\r\n this.libraryName = libraryName;\r\n this.libraryVersion = libraryVersion;\r\n this.applicationTelemetry = applicationTelemetry;\r\n this.clientId = clientId;\r\n this.logger = logger;\r\n this.callbacks = new Map();\r\n this.eventsByCorrelationId = new Map();\r\n this.eventStack = new Map();\r\n this.queueMeasurements = new Map();\r\n this.preQueueTimeByCorrelationId = new Map();\r\n this.intFields = intFields || new Set();\r\n for (const item of IntFields) {\r\n this.intFields.add(item);\r\n }\r\n this.abbreviations = abbreviations || new Map();\r\n for (const [key, value] of PerformanceEventAbbreviations) {\r\n this.abbreviations.set(key, value);\r\n }\r\n }\r\n\r\n /**\r\n * Generates and returns a unique id, typically a guid.\r\n *\r\n * @abstract\r\n * @returns {string}\r\n */\r\n abstract generateId(): string;\r\n\r\n /**\r\n * Starts and returns an platform-specific implementation of IPerformanceMeasurement.\r\n * Note: this function can be changed to abstract at the next major version bump.\r\n *\r\n * @param {string} measureName\r\n * @param {string} correlationId\r\n * @returns {IPerformanceMeasurement}\r\n * @deprecated This method will be removed in the next major version\r\n */\r\n startPerformanceMeasurement(\r\n measureName: string, // eslint-disable-line @typescript-eslint/no-unused-vars\r\n correlationId: string // eslint-disable-line @typescript-eslint/no-unused-vars\r\n ): IPerformanceMeasurement {\r\n return {} as IPerformanceMeasurement;\r\n }\r\n\r\n /**\r\n * Sets pre-queue time by correlation Id\r\n *\r\n * @abstract\r\n * @param {PerformanceEvents} eventName\r\n * @param {string} correlationId\r\n * @returns\r\n */\r\n abstract setPreQueueTime(\r\n eventName: PerformanceEvents,\r\n correlationId?: string\r\n ): void;\r\n\r\n /**\r\n * Gets map of pre-queue times by correlation Id\r\n *\r\n * @param {PerformanceEvents} eventName\r\n * @param {string} correlationId\r\n * @returns {number}\r\n */\r\n getPreQueueTime(eventName: string, correlationId: string): number | void {\r\n const preQueueEvent: PreQueueEvent | undefined =\r\n this.preQueueTimeByCorrelationId.get(correlationId);\r\n\r\n if (!preQueueEvent) {\r\n this.logger.trace(\r\n `PerformanceClient.getPreQueueTime: no pre-queue times found for correlationId: ${correlationId}, unable to add queue measurement`\r\n );\r\n return;\r\n } else if (preQueueEvent.name !== eventName) {\r\n this.logger.trace(\r\n `PerformanceClient.getPreQueueTime: no pre-queue time found for ${eventName}, unable to add queue measurement`\r\n );\r\n return;\r\n }\r\n\r\n return preQueueEvent.time;\r\n }\r\n\r\n /**\r\n * Calculates the difference between current time and time when function was queued.\r\n * Note: It is possible to have 0 as the queue time if the current time and the queued time was the same.\r\n *\r\n * @param {number} preQueueTime\r\n * @param {number} currentTime\r\n * @returns {number}\r\n */\r\n calculateQueuedTime(preQueueTime: number, currentTime: number): number {\r\n if (preQueueTime < 1) {\r\n this.logger.trace(\r\n `PerformanceClient: preQueueTime should be a positive integer and not ${preQueueTime}`\r\n );\r\n return 0;\r\n }\r\n\r\n if (currentTime < 1) {\r\n this.logger.trace(\r\n `PerformanceClient: currentTime should be a positive integer and not ${currentTime}`\r\n );\r\n return 0;\r\n }\r\n\r\n if (currentTime < preQueueTime) {\r\n this.logger.trace(\r\n \"PerformanceClient: currentTime is less than preQueueTime, check how time is being retrieved\"\r\n );\r\n return 0;\r\n }\r\n\r\n return currentTime - preQueueTime;\r\n }\r\n\r\n /**\r\n * Adds queue measurement time to QueueMeasurements array for given correlation ID.\r\n *\r\n * @param {PerformanceEvents} eventName\r\n * @param {?string} correlationId\r\n * @param {?number} queueTime\r\n * @param {?boolean} manuallyCompleted - indicator for manually completed queue measurements\r\n * @returns\r\n */\r\n addQueueMeasurement(\r\n eventName: string,\r\n correlationId?: string,\r\n queueTime?: number,\r\n manuallyCompleted?: boolean\r\n ): void {\r\n if (!correlationId) {\r\n this.logger.trace(\r\n `PerformanceClient.addQueueMeasurement: correlationId not provided for ${eventName}, cannot add queue measurement`\r\n );\r\n return;\r\n }\r\n\r\n if (queueTime === 0) {\r\n // Possible for there to be no queue time after calculation\r\n this.logger.trace(\r\n `PerformanceClient.addQueueMeasurement: queue time provided for ${eventName} is ${queueTime}`\r\n );\r\n } else if (!queueTime) {\r\n this.logger.trace(\r\n `PerformanceClient.addQueueMeasurement: no queue time provided for ${eventName}`\r\n );\r\n return;\r\n }\r\n\r\n const queueMeasurement: QueueMeasurement = {\r\n eventName,\r\n // Always default queue time to 0 for manually completed (improperly instrumented)\r\n queueTime: manuallyCompleted ? 0 : queueTime,\r\n manuallyCompleted,\r\n };\r\n\r\n // Adds to existing correlation Id if present in queueMeasurements\r\n const existingMeasurements = this.queueMeasurements.get(correlationId);\r\n if (existingMeasurements) {\r\n existingMeasurements.push(queueMeasurement);\r\n this.queueMeasurements.set(correlationId, existingMeasurements);\r\n } else {\r\n // Sets new correlation Id if not present in queueMeasurements\r\n this.logger.trace(\r\n `PerformanceClient.addQueueMeasurement: adding correlationId ${correlationId} to queue measurements`\r\n );\r\n const measurementArray = [queueMeasurement];\r\n this.queueMeasurements.set(correlationId, measurementArray);\r\n }\r\n // Delete processed pre-queue event.\r\n this.preQueueTimeByCorrelationId.delete(correlationId);\r\n }\r\n\r\n /**\r\n * Starts measuring performance for a given operation. Returns a function that should be used to end the measurement.\r\n *\r\n * @param {PerformanceEvents} measureName\r\n * @param {?string} [correlationId]\r\n * @returns {InProgressPerformanceEvent}\r\n */\r\n startMeasurement(\r\n measureName: string,\r\n correlationId?: string\r\n ): InProgressPerformanceEvent {\r\n // Generate a placeholder correlation if the request does not provide one\r\n const eventCorrelationId = correlationId || this.generateId();\r\n if (!correlationId) {\r\n this.logger.info(\r\n `PerformanceClient: No correlation id provided for ${measureName}, generating`,\r\n eventCorrelationId\r\n );\r\n }\r\n\r\n this.logger.trace(\r\n `PerformanceClient: Performance measurement started for ${measureName}`,\r\n eventCorrelationId\r\n );\r\n\r\n const inProgressEvent: PerformanceEvent = {\r\n eventId: this.generateId(),\r\n status: PerformanceEventStatus.InProgress,\r\n authority: this.authority,\r\n libraryName: this.libraryName,\r\n libraryVersion: this.libraryVersion,\r\n clientId: this.clientId,\r\n name: measureName,\r\n startTimeMs: Date.now(),\r\n correlationId: eventCorrelationId,\r\n appName: this.applicationTelemetry?.appName,\r\n appVersion: this.applicationTelemetry?.appVersion,\r\n };\r\n\r\n // Store in progress events so they can be discarded if not ended properly\r\n this.cacheEventByCorrelationId(inProgressEvent);\r\n startContext(\r\n inProgressEvent,\r\n this.abbreviations,\r\n this.eventStack.get(eventCorrelationId)\r\n );\r\n\r\n // Return the event and functions the caller can use to properly end/flush the measurement\r\n return {\r\n end: (\r\n event?: Partial,\r\n error?: unknown\r\n ): PerformanceEvent | null => {\r\n return this.endMeasurement(\r\n {\r\n // Initial set of event properties\r\n ...inProgressEvent,\r\n // Properties set when event ends\r\n ...event,\r\n },\r\n error\r\n );\r\n },\r\n discard: () => {\r\n return this.discardMeasurements(inProgressEvent.correlationId);\r\n },\r\n add: (fields: { [key: string]: {} | undefined }) => {\r\n return this.addFields(fields, inProgressEvent.correlationId);\r\n },\r\n increment: (fields: { [key: string]: number | undefined }) => {\r\n return this.incrementFields(\r\n fields,\r\n inProgressEvent.correlationId\r\n );\r\n },\r\n event: inProgressEvent,\r\n measurement: new StubPerformanceMeasurement(),\r\n };\r\n }\r\n\r\n /**\r\n * Stops measuring the performance for an operation. Should only be called directly by PerformanceClient classes,\r\n * as consumers should instead use the function returned by startMeasurement.\r\n * Adds a new field named as \"[event name]DurationMs\" for sub-measurements, completes and emits an event\r\n * otherwise.\r\n *\r\n * @param {PerformanceEvent} event\r\n * @param {unknown} error\r\n * @returns {(PerformanceEvent | null)}\r\n */\r\n endMeasurement(\r\n event: PerformanceEvent,\r\n error?: unknown\r\n ): PerformanceEvent | null {\r\n const rootEvent: PerformanceEvent | undefined =\r\n this.eventsByCorrelationId.get(event.correlationId);\r\n if (!rootEvent) {\r\n this.logger.trace(\r\n `PerformanceClient: Measurement not found for ${event.eventId}`,\r\n event.correlationId\r\n );\r\n return null;\r\n }\r\n\r\n const isRoot = event.eventId === rootEvent.eventId;\r\n let queueInfo = {\r\n totalQueueTime: 0,\r\n totalQueueCount: 0,\r\n manuallyCompletedCount: 0,\r\n };\r\n\r\n event.durationMs = Math.round(\r\n event.durationMs || this.getDurationMs(event.startTimeMs)\r\n );\r\n\r\n const context = JSON.stringify(\r\n endContext(\r\n event,\r\n this.abbreviations,\r\n this.eventStack.get(rootEvent.correlationId),\r\n error\r\n )\r\n );\r\n\r\n if (isRoot) {\r\n queueInfo = this.getQueueInfo(event.correlationId);\r\n this.discardMeasurements(rootEvent.correlationId);\r\n } else {\r\n rootEvent.incompleteSubMeasurements?.delete(event.eventId);\r\n }\r\n\r\n this.logger.trace(\r\n `PerformanceClient: Performance measurement ended for ${event.name}: ${event.durationMs} ms`,\r\n event.correlationId\r\n );\r\n\r\n if (error) {\r\n addError(error, this.logger, rootEvent);\r\n }\r\n\r\n // Add sub-measurement attribute to root event.\r\n if (!isRoot) {\r\n rootEvent[event.name + \"DurationMs\"] = Math.floor(event.durationMs);\r\n return { ...rootEvent };\r\n }\r\n\r\n if (\r\n isRoot &&\r\n !error &&\r\n (rootEvent.errorCode || rootEvent.subErrorCode)\r\n ) {\r\n this.logger.trace(\r\n `PerformanceClient: Remove error and sub-error codes for root event ${event.name} as intermediate error was successfully handled`,\r\n event.correlationId\r\n );\r\n rootEvent.errorCode = undefined;\r\n rootEvent.subErrorCode = undefined;\r\n }\r\n\r\n let finalEvent: PerformanceEvent = { ...rootEvent, ...event };\r\n let incompleteSubsCount: number = 0;\r\n // Incomplete sub-measurements are discarded. They are likely an instrumentation bug that should be fixed.\r\n finalEvent.incompleteSubMeasurements?.forEach((subMeasurement) => {\r\n this.logger.trace(\r\n `PerformanceClient: Incomplete submeasurement ${subMeasurement.name} found for ${event.name}`,\r\n finalEvent.correlationId\r\n );\r\n incompleteSubsCount++;\r\n });\r\n finalEvent.incompleteSubMeasurements = undefined;\r\n\r\n finalEvent = {\r\n ...finalEvent,\r\n queuedTimeMs: queueInfo.totalQueueTime,\r\n queuedCount: queueInfo.totalQueueCount,\r\n queuedManuallyCompletedCount: queueInfo.manuallyCompletedCount,\r\n status: PerformanceEventStatus.Completed,\r\n incompleteSubsCount,\r\n context,\r\n };\r\n this.truncateIntegralFields(finalEvent);\r\n this.emitEvents([finalEvent], event.correlationId);\r\n\r\n return finalEvent;\r\n }\r\n\r\n /**\r\n * Saves extra information to be emitted when the measurements are flushed\r\n * @param fields\r\n * @param correlationId\r\n */\r\n addFields(\r\n fields: { [key: string]: {} | undefined },\r\n correlationId: string\r\n ): void {\r\n this.logger.trace(\"PerformanceClient: Updating static fields\");\r\n const event = this.eventsByCorrelationId.get(correlationId);\r\n if (event) {\r\n this.eventsByCorrelationId.set(correlationId, {\r\n ...event,\r\n ...fields,\r\n });\r\n } else {\r\n this.logger.trace(\r\n \"PerformanceClient: Event not found for\",\r\n correlationId\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Increment counters to be emitted when the measurements are flushed\r\n * @param fields {string[]}\r\n * @param correlationId {string} correlation identifier\r\n */\r\n incrementFields(\r\n fields: { [key: string]: number | undefined },\r\n correlationId: string\r\n ): void {\r\n this.logger.trace(\"PerformanceClient: Updating counters\");\r\n const event = this.eventsByCorrelationId.get(correlationId);\r\n if (event) {\r\n for (const counter in fields) {\r\n if (!event.hasOwnProperty(counter)) {\r\n event[counter] = 0;\r\n } else if (isNaN(Number(event[counter]))) {\r\n return;\r\n }\r\n event[counter] += fields[counter];\r\n }\r\n } else {\r\n this.logger.trace(\r\n \"PerformanceClient: Event not found for\",\r\n correlationId\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Upserts event into event cache.\r\n * First key is the correlation id, second key is the event id.\r\n * Allows for events to be grouped by correlation id,\r\n * and to easily allow for properties on them to be updated.\r\n *\r\n * @private\r\n * @param {PerformanceEvent} event\r\n */\r\n protected cacheEventByCorrelationId(event: PerformanceEvent): void {\r\n const rootEvent = this.eventsByCorrelationId.get(event.correlationId);\r\n if (rootEvent) {\r\n this.logger.trace(\r\n `PerformanceClient: Performance measurement for ${event.name} added/updated`,\r\n event.correlationId\r\n );\r\n rootEvent.incompleteSubMeasurements =\r\n rootEvent.incompleteSubMeasurements || new Map();\r\n rootEvent.incompleteSubMeasurements.set(event.eventId, {\r\n name: event.name,\r\n startTimeMs: event.startTimeMs,\r\n });\r\n } else {\r\n this.logger.trace(\r\n `PerformanceClient: Performance measurement for ${event.name} started`,\r\n event.correlationId\r\n );\r\n this.eventsByCorrelationId.set(event.correlationId, { ...event });\r\n this.eventStack.set(event.correlationId, []);\r\n }\r\n }\r\n\r\n private getQueueInfo(correlationId: string): {\r\n totalQueueTime: number;\r\n totalQueueCount: number;\r\n manuallyCompletedCount: number;\r\n } {\r\n const queueMeasurementForCorrelationId =\r\n this.queueMeasurements.get(correlationId);\r\n if (!queueMeasurementForCorrelationId) {\r\n this.logger.trace(\r\n `PerformanceClient: no queue measurements found for for correlationId: ${correlationId}`\r\n );\r\n }\r\n\r\n let totalQueueTime = 0;\r\n let totalQueueCount = 0;\r\n let manuallyCompletedCount = 0;\r\n queueMeasurementForCorrelationId?.forEach((measurement) => {\r\n totalQueueTime += measurement.queueTime;\r\n totalQueueCount++;\r\n manuallyCompletedCount += measurement.manuallyCompleted ? 1 : 0;\r\n });\r\n\r\n return {\r\n totalQueueTime,\r\n totalQueueCount,\r\n manuallyCompletedCount,\r\n };\r\n }\r\n\r\n /**\r\n * Removes measurements and aux data for a given correlation id.\r\n *\r\n * @param {string} correlationId\r\n */\r\n discardMeasurements(correlationId: string): void {\r\n this.logger.trace(\r\n \"PerformanceClient: Performance measurements discarded\",\r\n correlationId\r\n );\r\n this.eventsByCorrelationId.delete(correlationId);\r\n\r\n this.logger.trace(\r\n \"PerformanceClient: QueueMeasurements discarded\",\r\n correlationId\r\n );\r\n this.queueMeasurements.delete(correlationId);\r\n\r\n this.logger.trace(\r\n \"PerformanceClient: Pre-queue times discarded\",\r\n correlationId\r\n );\r\n this.preQueueTimeByCorrelationId.delete(correlationId);\r\n\r\n this.logger.trace(\r\n \"PerformanceClient: Event stack discarded\",\r\n correlationId\r\n );\r\n this.eventStack.delete(correlationId);\r\n }\r\n\r\n /**\r\n * Registers a callback function to receive performance events.\r\n *\r\n * @param {PerformanceCallbackFunction} callback\r\n * @returns {string}\r\n */\r\n addPerformanceCallback(callback: PerformanceCallbackFunction): string {\r\n for (const [id, cb] of this.callbacks) {\r\n if (cb.toString() === callback.toString()) {\r\n this.logger.warning(\r\n `PerformanceClient: Performance callback is already registered with id: ${id}`\r\n );\r\n return id;\r\n }\r\n }\r\n\r\n const callbackId = this.generateId();\r\n this.callbacks.set(callbackId, callback);\r\n this.logger.verbose(\r\n `PerformanceClient: Performance callback registered with id: ${callbackId}`\r\n );\r\n\r\n return callbackId;\r\n }\r\n\r\n /**\r\n * Removes a callback registered with addPerformanceCallback.\r\n *\r\n * @param {string} callbackId\r\n * @returns {boolean}\r\n */\r\n removePerformanceCallback(callbackId: string): boolean {\r\n const result = this.callbacks.delete(callbackId);\r\n\r\n if (result) {\r\n this.logger.verbose(\r\n `PerformanceClient: Performance callback ${callbackId} removed.`\r\n );\r\n } else {\r\n this.logger.verbose(\r\n `PerformanceClient: Performance callback ${callbackId} not removed.`\r\n );\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Emits events to all registered callbacks.\r\n *\r\n * @param {PerformanceEvent[]} events\r\n * @param {?string} [correlationId]\r\n */\r\n emitEvents(events: PerformanceEvent[], correlationId: string): void {\r\n this.logger.verbose(\r\n \"PerformanceClient: Emitting performance events\",\r\n correlationId\r\n );\r\n\r\n this.callbacks.forEach(\r\n (callback: PerformanceCallbackFunction, callbackId: string) => {\r\n this.logger.trace(\r\n `PerformanceClient: Emitting event to callback ${callbackId}`,\r\n correlationId\r\n );\r\n callback.apply(null, [events]);\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Enforce truncation of integral fields in performance event.\r\n * @param {PerformanceEvent} event performance event to update.\r\n */\r\n private truncateIntegralFields(event: PerformanceEvent): void {\r\n this.intFields.forEach((key) => {\r\n if (key in event && typeof event[key] === \"number\") {\r\n event[key] = Math.floor(event[key]);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Returns event duration in milliseconds\r\n * @param startTimeMs {number}\r\n * @returns {number}\r\n */\r\n private getDurationMs(startTimeMs: number): number {\r\n const durationMs = Date.now() - startTimeMs;\r\n // Handle clock skew\r\n return durationMs < 0 ? durationMs : 0;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport const pkceNotCreated = \"pkce_not_created\";\r\nexport const earJwkEmpty = \"ear_jwk_empty\";\r\nexport const earJweEmpty = \"ear_jwe_empty\";\r\nexport const cryptoNonExistent = \"crypto_nonexistent\";\r\nexport const emptyNavigateUri = \"empty_navigate_uri\";\r\nexport const hashEmptyError = \"hash_empty_error\";\r\nexport const noStateInHash = \"no_state_in_hash\";\r\nexport const hashDoesNotContainKnownProperties =\r\n \"hash_does_not_contain_known_properties\";\r\nexport const unableToParseState = \"unable_to_parse_state\";\r\nexport const stateInteractionTypeMismatch = \"state_interaction_type_mismatch\";\r\nexport const interactionInProgress = \"interaction_in_progress\";\r\nexport const popupWindowError = \"popup_window_error\";\r\nexport const emptyWindowError = \"empty_window_error\";\r\nexport const userCancelled = \"user_cancelled\";\r\nexport const monitorPopupTimeout = \"monitor_popup_timeout\";\r\nexport const monitorWindowTimeout = \"monitor_window_timeout\";\r\nexport const redirectInIframe = \"redirect_in_iframe\";\r\nexport const blockIframeReload = \"block_iframe_reload\";\r\nexport const blockNestedPopups = \"block_nested_popups\";\r\nexport const iframeClosedPrematurely = \"iframe_closed_prematurely\";\r\nexport const silentLogoutUnsupported = \"silent_logout_unsupported\";\r\nexport const noAccountError = \"no_account_error\";\r\nexport const silentPromptValueError = \"silent_prompt_value_error\";\r\nexport const noTokenRequestCacheError = \"no_token_request_cache_error\";\r\nexport const unableToParseTokenRequestCacheError =\r\n \"unable_to_parse_token_request_cache_error\";\r\nexport const authRequestNotSetError = \"auth_request_not_set_error\";\r\nexport const invalidCacheType = \"invalid_cache_type\";\r\nexport const nonBrowserEnvironment = \"non_browser_environment\";\r\nexport const databaseNotOpen = \"database_not_open\";\r\nexport const noNetworkConnectivity = \"no_network_connectivity\";\r\nexport const postRequestFailed = \"post_request_failed\";\r\nexport const getRequestFailed = \"get_request_failed\";\r\nexport const failedToParseResponse = \"failed_to_parse_response\";\r\nexport const unableToLoadToken = \"unable_to_load_token\";\r\nexport const cryptoKeyNotFound = \"crypto_key_not_found\";\r\nexport const authCodeRequired = \"auth_code_required\";\r\nexport const authCodeOrNativeAccountIdRequired =\r\n \"auth_code_or_nativeAccountId_required\";\r\nexport const spaCodeAndNativeAccountIdPresent =\r\n \"spa_code_and_nativeAccountId_present\";\r\nexport const databaseUnavailable = \"database_unavailable\";\r\nexport const unableToAcquireTokenFromNativePlatform =\r\n \"unable_to_acquire_token_from_native_platform\";\r\nexport const nativeHandshakeTimeout = \"native_handshake_timeout\";\r\nexport const nativeExtensionNotInstalled = \"native_extension_not_installed\";\r\nexport const nativeConnectionNotEstablished =\r\n \"native_connection_not_established\";\r\nexport const uninitializedPublicClientApplication =\r\n \"uninitialized_public_client_application\";\r\nexport const nativePromptNotSupported = \"native_prompt_not_supported\";\r\nexport const invalidBase64String = \"invalid_base64_string\";\r\nexport const invalidPopTokenRequest = \"invalid_pop_token_request\";\r\nexport const failedToBuildHeaders = \"failed_to_build_headers\";\r\nexport const failedToParseHeaders = \"failed_to_parse_headers\";\r\nexport const failedToDecryptEarResponse = \"failed_to_decrypt_ear_response\";\r\nexport const timedOut = \"timed_out\";\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthError } from \"@azure/msal-common/browser\";\r\nimport * as BrowserAuthErrorCodes from \"./BrowserAuthErrorCodes.js\";\r\nexport { BrowserAuthErrorCodes }; // Allow importing as \"BrowserAuthErrorCodes\"\r\n\r\nconst ErrorLink = \"For more visit: aka.ms/msaljs/browser-errors\";\r\n\r\n/**\r\n * BrowserAuthErrorMessage class containing string constants used by error codes and messages.\r\n */\r\nexport const BrowserAuthErrorMessages = {\r\n [BrowserAuthErrorCodes.pkceNotCreated]:\r\n \"The PKCE code challenge and verifier could not be generated.\",\r\n [BrowserAuthErrorCodes.earJwkEmpty]:\r\n \"No EAR encryption key provided. This is unexpected.\",\r\n [BrowserAuthErrorCodes.earJweEmpty]:\r\n \"Server response does not contain ear_jwe property. This is unexpected.\",\r\n [BrowserAuthErrorCodes.cryptoNonExistent]:\r\n \"The crypto object or function is not available.\",\r\n [BrowserAuthErrorCodes.emptyNavigateUri]:\r\n \"Navigation URI is empty. Please check stack trace for more info.\",\r\n [BrowserAuthErrorCodes.hashEmptyError]: `Hash value cannot be processed because it is empty. Please verify that your redirectUri is not clearing the hash. ${ErrorLink}`,\r\n [BrowserAuthErrorCodes.noStateInHash]:\r\n \"Hash does not contain state. Please verify that the request originated from msal.\",\r\n [BrowserAuthErrorCodes.hashDoesNotContainKnownProperties]: `Hash does not contain known properites. Please verify that your redirectUri is not changing the hash. ${ErrorLink}`,\r\n [BrowserAuthErrorCodes.unableToParseState]:\r\n \"Unable to parse state. Please verify that the request originated from msal.\",\r\n [BrowserAuthErrorCodes.stateInteractionTypeMismatch]:\r\n \"Hash contains state but the interaction type does not match the caller.\",\r\n [BrowserAuthErrorCodes.interactionInProgress]: `Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API. ${ErrorLink}`,\r\n [BrowserAuthErrorCodes.popupWindowError]:\r\n \"Error opening popup window. This can happen if you are using IE or if popups are blocked in the browser.\",\r\n [BrowserAuthErrorCodes.emptyWindowError]:\r\n \"window.open returned null or undefined window object.\",\r\n [BrowserAuthErrorCodes.userCancelled]: \"User cancelled the flow.\",\r\n [BrowserAuthErrorCodes.monitorPopupTimeout]: `Token acquisition in popup failed due to timeout. ${ErrorLink}`,\r\n [BrowserAuthErrorCodes.monitorWindowTimeout]: `Token acquisition in iframe failed due to timeout. ${ErrorLink}`,\r\n [BrowserAuthErrorCodes.redirectInIframe]:\r\n \"Redirects are not supported for iframed or brokered applications. Please ensure you are using MSAL.js in a top frame of the window if using the redirect APIs, or use the popup APIs.\",\r\n [BrowserAuthErrorCodes.blockIframeReload]: `Request was blocked inside an iframe because MSAL detected an authentication response. ${ErrorLink}`,\r\n [BrowserAuthErrorCodes.blockNestedPopups]:\r\n \"Request was blocked inside a popup because MSAL detected it was running in a popup.\",\r\n [BrowserAuthErrorCodes.iframeClosedPrematurely]:\r\n \"The iframe being monitored was closed prematurely.\",\r\n [BrowserAuthErrorCodes.silentLogoutUnsupported]:\r\n \"Silent logout not supported. Please call logoutRedirect or logoutPopup instead.\",\r\n [BrowserAuthErrorCodes.noAccountError]:\r\n \"No account object provided to acquireTokenSilent and no active account has been set. Please call setActiveAccount or provide an account on the request.\",\r\n [BrowserAuthErrorCodes.silentPromptValueError]:\r\n \"The value given for the prompt value is not valid for silent requests - must be set to 'none' or 'no_session'.\",\r\n [BrowserAuthErrorCodes.noTokenRequestCacheError]:\r\n \"No token request found in cache.\",\r\n [BrowserAuthErrorCodes.unableToParseTokenRequestCacheError]:\r\n \"The cached token request could not be parsed.\",\r\n [BrowserAuthErrorCodes.authRequestNotSetError]:\r\n \"Auth Request not set. Please ensure initiateAuthRequest was called from the InteractionHandler\",\r\n [BrowserAuthErrorCodes.invalidCacheType]: \"Invalid cache type\",\r\n [BrowserAuthErrorCodes.nonBrowserEnvironment]:\r\n \"Login and token requests are not supported in non-browser environments.\",\r\n [BrowserAuthErrorCodes.databaseNotOpen]: \"Database is not open!\",\r\n [BrowserAuthErrorCodes.noNetworkConnectivity]:\r\n \"No network connectivity. Check your internet connection.\",\r\n [BrowserAuthErrorCodes.postRequestFailed]:\r\n \"Network request failed: If the browser threw a CORS error, check that the redirectUri is registered in the Azure App Portal as type 'SPA'\",\r\n [BrowserAuthErrorCodes.getRequestFailed]:\r\n \"Network request failed. Please check the network trace to determine root cause.\",\r\n [BrowserAuthErrorCodes.failedToParseResponse]:\r\n \"Failed to parse network response. Check network trace.\",\r\n [BrowserAuthErrorCodes.unableToLoadToken]: \"Error loading token to cache.\",\r\n [BrowserAuthErrorCodes.cryptoKeyNotFound]:\r\n \"Cryptographic Key or Keypair not found in browser storage.\",\r\n [BrowserAuthErrorCodes.authCodeRequired]:\r\n \"An authorization code must be provided (as the `code` property on the request) to this flow.\",\r\n [BrowserAuthErrorCodes.authCodeOrNativeAccountIdRequired]:\r\n \"An authorization code or nativeAccountId must be provided to this flow.\",\r\n [BrowserAuthErrorCodes.spaCodeAndNativeAccountIdPresent]:\r\n \"Request cannot contain both spa code and native account id.\",\r\n [BrowserAuthErrorCodes.databaseUnavailable]:\r\n \"IndexedDB, which is required for persistent cryptographic key storage, is unavailable. This may be caused by browser privacy features which block persistent storage in third-party contexts.\",\r\n [BrowserAuthErrorCodes.unableToAcquireTokenFromNativePlatform]: `Unable to acquire token from native platform. ${ErrorLink}`,\r\n [BrowserAuthErrorCodes.nativeHandshakeTimeout]:\r\n \"Timed out while attempting to establish connection to browser extension\",\r\n [BrowserAuthErrorCodes.nativeExtensionNotInstalled]:\r\n \"Native extension is not installed. If you think this is a mistake call the initialize function.\",\r\n [BrowserAuthErrorCodes.nativeConnectionNotEstablished]: `Connection to native platform has not been established. Please install a compatible browser extension and run initialize(). ${ErrorLink}`,\r\n [BrowserAuthErrorCodes.uninitializedPublicClientApplication]: `You must call and await the initialize function before attempting to call any other MSAL API. ${ErrorLink}`,\r\n [BrowserAuthErrorCodes.nativePromptNotSupported]:\r\n \"The provided prompt is not supported by the native platform. This request should be routed to the web based flow.\",\r\n [BrowserAuthErrorCodes.invalidBase64String]:\r\n \"Invalid base64 encoded string.\",\r\n [BrowserAuthErrorCodes.invalidPopTokenRequest]:\r\n \"Invalid PoP token request. The request should not have both a popKid value and signPopToken set to true.\",\r\n [BrowserAuthErrorCodes.failedToBuildHeaders]:\r\n \"Failed to build request headers object.\",\r\n [BrowserAuthErrorCodes.failedToParseHeaders]:\r\n \"Failed to parse response headers\",\r\n [BrowserAuthErrorCodes.failedToDecryptEarResponse]:\r\n \"Failed to decrypt ear response\",\r\n [BrowserAuthErrorCodes.timedOut]: \"The request timed out.\",\r\n};\r\n\r\n/**\r\n * BrowserAuthErrorMessage class containing string constants used by error codes and messages.\r\n * @deprecated Use exported BrowserAuthErrorCodes instead.\r\n * In your app you can do :\r\n * ```\r\n * import { BrowserAuthErrorCodes } from \"@azure/msal-browser\";\r\n * ```\r\n */\r\nexport const BrowserAuthErrorMessage = {\r\n pkceNotGenerated: {\r\n code: BrowserAuthErrorCodes.pkceNotCreated,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.pkceNotCreated],\r\n },\r\n cryptoDoesNotExist: {\r\n code: BrowserAuthErrorCodes.cryptoNonExistent,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.cryptoNonExistent],\r\n },\r\n emptyNavigateUriError: {\r\n code: BrowserAuthErrorCodes.emptyNavigateUri,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.emptyNavigateUri],\r\n },\r\n hashEmptyError: {\r\n code: BrowserAuthErrorCodes.hashEmptyError,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.hashEmptyError],\r\n },\r\n hashDoesNotContainStateError: {\r\n code: BrowserAuthErrorCodes.noStateInHash,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.noStateInHash],\r\n },\r\n hashDoesNotContainKnownPropertiesError: {\r\n code: BrowserAuthErrorCodes.hashDoesNotContainKnownProperties,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.hashDoesNotContainKnownProperties\r\n ],\r\n },\r\n unableToParseStateError: {\r\n code: BrowserAuthErrorCodes.unableToParseState,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.unableToParseState\r\n ],\r\n },\r\n stateInteractionTypeMismatchError: {\r\n code: BrowserAuthErrorCodes.stateInteractionTypeMismatch,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.stateInteractionTypeMismatch\r\n ],\r\n },\r\n interactionInProgress: {\r\n code: BrowserAuthErrorCodes.interactionInProgress,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.interactionInProgress\r\n ],\r\n },\r\n popupWindowError: {\r\n code: BrowserAuthErrorCodes.popupWindowError,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.popupWindowError],\r\n },\r\n emptyWindowError: {\r\n code: BrowserAuthErrorCodes.emptyWindowError,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.emptyWindowError],\r\n },\r\n userCancelledError: {\r\n code: BrowserAuthErrorCodes.userCancelled,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.userCancelled],\r\n },\r\n monitorPopupTimeoutError: {\r\n code: BrowserAuthErrorCodes.monitorPopupTimeout,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.monitorPopupTimeout\r\n ],\r\n },\r\n monitorIframeTimeoutError: {\r\n code: BrowserAuthErrorCodes.monitorWindowTimeout,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.monitorWindowTimeout\r\n ],\r\n },\r\n redirectInIframeError: {\r\n code: BrowserAuthErrorCodes.redirectInIframe,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.redirectInIframe],\r\n },\r\n blockTokenRequestsInHiddenIframeError: {\r\n code: BrowserAuthErrorCodes.blockIframeReload,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.blockIframeReload],\r\n },\r\n blockAcquireTokenInPopupsError: {\r\n code: BrowserAuthErrorCodes.blockNestedPopups,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.blockNestedPopups],\r\n },\r\n iframeClosedPrematurelyError: {\r\n code: BrowserAuthErrorCodes.iframeClosedPrematurely,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.iframeClosedPrematurely\r\n ],\r\n },\r\n silentLogoutUnsupportedError: {\r\n code: BrowserAuthErrorCodes.silentLogoutUnsupported,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.silentLogoutUnsupported\r\n ],\r\n },\r\n noAccountError: {\r\n code: BrowserAuthErrorCodes.noAccountError,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.noAccountError],\r\n },\r\n silentPromptValueError: {\r\n code: BrowserAuthErrorCodes.silentPromptValueError,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.silentPromptValueError\r\n ],\r\n },\r\n noTokenRequestCacheError: {\r\n code: BrowserAuthErrorCodes.noTokenRequestCacheError,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.noTokenRequestCacheError\r\n ],\r\n },\r\n unableToParseTokenRequestCacheError: {\r\n code: BrowserAuthErrorCodes.unableToParseTokenRequestCacheError,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.unableToParseTokenRequestCacheError\r\n ],\r\n },\r\n authRequestNotSet: {\r\n code: BrowserAuthErrorCodes.authRequestNotSetError,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.authRequestNotSetError\r\n ],\r\n },\r\n invalidCacheType: {\r\n code: BrowserAuthErrorCodes.invalidCacheType,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.invalidCacheType],\r\n },\r\n notInBrowserEnvironment: {\r\n code: BrowserAuthErrorCodes.nonBrowserEnvironment,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.nonBrowserEnvironment\r\n ],\r\n },\r\n databaseNotOpen: {\r\n code: BrowserAuthErrorCodes.databaseNotOpen,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.databaseNotOpen],\r\n },\r\n noNetworkConnectivity: {\r\n code: BrowserAuthErrorCodes.noNetworkConnectivity,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.noNetworkConnectivity\r\n ],\r\n },\r\n postRequestFailed: {\r\n code: BrowserAuthErrorCodes.postRequestFailed,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.postRequestFailed],\r\n },\r\n getRequestFailed: {\r\n code: BrowserAuthErrorCodes.getRequestFailed,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.getRequestFailed],\r\n },\r\n failedToParseNetworkResponse: {\r\n code: BrowserAuthErrorCodes.failedToParseResponse,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.failedToParseResponse\r\n ],\r\n },\r\n unableToLoadTokenError: {\r\n code: BrowserAuthErrorCodes.unableToLoadToken,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.unableToLoadToken],\r\n },\r\n signingKeyNotFoundInStorage: {\r\n code: BrowserAuthErrorCodes.cryptoKeyNotFound,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.cryptoKeyNotFound],\r\n },\r\n authCodeRequired: {\r\n code: BrowserAuthErrorCodes.authCodeRequired,\r\n desc: BrowserAuthErrorMessages[BrowserAuthErrorCodes.authCodeRequired],\r\n },\r\n authCodeOrNativeAccountRequired: {\r\n code: BrowserAuthErrorCodes.authCodeOrNativeAccountIdRequired,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.authCodeOrNativeAccountIdRequired\r\n ],\r\n },\r\n spaCodeAndNativeAccountPresent: {\r\n code: BrowserAuthErrorCodes.spaCodeAndNativeAccountIdPresent,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.spaCodeAndNativeAccountIdPresent\r\n ],\r\n },\r\n databaseUnavailable: {\r\n code: BrowserAuthErrorCodes.databaseUnavailable,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.databaseUnavailable\r\n ],\r\n },\r\n unableToAcquireTokenFromNativePlatform: {\r\n code: BrowserAuthErrorCodes.unableToAcquireTokenFromNativePlatform,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.unableToAcquireTokenFromNativePlatform\r\n ],\r\n },\r\n nativeHandshakeTimeout: {\r\n code: BrowserAuthErrorCodes.nativeHandshakeTimeout,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.nativeHandshakeTimeout\r\n ],\r\n },\r\n nativeExtensionNotInstalled: {\r\n code: BrowserAuthErrorCodes.nativeExtensionNotInstalled,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.nativeExtensionNotInstalled\r\n ],\r\n },\r\n nativeConnectionNotEstablished: {\r\n code: BrowserAuthErrorCodes.nativeConnectionNotEstablished,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.nativeConnectionNotEstablished\r\n ],\r\n },\r\n uninitializedPublicClientApplication: {\r\n code: BrowserAuthErrorCodes.uninitializedPublicClientApplication,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.uninitializedPublicClientApplication\r\n ],\r\n },\r\n nativePromptNotSupported: {\r\n code: BrowserAuthErrorCodes.nativePromptNotSupported,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.nativePromptNotSupported\r\n ],\r\n },\r\n invalidBase64StringError: {\r\n code: BrowserAuthErrorCodes.invalidBase64String,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.invalidBase64String\r\n ],\r\n },\r\n invalidPopTokenRequest: {\r\n code: BrowserAuthErrorCodes.invalidPopTokenRequest,\r\n desc: BrowserAuthErrorMessages[\r\n BrowserAuthErrorCodes.invalidPopTokenRequest\r\n ],\r\n },\r\n};\r\n\r\n/**\r\n * Browser library error class thrown by the MSAL.js library for SPAs\r\n */\r\nexport class BrowserAuthError extends AuthError {\r\n constructor(errorCode: string, subError?: string) {\r\n super(errorCode, BrowserAuthErrorMessages[errorCode], subError);\r\n\r\n Object.setPrototypeOf(this, BrowserAuthError.prototype);\r\n this.name = \"BrowserAuthError\";\r\n }\r\n}\r\n\r\nexport function createBrowserAuthError(\r\n errorCode: string,\r\n subError?: string\r\n): BrowserAuthError {\r\n return new BrowserAuthError(errorCode, subError);\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { OIDC_DEFAULT_SCOPES } from \"@azure/msal-common/browser\";\r\nimport { PopupRequest } from \"../request/PopupRequest.js\";\r\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\r\n\r\n/**\r\n * Constants\r\n */\r\nexport const BrowserConstants = {\r\n /**\r\n * Interaction in progress cache value\r\n */\r\n INTERACTION_IN_PROGRESS_VALUE: \"interaction_in_progress\",\r\n /**\r\n * Invalid grant error code\r\n */\r\n INVALID_GRANT_ERROR: \"invalid_grant\",\r\n /**\r\n * Default popup window width\r\n */\r\n POPUP_WIDTH: 483,\r\n /**\r\n * Default popup window height\r\n */\r\n POPUP_HEIGHT: 600,\r\n /**\r\n * Name of the popup window starts with\r\n */\r\n POPUP_NAME_PREFIX: \"msal\",\r\n /**\r\n * Default popup monitor poll interval in milliseconds\r\n */\r\n DEFAULT_POLL_INTERVAL_MS: 30,\r\n /**\r\n * Msal-browser SKU\r\n */\r\n MSAL_SKU: \"msal.js.browser\",\r\n};\r\n\r\nexport const PlatformAuthConstants = {\r\n CHANNEL_ID: \"53ee284d-920a-4b59-9d30-a60315b26836\",\r\n PREFERRED_EXTENSION_ID: \"ppnbnpeolgkicgegkbkbjmhlideopiji\",\r\n MATS_TELEMETRY: \"MATS\",\r\n MICROSOFT_ENTRA_BROKERID: \"MicrosoftEntra\",\r\n DOM_API_NAME: \"DOM API\",\r\n PLATFORM_DOM_APIS: \"get-token-and-sign-out\",\r\n PLATFORM_DOM_PROVIDER: \"PlatformAuthDOMHandler\",\r\n PLATFORM_EXTENSION_PROVIDER: \"PlatformAuthExtensionHandler\",\r\n};\r\n\r\nexport const NativeExtensionMethod = {\r\n HandshakeRequest: \"Handshake\",\r\n HandshakeResponse: \"HandshakeResponse\",\r\n GetToken: \"GetToken\",\r\n Response: \"Response\",\r\n} as const;\r\nexport type NativeExtensionMethod =\r\n (typeof NativeExtensionMethod)[keyof typeof NativeExtensionMethod];\r\n\r\nexport const BrowserCacheLocation = {\r\n LocalStorage: \"localStorage\",\r\n SessionStorage: \"sessionStorage\",\r\n MemoryStorage: \"memoryStorage\",\r\n} as const;\r\nexport type BrowserCacheLocation =\r\n (typeof BrowserCacheLocation)[keyof typeof BrowserCacheLocation];\r\n\r\n/**\r\n * HTTP Request types supported by MSAL.\r\n */\r\nexport const HTTP_REQUEST_TYPE = {\r\n GET: \"GET\",\r\n POST: \"POST\",\r\n} as const;\r\nexport type HTTP_REQUEST_TYPE =\r\n (typeof HTTP_REQUEST_TYPE)[keyof typeof HTTP_REQUEST_TYPE];\r\n\r\nexport const INTERACTION_TYPE = {\r\n SIGNIN: \"signin\",\r\n SIGNOUT: \"signout\",\r\n} as const;\r\nexport type INTERACTION_TYPE =\r\n (typeof INTERACTION_TYPE)[keyof typeof INTERACTION_TYPE];\r\n\r\n/**\r\n * Temporary cache keys for MSAL, deleted after any request.\r\n */\r\nexport const TemporaryCacheKeys = {\r\n ORIGIN_URI: \"request.origin\",\r\n URL_HASH: \"urlHash\",\r\n REQUEST_PARAMS: \"request.params\",\r\n VERIFIER: \"code.verifier\",\r\n INTERACTION_STATUS_KEY: \"interaction.status\",\r\n NATIVE_REQUEST: \"request.native\",\r\n} as const;\r\nexport type TemporaryCacheKeys =\r\n (typeof TemporaryCacheKeys)[keyof typeof TemporaryCacheKeys];\r\n\r\n/**\r\n * Cache keys stored in-memory\r\n */\r\nexport const InMemoryCacheKeys = {\r\n WRAPPER_SKU: \"wrapper.sku\",\r\n WRAPPER_VER: \"wrapper.version\",\r\n} as const;\r\nexport type InMemoryCacheKeys =\r\n (typeof InMemoryCacheKeys)[keyof typeof InMemoryCacheKeys];\r\n\r\n/**\r\n * API Codes for Telemetry purposes.\r\n * Before adding a new code you must claim it in the MSAL Telemetry tracker as these number spaces are shared across all MSALs\r\n * 0-99 Silent Flow\r\n * 800-899 Auth Code Flow\r\n */\r\nexport const ApiId = {\r\n acquireTokenRedirect: 861,\r\n acquireTokenPopup: 862,\r\n ssoSilent: 863,\r\n acquireTokenSilent_authCode: 864,\r\n handleRedirectPromise: 865,\r\n acquireTokenByCode: 866,\r\n acquireTokenSilent_silentFlow: 61,\r\n logout: 961,\r\n logoutPopup: 962,\r\n} as const;\r\nexport type ApiId = (typeof ApiId)[keyof typeof ApiId];\r\n\r\n/*\r\n * Interaction type of the API - used for state and telemetry\r\n */\r\nexport enum InteractionType {\r\n Redirect = \"redirect\",\r\n Popup = \"popup\",\r\n Silent = \"silent\",\r\n None = \"none\",\r\n}\r\n\r\n/**\r\n * Types of interaction currently in progress.\r\n * Used in events in wrapper libraries to invoke functions when certain interaction is in progress or all interactions are complete.\r\n */\r\nexport const InteractionStatus = {\r\n /**\r\n * Initial status before interaction occurs\r\n */\r\n Startup: \"startup\",\r\n /**\r\n * Status set when all login calls occuring\r\n */\r\n Login: \"login\",\r\n /**\r\n * Status set when logout call occuring\r\n */\r\n Logout: \"logout\",\r\n /**\r\n * Status set for acquireToken calls\r\n */\r\n AcquireToken: \"acquireToken\",\r\n /**\r\n * Status set for ssoSilent calls\r\n */\r\n SsoSilent: \"ssoSilent\",\r\n /**\r\n * Status set when handleRedirect in progress\r\n */\r\n HandleRedirect: \"handleRedirect\",\r\n /**\r\n * Status set when interaction is complete\r\n */\r\n None: \"none\",\r\n} as const;\r\nexport type InteractionStatus =\r\n (typeof InteractionStatus)[keyof typeof InteractionStatus];\r\n\r\nexport const DEFAULT_REQUEST: RedirectRequest | PopupRequest = {\r\n scopes: OIDC_DEFAULT_SCOPES,\r\n};\r\n\r\n/**\r\n * JWK Key Format string (Type MUST be defined for window crypto APIs)\r\n */\r\nexport const KEY_FORMAT_JWK = \"jwk\";\r\n\r\n// Supported wrapper SKUs\r\nexport const WrapperSKU = {\r\n React: \"@azure/msal-react\",\r\n Angular: \"@azure/msal-angular\",\r\n} as const;\r\nexport type WrapperSKU = (typeof WrapperSKU)[keyof typeof WrapperSKU];\r\n\r\n// DatabaseStorage Constants\r\nexport const DB_NAME = \"msal.db\";\r\nexport const DB_VERSION = 1;\r\nexport const DB_TABLE_NAME = `${DB_NAME}.keys`;\r\n\r\nexport const CacheLookupPolicy = {\r\n /*\r\n * acquireTokenSilent will attempt to retrieve an access token from the cache. If the access token is expired\r\n * or cannot be found the refresh token will be used to acquire a new one. Finally, if the refresh token\r\n * is expired acquireTokenSilent will attempt to acquire new access and refresh tokens.\r\n */\r\n Default: 0, // 0 is falsy, is equivalent to not passing in a CacheLookupPolicy\r\n /*\r\n * acquireTokenSilent will only look for access tokens in the cache. It will not attempt to renew access or\r\n * refresh tokens.\r\n */\r\n AccessToken: 1,\r\n /*\r\n * acquireTokenSilent will attempt to retrieve an access token from the cache. If the access token is expired or\r\n * cannot be found, the refresh token will be used to acquire a new one. If the refresh token is expired, it\r\n * will not be renewed and acquireTokenSilent will fail.\r\n */\r\n AccessTokenAndRefreshToken: 2,\r\n /*\r\n * acquireTokenSilent will not attempt to retrieve access tokens from the cache and will instead attempt to\r\n * exchange the cached refresh token for a new access token. If the refresh token is expired, it will not be\r\n * renewed and acquireTokenSilent will fail.\r\n */\r\n RefreshToken: 3,\r\n /*\r\n * acquireTokenSilent will not look in the cache for the access token. It will go directly to network with the\r\n * cached refresh token. If the refresh token is expired an attempt will be made to renew it. This is equivalent to\r\n * setting \"forceRefresh: true\".\r\n */\r\n RefreshTokenAndNetwork: 4,\r\n /*\r\n * acquireTokenSilent will attempt to renew both access and refresh tokens. It will not look in the cache. This will\r\n * always fail if 3rd party cookies are blocked by the browser.\r\n */\r\n Skip: 5,\r\n} as const;\r\nexport type CacheLookupPolicy =\r\n (typeof CacheLookupPolicy)[keyof typeof CacheLookupPolicy];\r\n\r\nexport const iFrameRenewalPolicies: CacheLookupPolicy[] = [\r\n CacheLookupPolicy.Default,\r\n CacheLookupPolicy.Skip,\r\n CacheLookupPolicy.RefreshTokenAndNetwork,\r\n];\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n/**\r\n * Class which exposes APIs to encode plaintext to base64 encoded string. See here for implementation details:\r\n * https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_JavaScript's_UTF-16_%3E_UTF-8_%3E_base64\r\n */\r\n\r\n/**\r\n * Returns URL Safe b64 encoded string from a plaintext string.\r\n * @param input\r\n */\r\nexport function urlEncode(input: string): string {\r\n return encodeURIComponent(\r\n base64Encode(input)\r\n .replace(/=/g, \"\")\r\n .replace(/\\+/g, \"-\")\r\n .replace(/\\//g, \"_\")\r\n );\r\n}\r\n\r\n/**\r\n * Returns URL Safe b64 encoded string from an int8Array.\r\n * @param inputArr\r\n */\r\nexport function urlEncodeArr(inputArr: Uint8Array): string {\r\n return base64EncArr(inputArr)\r\n .replace(/=/g, \"\")\r\n .replace(/\\+/g, \"-\")\r\n .replace(/\\//g, \"_\");\r\n}\r\n\r\n/**\r\n * Returns b64 encoded string from plaintext string.\r\n * @param input\r\n */\r\nexport function base64Encode(input: string): string {\r\n return base64EncArr(new TextEncoder().encode(input));\r\n}\r\n\r\n/**\r\n * Base64 encode byte array\r\n * @param aBytes\r\n */\r\nfunction base64EncArr(aBytes: Uint8Array): string {\r\n const binString = Array.from(aBytes, (x) => String.fromCodePoint(x)).join(\r\n \"\"\r\n );\r\n return btoa(binString);\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n BrowserAuthErrorCodes,\r\n createBrowserAuthError,\r\n} from \"../error/BrowserAuthError.js\";\r\n\r\n/**\r\n * Class which exposes APIs to decode base64 strings to plaintext. See here for implementation details:\r\n * https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem\r\n */\r\n\r\n/**\r\n * Returns a URL-safe plaintext decoded string from b64 encoded input.\r\n * @param input\r\n */\r\nexport function base64Decode(input: string): string {\r\n return new TextDecoder().decode(base64DecToArr(input));\r\n}\r\n\r\n/**\r\n * Decodes base64 into Uint8Array\r\n * @param base64String\r\n */\r\nexport function base64DecToArr(base64String: string): Uint8Array {\r\n let encodedString = base64String.replace(/-/g, \"+\").replace(/_/g, \"/\");\r\n switch (encodedString.length % 4) {\r\n case 0:\r\n break;\r\n case 2:\r\n encodedString += \"==\";\r\n break;\r\n case 3:\r\n encodedString += \"=\";\r\n break;\r\n default:\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.invalidBase64String\r\n );\r\n }\r\n const binString = atob(encodedString);\r\n return Uint8Array.from(binString, (m) => m.codePointAt(0) || 0);\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport {\r\n IPerformanceClient,\r\n PerformanceEvents,\r\n} from \"@azure/msal-common/browser\";\r\nimport { KEY_FORMAT_JWK } from \"../utils/BrowserConstants.js\";\r\nimport { base64Encode, urlEncodeArr } from \"../encode/Base64Encode.js\";\r\nimport { base64Decode, base64DecToArr } from \"../encode/Base64Decode.js\";\r\n\r\n/**\r\n * This file defines functions used by the browser library to perform cryptography operations such as\r\n * hashing and encoding. It also has helper functions to validate the availability of specific APIs.\r\n */\r\n\r\n/**\r\n * See here for more info on RsaHashedKeyGenParams: https://developer.mozilla.org/en-US/docs/Web/API/RsaHashedKeyGenParams\r\n */\r\n// Algorithms\r\nconst PKCS1_V15_KEYGEN_ALG = \"RSASSA-PKCS1-v1_5\";\r\nconst AES_GCM = \"AES-GCM\";\r\nconst HKDF = \"HKDF\";\r\n// SHA-256 hashing algorithm\r\nconst S256_HASH_ALG = \"SHA-256\";\r\n// MOD length for PoP tokens\r\nconst MODULUS_LENGTH = 2048;\r\n// Public Exponent\r\nconst PUBLIC_EXPONENT: Uint8Array = new Uint8Array([0x01, 0x00, 0x01]);\r\n// UUID hex digits\r\nconst UUID_CHARS = \"0123456789abcdef\";\r\n// Array to store UINT32 random value\r\nconst UINT32_ARR = new Uint32Array(1);\r\n\r\n// Key Format\r\nconst RAW = \"raw\";\r\n// Key Usages\r\nconst ENCRYPT = \"encrypt\";\r\nconst DECRYPT = \"decrypt\";\r\nconst DERIVE_KEY = \"deriveKey\";\r\n\r\n// Suberror\r\nconst SUBTLE_SUBERROR = \"crypto_subtle_undefined\";\r\n\r\nconst keygenAlgorithmOptions: RsaHashedKeyGenParams = {\r\n name: PKCS1_V15_KEYGEN_ALG,\r\n hash: S256_HASH_ALG,\r\n modulusLength: MODULUS_LENGTH,\r\n publicExponent: PUBLIC_EXPONENT,\r\n};\r\n\r\n/**\r\n * Check whether browser crypto is available.\r\n */\r\nexport function validateCryptoAvailable(\r\n skipValidateSubtleCrypto: boolean\r\n): void {\r\n if (!window) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.nonBrowserEnvironment\r\n );\r\n }\r\n if (!window.crypto) {\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.cryptoNonExistent);\r\n }\r\n if (!skipValidateSubtleCrypto && !window.crypto.subtle) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.cryptoNonExistent,\r\n SUBTLE_SUBERROR\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Returns a sha-256 hash of the given dataString as an ArrayBuffer.\r\n * @param dataString {string} data string\r\n * @param performanceClient {?IPerformanceClient}\r\n * @param correlationId {?string} correlation id\r\n */\r\nexport async function sha256Digest(\r\n dataString: string,\r\n performanceClient?: IPerformanceClient,\r\n correlationId?: string\r\n): Promise {\r\n performanceClient?.addQueueMeasurement(\r\n PerformanceEvents.Sha256Digest,\r\n correlationId\r\n );\r\n const encoder = new TextEncoder();\r\n const data = encoder.encode(dataString);\r\n return window.crypto.subtle.digest(\r\n S256_HASH_ALG,\r\n data\r\n ) as Promise;\r\n}\r\n\r\n/**\r\n * Populates buffer with cryptographically random values.\r\n * @param dataBuffer\r\n */\r\nexport function getRandomValues(dataBuffer: Uint8Array): Uint8Array {\r\n return window.crypto.getRandomValues(dataBuffer);\r\n}\r\n\r\n/**\r\n * Returns random Uint32 value.\r\n * @returns {number}\r\n */\r\nfunction getRandomUint32(): number {\r\n window.crypto.getRandomValues(UINT32_ARR);\r\n return UINT32_ARR[0];\r\n}\r\n\r\n/**\r\n * Creates a UUID v7 from the current timestamp.\r\n * Implementation relies on the system clock to guarantee increasing order of generated identifiers.\r\n * @returns {number}\r\n */\r\nexport function createNewGuid(): string {\r\n const currentTimestamp = Date.now();\r\n const baseRand = getRandomUint32() * 0x400 + (getRandomUint32() & 0x3ff);\r\n\r\n // Result byte array\r\n const bytes = new Uint8Array(16);\r\n // A 12-bit `rand_a` field value\r\n const randA = Math.trunc(baseRand / 2 ** 30);\r\n // The higher 30 bits of 62-bit `rand_b` field value\r\n const randBHi = baseRand & (2 ** 30 - 1);\r\n // The lower 32 bits of 62-bit `rand_b` field value\r\n const randBLo = getRandomUint32();\r\n\r\n bytes[0] = currentTimestamp / 2 ** 40;\r\n bytes[1] = currentTimestamp / 2 ** 32;\r\n bytes[2] = currentTimestamp / 2 ** 24;\r\n bytes[3] = currentTimestamp / 2 ** 16;\r\n bytes[4] = currentTimestamp / 2 ** 8;\r\n bytes[5] = currentTimestamp;\r\n bytes[6] = 0x70 | (randA >>> 8);\r\n bytes[7] = randA;\r\n bytes[8] = 0x80 | (randBHi >>> 24);\r\n bytes[9] = randBHi >>> 16;\r\n bytes[10] = randBHi >>> 8;\r\n bytes[11] = randBHi;\r\n bytes[12] = randBLo >>> 24;\r\n bytes[13] = randBLo >>> 16;\r\n bytes[14] = randBLo >>> 8;\r\n bytes[15] = randBLo;\r\n\r\n let text = \"\";\r\n for (let i = 0; i < bytes.length; i++) {\r\n text += UUID_CHARS.charAt(bytes[i] >>> 4);\r\n text += UUID_CHARS.charAt(bytes[i] & 0xf);\r\n if (i === 3 || i === 5 || i === 7 || i === 9) {\r\n text += \"-\";\r\n }\r\n }\r\n return text;\r\n}\r\n\r\n/**\r\n * Generates a keypair based on current keygen algorithm config.\r\n * @param extractable\r\n * @param usages\r\n */\r\nexport async function generateKeyPair(\r\n extractable: boolean,\r\n usages: Array\r\n): Promise {\r\n return window.crypto.subtle.generateKey(\r\n keygenAlgorithmOptions,\r\n extractable,\r\n usages\r\n ) as Promise;\r\n}\r\n\r\n/**\r\n * Export key as Json Web Key (JWK)\r\n * @param key\r\n */\r\nexport async function exportJwk(key: CryptoKey): Promise {\r\n return window.crypto.subtle.exportKey(\r\n KEY_FORMAT_JWK,\r\n key\r\n ) as Promise;\r\n}\r\n\r\n/**\r\n * Imports key as Json Web Key (JWK), can set extractable and usages.\r\n * @param key\r\n * @param extractable\r\n * @param usages\r\n */\r\nexport async function importJwk(\r\n key: JsonWebKey,\r\n extractable: boolean,\r\n usages: Array\r\n): Promise {\r\n return window.crypto.subtle.importKey(\r\n KEY_FORMAT_JWK,\r\n key,\r\n keygenAlgorithmOptions,\r\n extractable,\r\n usages\r\n ) as Promise;\r\n}\r\n\r\n/**\r\n * Signs given data with given key\r\n * @param key\r\n * @param data\r\n */\r\nexport async function sign(\r\n key: CryptoKey,\r\n data: ArrayBuffer\r\n): Promise {\r\n return window.crypto.subtle.sign(\r\n keygenAlgorithmOptions,\r\n key,\r\n data\r\n ) as Promise;\r\n}\r\n\r\n/**\r\n * Generates Base64 encoded jwk used in the Encrypted Authorize Response (EAR) flow\r\n */\r\nexport async function generateEarKey(): Promise {\r\n const key = await generateBaseKey();\r\n const keyStr = urlEncodeArr(new Uint8Array(key));\r\n\r\n const jwk = {\r\n alg: \"dir\",\r\n kty: \"oct\",\r\n k: keyStr,\r\n };\r\n\r\n return base64Encode(JSON.stringify(jwk));\r\n}\r\n\r\n/**\r\n * Parses earJwk for encryption key and returns CryptoKey object\r\n * @param earJwk\r\n * @returns\r\n */\r\nexport async function importEarKey(earJwk: string): Promise {\r\n const b64DecodedJwk = base64Decode(earJwk);\r\n const jwkJson = JSON.parse(b64DecodedJwk);\r\n const rawKey = jwkJson.k;\r\n const keyBuffer = base64DecToArr(rawKey);\r\n\r\n return window.crypto.subtle.importKey(RAW, keyBuffer, AES_GCM, false, [\r\n DECRYPT,\r\n ]);\r\n}\r\n\r\n/**\r\n * Decrypt ear_jwe response returned in the Encrypted Authorize Response (EAR) flow\r\n * @param earJwk\r\n * @param earJwe\r\n * @returns\r\n */\r\nexport async function decryptEarResponse(\r\n earJwk: string,\r\n earJwe: string\r\n): Promise {\r\n const earJweParts = earJwe.split(\".\");\r\n if (earJweParts.length !== 5) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.failedToDecryptEarResponse,\r\n \"jwe_length\"\r\n );\r\n }\r\n\r\n const key = await importEarKey(earJwk).catch(() => {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.failedToDecryptEarResponse,\r\n \"import_key\"\r\n );\r\n });\r\n\r\n try {\r\n const header = new TextEncoder().encode(earJweParts[0]);\r\n const iv = base64DecToArr(earJweParts[2]);\r\n const ciphertext = base64DecToArr(earJweParts[3]);\r\n const tag = base64DecToArr(earJweParts[4]);\r\n const tagLengthBits = tag.byteLength * 8;\r\n\r\n // Concat ciphertext and tag\r\n const encryptedData = new Uint8Array(ciphertext.length + tag.length);\r\n encryptedData.set(ciphertext);\r\n encryptedData.set(tag, ciphertext.length);\r\n\r\n const decryptedData = await window.crypto.subtle.decrypt(\r\n {\r\n name: AES_GCM,\r\n iv: iv,\r\n tagLength: tagLengthBits,\r\n additionalData: header,\r\n },\r\n key,\r\n encryptedData\r\n );\r\n\r\n return new TextDecoder().decode(decryptedData);\r\n } catch (e) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.failedToDecryptEarResponse,\r\n \"decrypt\"\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Generates symmetric base encryption key. This may be stored as all encryption/decryption keys will be derived from this one.\r\n */\r\nexport async function generateBaseKey(): Promise {\r\n const key = await window.crypto.subtle.generateKey(\r\n {\r\n name: AES_GCM,\r\n length: 256,\r\n },\r\n true,\r\n [ENCRYPT, DECRYPT]\r\n );\r\n return window.crypto.subtle.exportKey(RAW, key);\r\n}\r\n\r\n/**\r\n * Returns the raw key to be passed into the key derivation function\r\n * @param baseKey\r\n * @returns\r\n */\r\nexport async function generateHKDF(baseKey: ArrayBuffer): Promise {\r\n return window.crypto.subtle.importKey(RAW, baseKey, HKDF, false, [\r\n DERIVE_KEY,\r\n ]);\r\n}\r\n\r\n/**\r\n * Given a base key and a nonce generates a derived key to be used in encryption and decryption.\r\n * Note: every time we encrypt a new key is derived\r\n * @param baseKey\r\n * @param nonce\r\n * @returns\r\n */\r\nasync function deriveKey(\r\n baseKey: CryptoKey,\r\n nonce: ArrayBuffer,\r\n context: string\r\n): Promise {\r\n return window.crypto.subtle.deriveKey(\r\n {\r\n name: HKDF,\r\n salt: nonce,\r\n hash: S256_HASH_ALG,\r\n info: new TextEncoder().encode(context),\r\n },\r\n baseKey,\r\n { name: AES_GCM, length: 256 },\r\n false,\r\n [ENCRYPT, DECRYPT]\r\n );\r\n}\r\n\r\n/**\r\n * Encrypt the given data given a base key. Returns encrypted data and a nonce that must be provided during decryption\r\n * @param key\r\n * @param rawData\r\n */\r\nexport async function encrypt(\r\n baseKey: CryptoKey,\r\n rawData: string,\r\n context: string\r\n): Promise<{ data: string; nonce: string }> {\r\n const encodedData = new TextEncoder().encode(rawData);\r\n // The nonce must never be reused with a given key.\r\n const nonce = window.crypto.getRandomValues(new Uint8Array(16));\r\n const derivedKey = await deriveKey(baseKey, nonce, context);\r\n const encryptedData = await window.crypto.subtle.encrypt(\r\n {\r\n name: AES_GCM,\r\n iv: new Uint8Array(12), // New key is derived for every encrypt so we don't need a new nonce\r\n },\r\n derivedKey,\r\n encodedData\r\n );\r\n\r\n return {\r\n data: urlEncodeArr(new Uint8Array(encryptedData)),\r\n nonce: urlEncodeArr(nonce),\r\n };\r\n}\r\n\r\n/**\r\n * Decrypt data with the given key and nonce\r\n * @param key\r\n * @param nonce\r\n * @param encryptedData\r\n * @returns\r\n */\r\nexport async function decrypt(\r\n baseKey: CryptoKey,\r\n nonce: string,\r\n context: string,\r\n encryptedData: string\r\n): Promise {\r\n const encodedData = base64DecToArr(encryptedData);\r\n const derivedKey = await deriveKey(baseKey, base64DecToArr(nonce), context);\r\n const decryptedData = await window.crypto.subtle.decrypt(\r\n {\r\n name: AES_GCM,\r\n iv: new Uint8Array(12), // New key is derived for every encrypt so we don't need a new nonce\r\n },\r\n derivedKey,\r\n encodedData\r\n );\r\n\r\n return new TextDecoder().decode(decryptedData);\r\n}\r\n\r\n/**\r\n * Returns the SHA-256 hash of an input string\r\n * @param plainText\r\n */\r\nexport async function hashString(plainText: string): Promise {\r\n const hashBuffer: ArrayBuffer = await sha256Digest(plainText);\r\n const hashBytes = new Uint8Array(hashBuffer);\r\n return urlEncodeArr(hashBytes);\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport const storageNotSupported = \"storage_not_supported\";\r\nexport const stubbedPublicClientApplicationCalled =\r\n \"stubbed_public_client_application_called\";\r\nexport const inMemRedirectUnavailable = \"in_mem_redirect_unavailable\";\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthError } from \"@azure/msal-common/browser\";\r\nimport * as BrowserConfigurationAuthErrorCodes from \"./BrowserConfigurationAuthErrorCodes.js\";\r\nexport { BrowserConfigurationAuthErrorCodes };\r\n\r\nexport const BrowserConfigurationAuthErrorMessages = {\r\n [BrowserConfigurationAuthErrorCodes.storageNotSupported]:\r\n \"Given storage configuration option was not supported.\",\r\n [BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled]:\r\n \"Stub instance of Public Client Application was called. If using msal-react, please ensure context is not used without a provider. For more visit: aka.ms/msaljs/browser-errors\",\r\n [BrowserConfigurationAuthErrorCodes.inMemRedirectUnavailable]:\r\n \"Redirect cannot be supported. In-memory storage was selected and storeAuthStateInCookie=false, which would cause the library to be unable to handle the incoming hash. If you would like to use the redirect API, please use session/localStorage or set storeAuthStateInCookie=true.\",\r\n};\r\n\r\n/**\r\n * BrowserAuthErrorMessage class containing string constants used by error codes and messages.\r\n * @deprecated Use BrowserAuthErrorCodes instead\r\n */\r\nexport const BrowserConfigurationAuthErrorMessage = {\r\n storageNotSupportedError: {\r\n code: BrowserConfigurationAuthErrorCodes.storageNotSupported,\r\n desc: BrowserConfigurationAuthErrorMessages[\r\n BrowserConfigurationAuthErrorCodes.storageNotSupported\r\n ],\r\n },\r\n stubPcaInstanceCalled: {\r\n code: BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled,\r\n desc: BrowserConfigurationAuthErrorMessages[\r\n BrowserConfigurationAuthErrorCodes\r\n .stubbedPublicClientApplicationCalled\r\n ],\r\n },\r\n inMemRedirectUnavailable: {\r\n code: BrowserConfigurationAuthErrorCodes.inMemRedirectUnavailable,\r\n desc: BrowserConfigurationAuthErrorMessages[\r\n BrowserConfigurationAuthErrorCodes.inMemRedirectUnavailable\r\n ],\r\n },\r\n};\r\n\r\n/**\r\n * Browser library error class thrown by the MSAL.js library for SPAs\r\n */\r\nexport class BrowserConfigurationAuthError extends AuthError {\r\n constructor(errorCode: string, errorMessage?: string) {\r\n super(errorCode, errorMessage);\r\n this.name = \"BrowserConfigurationAuthError\";\r\n\r\n Object.setPrototypeOf(this, BrowserConfigurationAuthError.prototype);\r\n }\r\n}\r\n\r\nexport function createBrowserConfigurationAuthError(\r\n errorCode: string\r\n): BrowserConfigurationAuthError {\r\n return new BrowserConfigurationAuthError(\r\n errorCode,\r\n BrowserConfigurationAuthErrorMessages[errorCode]\r\n );\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n UrlString,\r\n invoke,\r\n invokeAsync,\r\n RequestParameterBuilder,\r\n} from \"@azure/msal-common/browser\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { BrowserConstants, BrowserCacheLocation } from \"./BrowserConstants.js\";\r\nimport * as BrowserCrypto from \"../crypto/BrowserCrypto.js\";\r\nimport {\r\n BrowserConfigurationAuthErrorCodes,\r\n createBrowserConfigurationAuthError,\r\n} from \"../error/BrowserConfigurationAuthError.js\";\r\nimport type { BrowserConfiguration } from \"../config/Configuration.js\";\r\n\r\n/**\r\n * Clears hash from window url.\r\n */\r\nexport function clearHash(contentWindow: Window): void {\r\n // Office.js sets history.replaceState to null\r\n contentWindow.location.hash = \"\";\r\n if (typeof contentWindow.history.replaceState === \"function\") {\r\n // Full removes \"#\" from url\r\n contentWindow.history.replaceState(\r\n null,\r\n \"\",\r\n `${contentWindow.location.origin}${contentWindow.location.pathname}${contentWindow.location.search}`\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Replaces current hash with hash from provided url\r\n */\r\nexport function replaceHash(url: string): void {\r\n const urlParts = url.split(\"#\");\r\n urlParts.shift(); // Remove part before the hash\r\n window.location.hash = urlParts.length > 0 ? urlParts.join(\"#\") : \"\";\r\n}\r\n\r\n/**\r\n * Returns boolean of whether the current window is in an iframe or not.\r\n */\r\nexport function isInIframe(): boolean {\r\n return window.parent !== window;\r\n}\r\n\r\n/**\r\n * Returns boolean of whether or not the current window is a popup opened by msal\r\n */\r\nexport function isInPopup(): boolean {\r\n return (\r\n typeof window !== \"undefined\" &&\r\n !!window.opener &&\r\n window.opener !== window &&\r\n typeof window.name === \"string\" &&\r\n window.name.indexOf(`${BrowserConstants.POPUP_NAME_PREFIX}.`) === 0\r\n );\r\n}\r\n\r\n// #endregion\r\n\r\n/**\r\n * Returns current window URL as redirect uri\r\n */\r\nexport function getCurrentUri(): string {\r\n return typeof window !== \"undefined\" && window.location\r\n ? window.location.href.split(\"?\")[0].split(\"#\")[0]\r\n : \"\";\r\n}\r\n\r\n/**\r\n * Gets the homepage url for the current window location.\r\n */\r\nexport function getHomepage(): string {\r\n const currentUrl = new UrlString(window.location.href);\r\n const urlComponents = currentUrl.getUrlComponents();\r\n return `${urlComponents.Protocol}//${urlComponents.HostNameAndPort}/`;\r\n}\r\n\r\n/**\r\n * Throws error if we have completed an auth and are\r\n * attempting another auth request inside an iframe.\r\n */\r\nexport function blockReloadInHiddenIframes(): void {\r\n const isResponseHash = UrlString.hashContainsKnownProperties(\r\n window.location.hash\r\n );\r\n // return an error if called from the hidden iframe created by the msal js silent calls\r\n if (isResponseHash && isInIframe()) {\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.blockIframeReload);\r\n }\r\n}\r\n\r\n/**\r\n * Block redirect operations in iframes unless explicitly allowed\r\n * @param interactionType Interaction type for the request\r\n * @param allowRedirectInIframe Config value to allow redirects when app is inside an iframe\r\n */\r\nexport function blockRedirectInIframe(allowRedirectInIframe: boolean): void {\r\n if (isInIframe() && !allowRedirectInIframe) {\r\n // If we are not in top frame, we shouldn't redirect. This is also handled by the service.\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.redirectInIframe);\r\n }\r\n}\r\n\r\n/**\r\n * Block redirectUri loaded in popup from calling AcquireToken APIs\r\n */\r\nexport function blockAcquireTokenInPopups(): void {\r\n // Popups opened by msal popup APIs are given a name that starts with \"msal.\"\r\n if (isInPopup()) {\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.blockNestedPopups);\r\n }\r\n}\r\n\r\n/**\r\n * Throws error if token requests are made in non-browser environment\r\n * @param isBrowserEnvironment Flag indicating if environment is a browser.\r\n */\r\nexport function blockNonBrowserEnvironment(): void {\r\n if (typeof window === \"undefined\") {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.nonBrowserEnvironment\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Throws error if initialize hasn't been called\r\n * @param initialized\r\n */\r\nexport function blockAPICallsBeforeInitialize(initialized: boolean): void {\r\n if (!initialized) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.uninitializedPublicClientApplication\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Helper to validate app environment before making an auth request\r\n * @param initialized\r\n */\r\nexport function preflightCheck(initialized: boolean): void {\r\n // Block request if not in browser environment\r\n blockNonBrowserEnvironment();\r\n\r\n // Block auth requests inside a hidden iframe\r\n blockReloadInHiddenIframes();\r\n\r\n // Block redirectUri opened in a popup from calling MSAL APIs\r\n blockAcquireTokenInPopups();\r\n\r\n // Block token acquisition before initialize has been called\r\n blockAPICallsBeforeInitialize(initialized);\r\n}\r\n\r\n/**\r\n * Helper to validate app enviornment before making redirect request\r\n * @param initialized\r\n * @param config\r\n */\r\nexport function redirectPreflightCheck(\r\n initialized: boolean,\r\n config: BrowserConfiguration\r\n): void {\r\n preflightCheck(initialized);\r\n blockRedirectInIframe(config.system.allowRedirectInIframe);\r\n // Block redirects if memory storage is enabled but storeAuthStateInCookie is not\r\n if (\r\n config.cache.cacheLocation === BrowserCacheLocation.MemoryStorage &&\r\n !config.cache.storeAuthStateInCookie\r\n ) {\r\n throw createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.inMemRedirectUnavailable\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Adds a preconnect link element to the header which begins DNS resolution and SSL connection in anticipation of the /token request\r\n * @param loginDomain Authority domain, including https protocol e.g. https://login.microsoftonline.com\r\n * @returns\r\n */\r\nexport function preconnect(authority: string): void {\r\n const link = document.createElement(\"link\");\r\n link.rel = \"preconnect\";\r\n link.href = new URL(authority).origin;\r\n link.crossOrigin = \"anonymous\";\r\n document.head.appendChild(link);\r\n\r\n // The browser will close connection if not used within a few seconds, remove element from the header after 10s\r\n window.setTimeout(() => {\r\n try {\r\n document.head.removeChild(link);\r\n } catch {}\r\n }, 10000); // 10s Timeout\r\n}\r\n\r\n/**\r\n * Wrapper function that creates a UUID v7 from the current timestamp.\r\n * @returns {string}\r\n */\r\nexport function createGuid(): string {\r\n return BrowserCrypto.createNewGuid();\r\n}\r\n\r\nexport { invoke };\r\nexport { invokeAsync };\r\nexport const addClientCapabilitiesToClaims =\r\n RequestParameterBuilder.addClientCapabilitiesToClaims;\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n BrowserAuthErrorCodes,\r\n createBrowserAuthError,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { INavigationClient } from \"./INavigationClient.js\";\r\nimport { NavigationOptions } from \"./NavigationOptions.js\";\r\n\r\nexport class NavigationClient implements INavigationClient {\r\n /**\r\n * Navigates to other pages within the same web application\r\n * @param url\r\n * @param options\r\n */\r\n navigateInternal(\r\n url: string,\r\n options: NavigationOptions\r\n ): Promise {\r\n return NavigationClient.defaultNavigateWindow(url, options);\r\n }\r\n\r\n /**\r\n * Navigates to other pages outside the web application i.e. the Identity Provider\r\n * @param url\r\n * @param options\r\n */\r\n navigateExternal(\r\n url: string,\r\n options: NavigationOptions\r\n ): Promise {\r\n return NavigationClient.defaultNavigateWindow(url, options);\r\n }\r\n\r\n /**\r\n * Default navigation implementation invoked by the internal and external functions\r\n * @param url\r\n * @param options\r\n */\r\n private static defaultNavigateWindow(\r\n url: string,\r\n options: NavigationOptions\r\n ): Promise {\r\n if (options.noHistory) {\r\n window.location.replace(url); // CodeQL [SM03712] Application owner controls the URL. User can't change it.\r\n } else {\r\n window.location.assign(url); // CodeQL [SM03712] Application owner controls the URL. User can't change it.\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n setTimeout(() => {\r\n reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.timedOut,\r\n \"failed_to_redirect\"\r\n )\r\n );\r\n }, options.timeout);\r\n });\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n INetworkModule,\r\n NetworkRequestOptions,\r\n NetworkResponse,\r\n createNetworkError,\r\n} from \"@azure/msal-common/browser\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { HTTP_REQUEST_TYPE } from \"../utils/BrowserConstants.js\";\r\n\r\n/**\r\n * This class implements the Fetch API for GET and POST requests. See more here: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API\r\n */\r\nexport class FetchClient implements INetworkModule {\r\n /**\r\n * Fetch Client for REST endpoints - Get request\r\n * @param url\r\n * @param headers\r\n * @param body\r\n */\r\n async sendGetRequestAsync(\r\n url: string,\r\n options?: NetworkRequestOptions\r\n ): Promise> {\r\n let response: Response;\r\n let responseHeaders: Record = {};\r\n let responseStatus = 0;\r\n const reqHeaders = getFetchHeaders(options);\r\n try {\r\n response = await fetch(url, {\r\n method: HTTP_REQUEST_TYPE.GET,\r\n headers: reqHeaders,\r\n });\r\n } catch (e) {\r\n throw createNetworkError(\r\n createBrowserAuthError(\r\n window.navigator.onLine\r\n ? BrowserAuthErrorCodes.getRequestFailed\r\n : BrowserAuthErrorCodes.noNetworkConnectivity\r\n ),\r\n undefined,\r\n undefined,\r\n e as Error\r\n );\r\n }\r\n\r\n responseHeaders = getHeaderDict(response.headers);\r\n try {\r\n responseStatus = response.status;\r\n return {\r\n headers: responseHeaders,\r\n body: (await response.json()) as T,\r\n status: responseStatus,\r\n };\r\n } catch (e) {\r\n throw createNetworkError(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.failedToParseResponse\r\n ),\r\n responseStatus,\r\n responseHeaders,\r\n e as Error\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Fetch Client for REST endpoints - Post request\r\n * @param url\r\n * @param headers\r\n * @param body\r\n */\r\n async sendPostRequestAsync(\r\n url: string,\r\n options?: NetworkRequestOptions\r\n ): Promise> {\r\n const reqBody = (options && options.body) || \"\";\r\n const reqHeaders = getFetchHeaders(options);\r\n\r\n let response: Response;\r\n let responseStatus = 0;\r\n let responseHeaders: Record = {};\r\n try {\r\n response = await fetch(url, {\r\n method: HTTP_REQUEST_TYPE.POST,\r\n headers: reqHeaders,\r\n body: reqBody,\r\n });\r\n } catch (e) {\r\n throw createNetworkError(\r\n createBrowserAuthError(\r\n window.navigator.onLine\r\n ? BrowserAuthErrorCodes.postRequestFailed\r\n : BrowserAuthErrorCodes.noNetworkConnectivity\r\n ),\r\n undefined,\r\n undefined,\r\n e as Error\r\n );\r\n }\r\n\r\n responseHeaders = getHeaderDict(response.headers);\r\n try {\r\n responseStatus = response.status;\r\n return {\r\n headers: responseHeaders,\r\n body: (await response.json()) as T,\r\n status: responseStatus,\r\n };\r\n } catch (e) {\r\n throw createNetworkError(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.failedToParseResponse\r\n ),\r\n responseStatus,\r\n responseHeaders,\r\n e as Error\r\n );\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Get Fetch API Headers object from string map\r\n * @param inputHeaders\r\n */\r\nfunction getFetchHeaders(options?: NetworkRequestOptions): Headers {\r\n try {\r\n const headers = new Headers();\r\n if (!(options && options.headers)) {\r\n return headers;\r\n }\r\n const optionsHeaders = options.headers;\r\n Object.entries(optionsHeaders).forEach(([key, value]) => {\r\n headers.append(key, value);\r\n });\r\n return headers;\r\n } catch (e) {\r\n throw createNetworkError(\r\n createBrowserAuthError(BrowserAuthErrorCodes.failedToBuildHeaders),\r\n undefined,\r\n undefined,\r\n e as Error\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Returns object representing response headers\r\n * @param headers\r\n * @returns\r\n */\r\nfunction getHeaderDict(headers: Headers): Record {\r\n try {\r\n const headerDict: Record = {};\r\n headers.forEach((value: string, key: string) => {\r\n headerDict[key] = value;\r\n });\r\n return headerDict;\r\n } catch (e) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.failedToParseHeaders\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n SystemOptions,\r\n LoggerOptions,\r\n INetworkModule,\r\n DEFAULT_SYSTEM_OPTIONS,\r\n Constants,\r\n ProtocolMode,\r\n OIDCOptions,\r\n ServerResponseType,\r\n LogLevel,\r\n StubbedNetworkModule,\r\n AzureCloudInstance,\r\n AzureCloudOptions,\r\n ApplicationTelemetry,\r\n createClientConfigurationError,\r\n ClientConfigurationErrorCodes,\r\n IPerformanceClient,\r\n StubPerformanceClient,\r\n Logger,\r\n} from \"@azure/msal-common/browser\";\r\nimport {\r\n BrowserCacheLocation,\r\n BrowserConstants,\r\n} from \"../utils/BrowserConstants.js\";\r\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\r\nimport { NavigationClient } from \"../navigation/NavigationClient.js\";\r\nimport { FetchClient } from \"../network/FetchClient.js\";\r\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\r\n\r\n// Default timeout for popup windows and iframes in milliseconds\r\nexport const DEFAULT_POPUP_TIMEOUT_MS = 60000;\r\nexport const DEFAULT_IFRAME_TIMEOUT_MS = 10000;\r\nexport const DEFAULT_REDIRECT_TIMEOUT_MS = 30000;\r\nexport const DEFAULT_NATIVE_BROKER_HANDSHAKE_TIMEOUT_MS = 2000;\r\n\r\n/**\r\n * Use this to configure the auth options in the Configuration object\r\n */\r\nexport type BrowserAuthOptions = {\r\n /**\r\n * Client ID of your app registered with our Application registration portal : https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredAppsPreview in Microsoft Identity Platform\r\n */\r\n clientId: string;\r\n /**\r\n * You can configure a specific authority, defaults to \" \" or \"https://login.microsoftonline.com/common\"\r\n */\r\n authority?: string;\r\n /**\r\n * An array of URIs that are known to be valid. Used in B2C scenarios.\r\n */\r\n knownAuthorities?: Array;\r\n /**\r\n * A string containing the cloud discovery response. Used in AAD scenarios.\r\n */\r\n cloudDiscoveryMetadata?: string;\r\n /**\r\n * A string containing the .well-known/openid-configuration endpoint response\r\n */\r\n authorityMetadata?: string;\r\n /**\r\n * The redirect URI where authentication responses can be received by your application. It must exactly match one of the redirect URIs registered in the Azure portal.\r\n */\r\n redirectUri?: string;\r\n /**\r\n * The redirect URI where the window navigates after a successful logout.\r\n */\r\n postLogoutRedirectUri?: string | null;\r\n /**\r\n * Boolean indicating whether to navigate to the original request URL after the auth server navigates to the redirect URL.\r\n */\r\n navigateToLoginRequestUrl?: boolean;\r\n /**\r\n * Array of capabilities which will be added to the claims.access_token.xms_cc request property on every network request.\r\n */\r\n clientCapabilities?: Array;\r\n /**\r\n * Enum that represents the protocol that msal follows. Used for configuring proper endpoints.\r\n */\r\n protocolMode?: ProtocolMode;\r\n /**\r\n * Enum that configures options for the OIDC protocol mode.\r\n */\r\n OIDCOptions?: OIDCOptions;\r\n /**\r\n * Enum that represents the Azure Cloud to use.\r\n */\r\n azureCloudOptions?: AzureCloudOptions;\r\n /**\r\n * Flag of whether to use the local metadata cache\r\n */\r\n skipAuthorityMetadataCache?: boolean;\r\n /**\r\n * App supports nested app auth or not; defaults to\r\n *\r\n * @deprecated This flag is deprecated and will be removed in the next major version. createNestablePublicClientApplication should be used instead.\r\n */\r\n supportsNestedAppAuth?: boolean;\r\n /**\r\n * Callback that will be passed the url that MSAL will navigate to in redirect flows. Returning false in the callback will stop navigation.\r\n */\r\n onRedirectNavigate?: (url: string) => boolean | void;\r\n /**\r\n * Flag of whether the STS will send back additional parameters to specify where the tokens should be retrieved from.\r\n */\r\n instanceAware?: boolean;\r\n /**\r\n * Flag of whether to encode query parameters\r\n * @deprecated This flag is deprecated and will be removed in the next major version where all extra query params will be encoded by default.\r\n */\r\n encodeExtraQueryParams?: boolean;\r\n};\r\n\r\n/** @internal */\r\nexport type InternalAuthOptions = Omit<\r\n Required,\r\n \"onRedirectNavigate\"\r\n> & {\r\n OIDCOptions: Required;\r\n onRedirectNavigate?: (url: string) => boolean | void;\r\n};\r\n\r\n/**\r\n * Use this to configure the below cache configuration options:\r\n */\r\nexport type CacheOptions = {\r\n /**\r\n * Used to specify the cacheLocation user wants to set. Valid values are \"localStorage\", \"sessionStorage\" and \"memoryStorage\".\r\n */\r\n cacheLocation?: BrowserCacheLocation | string;\r\n /**\r\n * Used to specify the number of days cache entries written by previous versions of MSAL.js should be retained in the browser. Defaults to 5 days.\r\n */\r\n cacheRetentionDays?: number;\r\n /**\r\n * Used to specify the temporaryCacheLocation user wants to set. Valid values are \"localStorage\", \"sessionStorage\" and \"memoryStorage\".\r\n * @deprecated This option is deprecated and will be removed in the next major version.\r\n */\r\n temporaryCacheLocation?: BrowserCacheLocation | string;\r\n /**\r\n * If set, MSAL stores the auth request state required for validation of the auth flows in the browser cookies. By default this flag is set to false.\r\n * @deprecated This option is deprecated and will be removed in the next major version.\r\n */\r\n storeAuthStateInCookie?: boolean;\r\n /**\r\n * If set, MSAL sets the \"Secure\" flag on cookies so they can only be sent over HTTPS. By default this flag is set to true.\r\n * @deprecated This option will be removed in the next major version and all cookies set will include the Secure attribute.\r\n */\r\n secureCookies?: boolean;\r\n /**\r\n * If set, MSAL will attempt to migrate cache entries from older versions on initialization. By default this flag is set to true if cacheLocation is localStorage, otherwise false.\r\n * @deprecated This option is deprecated and will be removed in the next major version.\r\n */\r\n cacheMigrationEnabled?: boolean;\r\n /**\r\n * Flag that determines whether access tokens are stored based on requested claims\r\n * @deprecated This option is deprecated and will be removed in the next major version.\r\n */\r\n claimsBasedCachingEnabled?: boolean;\r\n};\r\n\r\nexport type BrowserSystemOptions = SystemOptions & {\r\n /**\r\n * Used to initialize the Logger object (See ClientConfiguration.ts)\r\n */\r\n loggerOptions?: LoggerOptions;\r\n /**\r\n * Network interface implementation\r\n */\r\n networkClient?: INetworkModule;\r\n /**\r\n * Override the methods used to navigate to other webpages. Particularly useful if you are using a client-side router\r\n */\r\n navigationClient?: INavigationClient;\r\n /**\r\n * Sets the timeout for waiting for a response hash in a popup. Will take precedence over loadFrameTimeout if both are set.\r\n */\r\n windowHashTimeout?: number;\r\n /**\r\n * Sets the timeout for waiting for a response hash in an iframe. Will take precedence over loadFrameTimeout if both are set.\r\n */\r\n iframeHashTimeout?: number;\r\n /**\r\n * Sets the timeout for waiting for a response hash in an iframe or popup\r\n */\r\n loadFrameTimeout?: number;\r\n /**\r\n * Maximum time the library should wait for a frame to load\r\n * @deprecated This was previously needed for older browsers which are no longer supported by MSAL.js. This option will be removed in the next major version\r\n */\r\n navigateFrameWait?: number;\r\n /**\r\n * Time to wait for redirection to occur before resolving promise\r\n */\r\n redirectNavigationTimeout?: number;\r\n /**\r\n * Sets whether popups are opened asynchronously. By default, this flag is set to false. When set to false, blank popups are opened before anything else happens. When set to true, popups are opened when making the network request.\r\n */\r\n asyncPopups?: boolean;\r\n /**\r\n * Flag to enable redirect opertaions when the app is rendered in an iframe (to support scenarios such as embedded B2C login).\r\n */\r\n allowRedirectInIframe?: boolean;\r\n /**\r\n * Flag to enable native broker support (e.g. acquiring tokens from WAM on Windows, MacBroker on Mac)\r\n */\r\n allowPlatformBroker?: boolean;\r\n /**\r\n * Sets the timeout for waiting for the native broker handshake to resolve\r\n */\r\n nativeBrokerHandshakeTimeout?: number;\r\n /**\r\n * Sets the interval length in milliseconds for polling the location attribute in popup windows (default is 30ms)\r\n */\r\n pollIntervalMilliseconds?: number;\r\n};\r\n\r\n/**\r\n * Telemetry Options\r\n */\r\nexport type BrowserTelemetryOptions = {\r\n /**\r\n * Telemetry information sent on request\r\n * - appName: Unique string name of an application\r\n * - appVersion: Version of the application using MSAL\r\n */\r\n application?: ApplicationTelemetry;\r\n\r\n client?: IPerformanceClient;\r\n};\r\n\r\n/**\r\n * This object allows you to configure important elements of MSAL functionality and is passed into the constructor of PublicClientApplication\r\n */\r\nexport type Configuration = {\r\n /**\r\n * This is where you configure auth elements like clientID, authority used for authenticating against the Microsoft Identity Platform\r\n */\r\n auth: BrowserAuthOptions;\r\n /**\r\n * This is where you configure cache location and whether to store cache in cookies\r\n */\r\n cache?: CacheOptions;\r\n /**\r\n * This is where you can configure the network client, logger, token renewal offset\r\n */\r\n system?: BrowserSystemOptions;\r\n /**\r\n * This is where you can configure telemetry data and options\r\n */\r\n telemetry?: BrowserTelemetryOptions;\r\n};\r\n\r\n/** @internal */\r\nexport type BrowserConfiguration = {\r\n auth: InternalAuthOptions;\r\n cache: Required;\r\n system: Required;\r\n telemetry: Required;\r\n};\r\n\r\n/**\r\n * MSAL function that sets the default options when not explicitly configured from app developer\r\n *\r\n * @param auth\r\n * @param cache\r\n * @param system\r\n *\r\n * @returns Configuration object\r\n */\r\nexport function buildConfiguration(\r\n {\r\n auth: userInputAuth,\r\n cache: userInputCache,\r\n system: userInputSystem,\r\n telemetry: userInputTelemetry,\r\n }: Configuration,\r\n isBrowserEnvironment: boolean\r\n): BrowserConfiguration {\r\n // Default auth options for browser\r\n const DEFAULT_AUTH_OPTIONS: InternalAuthOptions = {\r\n clientId: Constants.EMPTY_STRING,\r\n authority: `${Constants.DEFAULT_AUTHORITY}`,\r\n knownAuthorities: [],\r\n cloudDiscoveryMetadata: Constants.EMPTY_STRING,\r\n authorityMetadata: Constants.EMPTY_STRING,\r\n redirectUri:\r\n typeof window !== \"undefined\" ? BrowserUtils.getCurrentUri() : \"\",\r\n postLogoutRedirectUri: Constants.EMPTY_STRING,\r\n navigateToLoginRequestUrl: true,\r\n clientCapabilities: [],\r\n protocolMode: ProtocolMode.AAD,\r\n OIDCOptions: {\r\n serverResponseType: ServerResponseType.FRAGMENT,\r\n defaultScopes: [\r\n Constants.OPENID_SCOPE,\r\n Constants.PROFILE_SCOPE,\r\n Constants.OFFLINE_ACCESS_SCOPE,\r\n ],\r\n },\r\n azureCloudOptions: {\r\n azureCloudInstance: AzureCloudInstance.None,\r\n tenant: Constants.EMPTY_STRING,\r\n },\r\n skipAuthorityMetadataCache: false,\r\n supportsNestedAppAuth: false,\r\n instanceAware: false,\r\n encodeExtraQueryParams: false,\r\n };\r\n\r\n // Default cache options for browser\r\n const DEFAULT_CACHE_OPTIONS: Required = {\r\n cacheLocation: BrowserCacheLocation.SessionStorage,\r\n cacheRetentionDays: 5,\r\n temporaryCacheLocation: BrowserCacheLocation.SessionStorage,\r\n storeAuthStateInCookie: false,\r\n secureCookies: false,\r\n // Default cache migration to true if cache location is localStorage since entries are preserved across tabs/windows. Migration has little to no benefit in sessionStorage and memoryStorage\r\n cacheMigrationEnabled:\r\n userInputCache &&\r\n userInputCache.cacheLocation === BrowserCacheLocation.LocalStorage\r\n ? true\r\n : false,\r\n claimsBasedCachingEnabled: false,\r\n };\r\n\r\n // Default logger options for browser\r\n const DEFAULT_LOGGER_OPTIONS: LoggerOptions = {\r\n // eslint-disable-next-line @typescript-eslint/no-empty-function\r\n loggerCallback: (): void => {\r\n // allow users to not set logger call back\r\n },\r\n logLevel: LogLevel.Info,\r\n piiLoggingEnabled: false,\r\n };\r\n\r\n // Default system options for browser\r\n const DEFAULT_BROWSER_SYSTEM_OPTIONS: Required = {\r\n ...DEFAULT_SYSTEM_OPTIONS,\r\n loggerOptions: DEFAULT_LOGGER_OPTIONS,\r\n networkClient: isBrowserEnvironment\r\n ? new FetchClient()\r\n : StubbedNetworkModule,\r\n navigationClient: new NavigationClient(),\r\n loadFrameTimeout: 0,\r\n // If loadFrameTimeout is provided, use that as default.\r\n windowHashTimeout:\r\n userInputSystem?.loadFrameTimeout || DEFAULT_POPUP_TIMEOUT_MS,\r\n iframeHashTimeout:\r\n userInputSystem?.loadFrameTimeout || DEFAULT_IFRAME_TIMEOUT_MS,\r\n navigateFrameWait: 0,\r\n redirectNavigationTimeout: DEFAULT_REDIRECT_TIMEOUT_MS,\r\n asyncPopups: false,\r\n allowRedirectInIframe: false,\r\n allowPlatformBroker: false,\r\n nativeBrokerHandshakeTimeout:\r\n userInputSystem?.nativeBrokerHandshakeTimeout ||\r\n DEFAULT_NATIVE_BROKER_HANDSHAKE_TIMEOUT_MS,\r\n pollIntervalMilliseconds: BrowserConstants.DEFAULT_POLL_INTERVAL_MS,\r\n };\r\n\r\n const providedSystemOptions: Required = {\r\n ...DEFAULT_BROWSER_SYSTEM_OPTIONS,\r\n ...userInputSystem,\r\n loggerOptions: userInputSystem?.loggerOptions || DEFAULT_LOGGER_OPTIONS,\r\n };\r\n\r\n const DEFAULT_TELEMETRY_OPTIONS: Required = {\r\n application: {\r\n appName: Constants.EMPTY_STRING,\r\n appVersion: Constants.EMPTY_STRING,\r\n },\r\n client: new StubPerformanceClient(),\r\n };\r\n\r\n // Throw an error if user has set OIDCOptions without being in OIDC protocol mode\r\n if (\r\n userInputAuth?.protocolMode !== ProtocolMode.OIDC &&\r\n userInputAuth?.OIDCOptions\r\n ) {\r\n const logger = new Logger(providedSystemOptions.loggerOptions);\r\n logger.warning(\r\n JSON.stringify(\r\n createClientConfigurationError(\r\n ClientConfigurationErrorCodes.cannotSetOIDCOptions\r\n )\r\n )\r\n );\r\n }\r\n\r\n // Throw an error if user has set allowPlatformBroker to true with OIDC protocol mode\r\n if (\r\n userInputAuth?.protocolMode &&\r\n userInputAuth.protocolMode === ProtocolMode.OIDC &&\r\n providedSystemOptions?.allowPlatformBroker\r\n ) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.cannotAllowPlatformBroker\r\n );\r\n }\r\n\r\n const overlayedConfig: BrowserConfiguration = {\r\n auth: {\r\n ...DEFAULT_AUTH_OPTIONS,\r\n ...userInputAuth,\r\n OIDCOptions: {\r\n ...DEFAULT_AUTH_OPTIONS.OIDCOptions,\r\n ...userInputAuth?.OIDCOptions,\r\n },\r\n },\r\n cache: { ...DEFAULT_CACHE_OPTIONS, ...userInputCache },\r\n system: providedSystemOptions,\r\n telemetry: { ...DEFAULT_TELEMETRY_OPTIONS, ...userInputTelemetry },\r\n };\r\n\r\n return overlayedConfig;\r\n}\r\n", "/* eslint-disable header/header */\r\nexport const name = \"@azure/msal-browser\";\r\nexport const version = \"4.22.1\";\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport const PREFIX = \"msal\";\r\nconst BROWSER_PREFIX = \"browser\";\r\nexport const CACHE_KEY_SEPARATOR = \"-\";\r\nexport const CREDENTIAL_SCHEMA_VERSION = 1;\r\nexport const ACCOUNT_SCHEMA_VERSION = 1;\r\n\r\nexport const LOG_LEVEL_CACHE_KEY = `${PREFIX}.${BROWSER_PREFIX}.log.level`;\r\nexport const LOG_PII_CACHE_KEY = `${PREFIX}.${BROWSER_PREFIX}.log.pii`;\r\nexport const BROWSER_PERF_ENABLED_KEY = `${PREFIX}.${BROWSER_PREFIX}.performance.enabled`;\r\nexport const PLATFORM_AUTH_DOM_SUPPORT = `${PREFIX}.${BROWSER_PREFIX}.platform.auth.dom`;\r\nexport const VERSION_CACHE_KEY = `${PREFIX}.version`;\r\nexport const ACCOUNT_KEYS = \"account.keys\";\r\nexport const TOKEN_KEYS = \"token.keys\";\r\n\r\nexport function getAccountKeysCacheKey(\r\n schema: number = ACCOUNT_SCHEMA_VERSION\r\n): string {\r\n if (schema < 1) {\r\n return `${PREFIX}.${ACCOUNT_KEYS}`;\r\n }\r\n\r\n return `${PREFIX}.${schema}.${ACCOUNT_KEYS}`;\r\n}\r\n\r\nexport function getTokenKeysCacheKey(\r\n clientId: string,\r\n schema: number = CREDENTIAL_SCHEMA_VERSION\r\n): string {\r\n if (schema < 1) {\r\n return `${PREFIX}.${TOKEN_KEYS}.${clientId}`;\r\n }\r\n\r\n return `${PREFIX}.${schema}.${TOKEN_KEYS}.${clientId}`;\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { Logger, LogLevel } from \"@azure/msal-common/browser\";\r\nimport {\r\n BrowserConfiguration,\r\n buildConfiguration,\r\n Configuration,\r\n} from \"../config/Configuration.js\";\r\nimport { version, name } from \"../packageMetadata.js\";\r\nimport { BrowserCacheLocation } from \"../utils/BrowserConstants.js\";\r\nimport { LOG_LEVEL_CACHE_KEY, LOG_PII_CACHE_KEY } from \"../cache/CacheKeys.js\";\r\n\r\n/**\r\n * Base class for operating context\r\n * Operating contexts are contexts in which MSAL.js is being run\r\n * More than one operating context may be available at a time\r\n * It's important from a logging and telemetry point of view for us to be able to identify the operating context.\r\n * For example: Some operating contexts will pre-cache tokens impacting performance telemetry\r\n */\r\nexport abstract class BaseOperatingContext {\r\n protected logger: Logger;\r\n protected config: BrowserConfiguration;\r\n protected available: boolean;\r\n protected browserEnvironment: boolean;\r\n\r\n protected static loggerCallback(level: LogLevel, message: string): void {\r\n switch (level) {\r\n case LogLevel.Error:\r\n // eslint-disable-next-line no-console\r\n console.error(message);\r\n return;\r\n case LogLevel.Info:\r\n // eslint-disable-next-line no-console\r\n console.info(message);\r\n return;\r\n case LogLevel.Verbose:\r\n // eslint-disable-next-line no-console\r\n console.debug(message);\r\n return;\r\n case LogLevel.Warning:\r\n // eslint-disable-next-line no-console\r\n console.warn(message);\r\n return;\r\n default:\r\n // eslint-disable-next-line no-console\r\n console.log(message);\r\n return;\r\n }\r\n }\r\n\r\n constructor(config: Configuration) {\r\n /*\r\n * If loaded in an environment where window is not available,\r\n * set internal flag to false so that further requests fail.\r\n * This is to support server-side rendering environments.\r\n */\r\n this.browserEnvironment = typeof window !== \"undefined\";\r\n this.config = buildConfiguration(config, this.browserEnvironment);\r\n\r\n let sessionStorage: Storage | undefined;\r\n try {\r\n sessionStorage = window[BrowserCacheLocation.SessionStorage];\r\n // Mute errors if it's a non-browser environment or cookies are blocked.\r\n } catch (e) {}\r\n\r\n const logLevelKey = sessionStorage?.getItem(LOG_LEVEL_CACHE_KEY);\r\n const piiLoggingKey = sessionStorage\r\n ?.getItem(LOG_PII_CACHE_KEY)\r\n ?.toLowerCase();\r\n\r\n const piiLoggingEnabled =\r\n piiLoggingKey === \"true\"\r\n ? true\r\n : piiLoggingKey === \"false\"\r\n ? false\r\n : undefined;\r\n const loggerOptions = { ...this.config.system.loggerOptions };\r\n\r\n const logLevel =\r\n logLevelKey && Object.keys(LogLevel).includes(logLevelKey)\r\n ? LogLevel[logLevelKey]\r\n : undefined;\r\n if (logLevel) {\r\n loggerOptions.loggerCallback = BaseOperatingContext.loggerCallback;\r\n loggerOptions.logLevel = logLevel;\r\n }\r\n if (piiLoggingEnabled !== undefined) {\r\n loggerOptions.piiLoggingEnabled = piiLoggingEnabled;\r\n }\r\n\r\n this.logger = new Logger(loggerOptions, name, version);\r\n this.available = false;\r\n }\r\n\r\n /**\r\n * returns the name of the module containing the API controller associated with this operating context\r\n */\r\n abstract getModuleName(): string;\r\n\r\n /**\r\n * returns the string identifier of this operating context\r\n */\r\n abstract getId(): string;\r\n\r\n /**\r\n * returns a boolean indicating whether this operating context is present\r\n */\r\n abstract initialize(): Promise;\r\n\r\n /**\r\n * Return the MSAL config\r\n * @returns BrowserConfiguration\r\n */\r\n getConfig(): BrowserConfiguration {\r\n return this.config;\r\n }\r\n\r\n /**\r\n * Returns the MSAL Logger\r\n * @returns Logger\r\n */\r\n getLogger(): Logger {\r\n return this.logger;\r\n }\r\n\r\n isAvailable(): boolean {\r\n return this.available;\r\n }\r\n\r\n isBrowserEnvironment(): boolean {\r\n return this.browserEnvironment;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport const BridgeStatusCode = {\r\n UserInteractionRequired: \"USER_INTERACTION_REQUIRED\",\r\n UserCancel: \"USER_CANCEL\",\r\n NoNetwork: \"NO_NETWORK\",\r\n TransientError: \"TRANSIENT_ERROR\",\r\n PersistentError: \"PERSISTENT_ERROR\",\r\n Disabled: \"DISABLED\",\r\n AccountUnavailable: \"ACCOUNT_UNAVAILABLE\",\r\n NestedAppAuthUnavailable: \"NESTED_APP_AUTH_UNAVAILABLE\", // NAA is unavailable in the current context, can retry with standard browser based auth\r\n} as const;\r\nexport type BridgeStatusCode =\r\n (typeof BridgeStatusCode)[keyof typeof BridgeStatusCode];\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthBridge, AuthBridgeResponse } from \"./AuthBridge.js\";\r\nimport { AuthResult } from \"./AuthResult.js\";\r\nimport { BridgeCapabilities } from \"./BridgeCapabilities.js\";\r\nimport { AccountContext } from \"./BridgeAccountContext.js\";\r\nimport { BridgeError } from \"./BridgeError.js\";\r\nimport { BridgeRequest } from \"./BridgeRequest.js\";\r\nimport {\r\n BridgeRequestEnvelope,\r\n BridgeMethods,\r\n} from \"./BridgeRequestEnvelope.js\";\r\nimport { BridgeResponseEnvelope } from \"./BridgeResponseEnvelope.js\";\r\nimport { BridgeStatusCode } from \"./BridgeStatusCode.js\";\r\nimport { IBridgeProxy } from \"./IBridgeProxy.js\";\r\nimport { InitContext } from \"./InitContext.js\";\r\nimport { TokenRequest } from \"./TokenRequest.js\";\r\nimport * as BrowserCrypto from \"../crypto/BrowserCrypto.js\";\r\nimport { BrowserConstants } from \"../utils/BrowserConstants.js\";\r\nimport { version } from \"../packageMetadata.js\";\r\n\r\ndeclare global {\r\n interface Window {\r\n nestedAppAuthBridge: AuthBridge;\r\n }\r\n}\r\n\r\n/**\r\n * BridgeProxy\r\n * Provides a proxy for accessing a bridge to a host app and/or\r\n * platform broker\r\n */\r\nexport class BridgeProxy implements IBridgeProxy {\r\n static bridgeRequests: BridgeRequest[] = [];\r\n sdkName: string;\r\n sdkVersion: string;\r\n capabilities?: BridgeCapabilities;\r\n accountContext?: AccountContext;\r\n\r\n /**\r\n * initializeNestedAppAuthBridge - Initializes the bridge to the host app\r\n * @returns a promise that resolves to an InitializeBridgeResponse or rejects with an Error\r\n * @remarks This method will be called by the create factory method\r\n * @remarks If the bridge is not available, this method will throw an error\r\n */\r\n protected static async initializeNestedAppAuthBridge(): Promise {\r\n if (window === undefined) {\r\n throw new Error(\"window is undefined\");\r\n }\r\n if (window.nestedAppAuthBridge === undefined) {\r\n throw new Error(\"window.nestedAppAuthBridge is undefined\");\r\n }\r\n\r\n try {\r\n window.nestedAppAuthBridge.addEventListener(\r\n \"message\",\r\n (response: AuthBridgeResponse) => {\r\n const responsePayload =\r\n typeof response === \"string\" ? response : response.data;\r\n const responseEnvelope: BridgeResponseEnvelope =\r\n JSON.parse(responsePayload);\r\n const request = BridgeProxy.bridgeRequests.find(\r\n (element) =>\r\n element.requestId === responseEnvelope.requestId\r\n );\r\n if (request !== undefined) {\r\n BridgeProxy.bridgeRequests.splice(\r\n BridgeProxy.bridgeRequests.indexOf(request),\r\n 1\r\n );\r\n if (responseEnvelope.success) {\r\n request.resolve(responseEnvelope);\r\n } else {\r\n request.reject(responseEnvelope.error);\r\n }\r\n }\r\n }\r\n );\r\n\r\n const bridgeResponse = await new Promise(\r\n (resolve, reject) => {\r\n const message = BridgeProxy.buildRequest(\"GetInitContext\");\r\n\r\n const request: BridgeRequest = {\r\n requestId: message.requestId,\r\n method: message.method,\r\n resolve: resolve,\r\n reject: reject,\r\n };\r\n BridgeProxy.bridgeRequests.push(request);\r\n window.nestedAppAuthBridge.postMessage(\r\n JSON.stringify(message)\r\n );\r\n }\r\n );\r\n\r\n return BridgeProxy.validateBridgeResultOrThrow(\r\n bridgeResponse.initContext\r\n );\r\n } catch (error) {\r\n window.console.log(error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * getTokenInteractive - Attempts to get a token interactively from the bridge\r\n * @param request A token request\r\n * @returns a promise that resolves to an auth result or rejects with a BridgeError\r\n */\r\n public getTokenInteractive(request: TokenRequest): Promise {\r\n return this.getToken(\"GetTokenPopup\", request);\r\n }\r\n\r\n /**\r\n * getTokenSilent Attempts to get a token silently from the bridge\r\n * @param request A token request\r\n * @returns a promise that resolves to an auth result or rejects with a BridgeError\r\n */\r\n public getTokenSilent(request: TokenRequest): Promise {\r\n return this.getToken(\"GetToken\", request);\r\n }\r\n\r\n private async getToken(\r\n requestType: BridgeMethods,\r\n request: TokenRequest\r\n ): Promise {\r\n const result = await this.sendRequest(requestType, {\r\n tokenParams: request,\r\n });\r\n return {\r\n token: BridgeProxy.validateBridgeResultOrThrow(result.token),\r\n account: BridgeProxy.validateBridgeResultOrThrow(result.account),\r\n };\r\n }\r\n\r\n public getHostCapabilities(): BridgeCapabilities | null {\r\n return this.capabilities ?? null;\r\n }\r\n\r\n public getAccountContext(): AccountContext | null {\r\n return this.accountContext ? this.accountContext : null;\r\n }\r\n\r\n private static buildRequest(\r\n method: BridgeMethods,\r\n requestParams?: Partial\r\n ): BridgeRequestEnvelope {\r\n return {\r\n messageType: \"NestedAppAuthRequest\",\r\n method: method,\r\n requestId: BrowserCrypto.createNewGuid(),\r\n sendTime: Date.now(),\r\n clientLibrary: BrowserConstants.MSAL_SKU,\r\n clientLibraryVersion: version,\r\n ...requestParams,\r\n };\r\n }\r\n\r\n /**\r\n * A method used to send a request to the bridge\r\n * @param request A token request\r\n * @returns a promise that resolves to a response of provided type or rejects with a BridgeError\r\n */\r\n private sendRequest(\r\n method: BridgeMethods,\r\n requestParams?: Partial\r\n ): Promise {\r\n const message = BridgeProxy.buildRequest(method, requestParams);\r\n\r\n const promise = new Promise(\r\n (resolve, reject) => {\r\n const request: BridgeRequest = {\r\n requestId: message.requestId,\r\n method: message.method,\r\n resolve: resolve,\r\n reject: reject,\r\n };\r\n BridgeProxy.bridgeRequests.push(request);\r\n window.nestedAppAuthBridge.postMessage(JSON.stringify(message));\r\n }\r\n );\r\n\r\n return promise;\r\n }\r\n\r\n private static validateBridgeResultOrThrow(input: T | undefined): T {\r\n if (input === undefined) {\r\n const bridgeError: BridgeError = {\r\n status: BridgeStatusCode.NestedAppAuthUnavailable,\r\n };\r\n throw bridgeError;\r\n }\r\n return input;\r\n }\r\n\r\n /**\r\n * Private constructor for BridgeProxy\r\n * @param sdkName The name of the SDK being used to make requests on behalf of the app\r\n * @param sdkVersion The version of the SDK being used to make requests on behalf of the app\r\n * @param capabilities The capabilities of the bridge / SDK / platform broker\r\n */\r\n private constructor(\r\n sdkName: string,\r\n sdkVersion: string,\r\n accountContext?: AccountContext,\r\n capabilities?: BridgeCapabilities\r\n ) {\r\n this.sdkName = sdkName;\r\n this.sdkVersion = sdkVersion;\r\n this.accountContext = accountContext;\r\n this.capabilities = capabilities;\r\n }\r\n\r\n /**\r\n * Factory method for creating an implementation of IBridgeProxy\r\n * @returns A promise that resolves to a BridgeProxy implementation\r\n */\r\n public static async create(): Promise {\r\n const response = await BridgeProxy.initializeNestedAppAuthBridge();\r\n return new BridgeProxy(\r\n response.sdkName,\r\n response.sdkVersion,\r\n response.accountContext,\r\n response.capabilities\r\n );\r\n }\r\n}\r\n\r\nexport default BridgeProxy;\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { BaseOperatingContext } from \"./BaseOperatingContext.js\";\r\nimport { IBridgeProxy } from \"../naa/IBridgeProxy.js\";\r\nimport { BridgeProxy } from \"../naa/BridgeProxy.js\";\r\nimport { AccountContext } from \"../naa/BridgeAccountContext.js\";\r\n\r\ndeclare global {\r\n interface Window {\r\n __initializeNestedAppAuth?(): Promise;\r\n }\r\n}\r\n\r\nexport class NestedAppOperatingContext extends BaseOperatingContext {\r\n protected bridgeProxy: IBridgeProxy | undefined = undefined;\r\n protected accountContext: AccountContext | null = null;\r\n\r\n /*\r\n * TODO: Once we have determine the bundling code return here to specify the name of the bundle\r\n * containing the implementation for this operating context\r\n */\r\n static readonly MODULE_NAME: string = \"\";\r\n\r\n /**\r\n * Unique identifier for the operating context\r\n */\r\n static readonly ID: string = \"NestedAppOperatingContext\";\r\n\r\n /**\r\n * Return the module name. Intended for use with import() to enable dynamic import\r\n * of the implementation associated with this operating context\r\n * @returns\r\n */\r\n getModuleName(): string {\r\n return NestedAppOperatingContext.MODULE_NAME;\r\n }\r\n\r\n /**\r\n * Returns the unique identifier for this operating context\r\n * @returns string\r\n */\r\n getId(): string {\r\n return NestedAppOperatingContext.ID;\r\n }\r\n\r\n /**\r\n * Returns the current BridgeProxy\r\n * @returns IBridgeProxy | undefined\r\n */\r\n getBridgeProxy(): IBridgeProxy | undefined {\r\n return this.bridgeProxy;\r\n }\r\n\r\n /**\r\n * Checks whether the operating context is available.\r\n * Confirms that the code is running a browser rather. This is required.\r\n * @returns Promise indicating whether this operating context is currently available.\r\n */\r\n async initialize(): Promise {\r\n try {\r\n if (typeof window !== \"undefined\") {\r\n if (typeof window.__initializeNestedAppAuth === \"function\") {\r\n await window.__initializeNestedAppAuth();\r\n }\r\n\r\n const bridgeProxy: IBridgeProxy = await BridgeProxy.create();\r\n /*\r\n * Because we want single sign on we expect the host app to provide the account context\r\n * with a min set of params that can be used to identify the account\r\n * this.account = nestedApp.getAccountByFilter(bridgeProxy.getAccountContext());\r\n */\r\n this.accountContext = bridgeProxy.getAccountContext();\r\n this.bridgeProxy = bridgeProxy;\r\n this.available = bridgeProxy !== undefined;\r\n }\r\n } catch (ex) {\r\n this.logger.infoPii(\r\n `Could not initialize Nested App Auth bridge (${ex})`\r\n );\r\n }\r\n\r\n this.logger.info(`Nested App Auth Bridge available: ${this.available}`);\r\n return this.available;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { BaseOperatingContext } from \"./BaseOperatingContext.js\";\r\n\r\nexport class StandardOperatingContext extends BaseOperatingContext {\r\n /*\r\n * TODO: Once we have determine the bundling code return here to specify the name of the bundle\r\n * containing the implementation for this operating context\r\n */\r\n static readonly MODULE_NAME: string = \"\";\r\n\r\n /**\r\n * Unique identifier for the operating context\r\n */\r\n static readonly ID: string = \"StandardOperatingContext\";\r\n\r\n /**\r\n * Return the module name. Intended for use with import() to enable dynamic import\r\n * of the implementation associated with this operating context\r\n * @returns\r\n */\r\n getModuleName(): string {\r\n return StandardOperatingContext.MODULE_NAME;\r\n }\r\n\r\n /**\r\n * Returns the unique identifier for this operating context\r\n * @returns string\r\n */\r\n getId(): string {\r\n return StandardOperatingContext.ID;\r\n }\r\n\r\n /**\r\n * Checks whether the operating context is available.\r\n * Confirms that the code is running a browser rather. This is required.\r\n * @returns Promise indicating whether this operating context is currently available.\r\n */\r\n async initialize(): Promise {\r\n this.available = typeof window !== \"undefined\";\r\n return this.available;\r\n /*\r\n * NOTE: The standard context is available as long as there is a window. If/when we split out WAM from Browser\r\n * We can move the current contents of the initialize method to here and verify that the WAM extension is available\r\n */\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport {\r\n DB_NAME,\r\n DB_TABLE_NAME,\r\n DB_VERSION,\r\n} from \"../utils/BrowserConstants.js\";\r\nimport { IAsyncStorage } from \"./IAsyncStorage.js\";\r\n\r\ninterface IDBOpenDBRequestEvent extends Event {\r\n target: IDBOpenDBRequest & EventTarget;\r\n}\r\n\r\ninterface IDBOpenOnUpgradeNeededEvent extends IDBVersionChangeEvent {\r\n target: IDBOpenDBRequest & EventTarget;\r\n}\r\n\r\ninterface IDBRequestEvent extends Event {\r\n target: IDBRequest & EventTarget;\r\n}\r\n\r\n/**\r\n * Storage wrapper for IndexedDB storage in browsers: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API\r\n */\r\nexport class DatabaseStorage implements IAsyncStorage {\r\n private db: IDBDatabase | undefined;\r\n private dbName: string;\r\n private tableName: string;\r\n private version: number;\r\n private dbOpen: boolean;\r\n\r\n constructor() {\r\n this.dbName = DB_NAME;\r\n this.version = DB_VERSION;\r\n this.tableName = DB_TABLE_NAME;\r\n this.dbOpen = false;\r\n }\r\n\r\n /**\r\n * Opens IndexedDB instance.\r\n */\r\n async open(): Promise {\r\n return new Promise((resolve, reject) => {\r\n const openDB = window.indexedDB.open(this.dbName, this.version);\r\n openDB.addEventListener(\r\n \"upgradeneeded\",\r\n (e: IDBVersionChangeEvent) => {\r\n const event = e as IDBOpenOnUpgradeNeededEvent;\r\n event.target.result.createObjectStore(this.tableName);\r\n }\r\n );\r\n openDB.addEventListener(\"success\", (e: Event) => {\r\n const event = e as IDBOpenDBRequestEvent;\r\n this.db = event.target.result;\r\n this.dbOpen = true;\r\n resolve();\r\n });\r\n openDB.addEventListener(\"error\", () =>\r\n reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.databaseUnavailable\r\n )\r\n )\r\n );\r\n });\r\n }\r\n\r\n /**\r\n * Closes the connection to IndexedDB database when all pending transactions\r\n * complete.\r\n */\r\n closeConnection(): void {\r\n const db = this.db;\r\n if (db && this.dbOpen) {\r\n db.close();\r\n this.dbOpen = false;\r\n }\r\n }\r\n\r\n /**\r\n * Opens database if it's not already open\r\n */\r\n private async validateDbIsOpen(): Promise {\r\n if (!this.dbOpen) {\r\n return this.open();\r\n }\r\n }\r\n\r\n /**\r\n * Retrieves item from IndexedDB instance.\r\n * @param key\r\n */\r\n async getItem(key: string): Promise {\r\n await this.validateDbIsOpen();\r\n return new Promise((resolve, reject) => {\r\n // TODO: Add timeouts?\r\n if (!this.db) {\r\n return reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.databaseNotOpen\r\n )\r\n );\r\n }\r\n const transaction = this.db.transaction(\r\n [this.tableName],\r\n \"readonly\"\r\n );\r\n const objectStore = transaction.objectStore(this.tableName);\r\n const dbGet = objectStore.get(key);\r\n\r\n dbGet.addEventListener(\"success\", (e: Event) => {\r\n const event = e as IDBRequestEvent;\r\n this.closeConnection();\r\n resolve(event.target.result);\r\n });\r\n\r\n dbGet.addEventListener(\"error\", (e: Event) => {\r\n this.closeConnection();\r\n reject(e);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Adds item to IndexedDB under given key\r\n * @param key\r\n * @param payload\r\n */\r\n async setItem(key: string, payload: T): Promise {\r\n await this.validateDbIsOpen();\r\n return new Promise((resolve: Function, reject: Function) => {\r\n // TODO: Add timeouts?\r\n if (!this.db) {\r\n return reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.databaseNotOpen\r\n )\r\n );\r\n }\r\n const transaction = this.db.transaction(\r\n [this.tableName],\r\n \"readwrite\"\r\n );\r\n\r\n const objectStore = transaction.objectStore(this.tableName);\r\n\r\n const dbPut = objectStore.put(payload, key);\r\n\r\n dbPut.addEventListener(\"success\", () => {\r\n this.closeConnection();\r\n resolve();\r\n });\r\n\r\n dbPut.addEventListener(\"error\", (e) => {\r\n this.closeConnection();\r\n reject(e);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Removes item from IndexedDB under given key\r\n * @param key\r\n */\r\n async removeItem(key: string): Promise {\r\n await this.validateDbIsOpen();\r\n return new Promise((resolve: Function, reject: Function) => {\r\n if (!this.db) {\r\n return reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.databaseNotOpen\r\n )\r\n );\r\n }\r\n\r\n const transaction = this.db.transaction(\r\n [this.tableName],\r\n \"readwrite\"\r\n );\r\n const objectStore = transaction.objectStore(this.tableName);\r\n const dbDelete = objectStore.delete(key);\r\n\r\n dbDelete.addEventListener(\"success\", () => {\r\n this.closeConnection();\r\n resolve();\r\n });\r\n\r\n dbDelete.addEventListener(\"error\", (e) => {\r\n this.closeConnection();\r\n reject(e);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Get all the keys from the storage object as an iterable array of strings.\r\n */\r\n async getKeys(): Promise {\r\n await this.validateDbIsOpen();\r\n return new Promise((resolve: Function, reject: Function) => {\r\n if (!this.db) {\r\n return reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.databaseNotOpen\r\n )\r\n );\r\n }\r\n\r\n const transaction = this.db.transaction(\r\n [this.tableName],\r\n \"readonly\"\r\n );\r\n const objectStore = transaction.objectStore(this.tableName);\r\n const dbGetKeys = objectStore.getAllKeys();\r\n\r\n dbGetKeys.addEventListener(\"success\", (e: Event) => {\r\n const event = e as IDBRequestEvent;\r\n this.closeConnection();\r\n resolve(event.target.result);\r\n });\r\n\r\n dbGetKeys.addEventListener(\"error\", (e: Event) => {\r\n this.closeConnection();\r\n reject(e);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n *\r\n * Checks whether there is an object under the search key in the object store\r\n */\r\n async containsKey(key: string): Promise {\r\n await this.validateDbIsOpen();\r\n\r\n return new Promise((resolve: Function, reject: Function) => {\r\n if (!this.db) {\r\n return reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.databaseNotOpen\r\n )\r\n );\r\n }\r\n\r\n const transaction = this.db.transaction(\r\n [this.tableName],\r\n \"readonly\"\r\n );\r\n const objectStore = transaction.objectStore(this.tableName);\r\n const dbContainsKey = objectStore.count(key);\r\n\r\n dbContainsKey.addEventListener(\"success\", (e: Event) => {\r\n const event = e as IDBRequestEvent;\r\n this.closeConnection();\r\n resolve(event.target.result === 1);\r\n });\r\n\r\n dbContainsKey.addEventListener(\"error\", (e: Event) => {\r\n this.closeConnection();\r\n reject(e);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Deletes the MSAL database. The database is deleted rather than cleared to make it possible\r\n * for client applications to downgrade to a previous MSAL version without worrying about forward compatibility issues\r\n * with IndexedDB database versions.\r\n */\r\n async deleteDatabase(): Promise {\r\n // Check if database being deleted exists\r\n\r\n if (this.db && this.dbOpen) {\r\n this.closeConnection();\r\n }\r\n\r\n return new Promise((resolve: Function, reject: Function) => {\r\n const deleteDbRequest = window.indexedDB.deleteDatabase(DB_NAME);\r\n const id = setTimeout(() => reject(false), 200); // Reject if events aren't raised within 200ms\r\n deleteDbRequest.addEventListener(\"success\", () => {\r\n clearTimeout(id);\r\n return resolve(true);\r\n });\r\n deleteDbRequest.addEventListener(\"blocked\", () => {\r\n clearTimeout(id);\r\n return resolve(true);\r\n });\r\n deleteDbRequest.addEventListener(\"error\", () => {\r\n clearTimeout(id);\r\n return reject(false);\r\n });\r\n });\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { IWindowStorage } from \"./IWindowStorage.js\";\r\n\r\nexport class MemoryStorage implements IWindowStorage {\r\n private cache: Map;\r\n\r\n constructor() {\r\n this.cache = new Map();\r\n }\r\n\r\n async initialize(): Promise {\r\n // Memory storage does not require initialization\r\n }\r\n\r\n getItem(key: string): T | null {\r\n return this.cache.get(key) || null;\r\n }\r\n\r\n getUserData(key: string): T | null {\r\n return this.getItem(key);\r\n }\r\n\r\n setItem(key: string, value: T): void {\r\n this.cache.set(key, value);\r\n }\r\n\r\n async setUserData(key: string, value: T): Promise {\r\n this.setItem(key, value);\r\n }\r\n\r\n removeItem(key: string): void {\r\n this.cache.delete(key);\r\n }\r\n\r\n getKeys(): string[] {\r\n const cacheKeys: string[] = [];\r\n this.cache.forEach((value: T, key: string) => {\r\n cacheKeys.push(key);\r\n });\r\n return cacheKeys;\r\n }\r\n\r\n containsKey(key: string): boolean {\r\n return this.cache.has(key);\r\n }\r\n\r\n clear(): void {\r\n this.cache.clear();\r\n }\r\n\r\n decryptData(): Promise {\r\n // Memory storage does not support encryption, so this method is a no-op\r\n return Promise.resolve(null);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { Logger } from \"@azure/msal-common/browser\";\r\nimport {\r\n BrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { DatabaseStorage } from \"./DatabaseStorage.js\";\r\nimport { IAsyncStorage } from \"./IAsyncStorage.js\";\r\nimport { MemoryStorage } from \"./MemoryStorage.js\";\r\n\r\n/**\r\n * This class allows MSAL to store artifacts asynchronously using the DatabaseStorage IndexedDB wrapper,\r\n * backed up with the more volatile MemoryStorage object for cases in which IndexedDB may be unavailable.\r\n */\r\nexport class AsyncMemoryStorage implements IAsyncStorage {\r\n private inMemoryCache: MemoryStorage;\r\n private indexedDBCache: DatabaseStorage;\r\n private logger: Logger;\r\n\r\n constructor(logger: Logger) {\r\n this.inMemoryCache = new MemoryStorage();\r\n this.indexedDBCache = new DatabaseStorage();\r\n this.logger = logger;\r\n }\r\n\r\n private handleDatabaseAccessError(error: unknown): void {\r\n if (\r\n error instanceof BrowserAuthError &&\r\n error.errorCode === BrowserAuthErrorCodes.databaseUnavailable\r\n ) {\r\n this.logger.error(\r\n \"Could not access persistent storage. This may be caused by browser privacy features which block persistent storage in third-party contexts.\"\r\n );\r\n } else {\r\n throw error;\r\n }\r\n }\r\n /**\r\n * Get the item matching the given key. Tries in-memory cache first, then in the asynchronous\r\n * storage object if item isn't found in-memory.\r\n * @param key\r\n */\r\n async getItem(key: string): Promise {\r\n const item = this.inMemoryCache.getItem(key);\r\n if (!item) {\r\n try {\r\n this.logger.verbose(\r\n \"Queried item not found in in-memory cache, now querying persistent storage.\"\r\n );\r\n return await this.indexedDBCache.getItem(key);\r\n } catch (e) {\r\n this.handleDatabaseAccessError(e);\r\n }\r\n }\r\n return item;\r\n }\r\n\r\n /**\r\n * Sets the item in the in-memory cache and then tries to set it in the asynchronous\r\n * storage object with the given key.\r\n * @param key\r\n * @param value\r\n */\r\n async setItem(key: string, value: T): Promise {\r\n this.inMemoryCache.setItem(key, value);\r\n try {\r\n await this.indexedDBCache.setItem(key, value);\r\n } catch (e) {\r\n this.handleDatabaseAccessError(e);\r\n }\r\n }\r\n\r\n /**\r\n * Removes the item matching the key from the in-memory cache, then tries to remove it from the asynchronous storage object.\r\n * @param key\r\n */\r\n async removeItem(key: string): Promise {\r\n this.inMemoryCache.removeItem(key);\r\n try {\r\n await this.indexedDBCache.removeItem(key);\r\n } catch (e) {\r\n this.handleDatabaseAccessError(e);\r\n }\r\n }\r\n\r\n /**\r\n * Get all the keys from the in-memory cache as an iterable array of strings. If no keys are found, query the keys in the\r\n * asynchronous storage object.\r\n */\r\n async getKeys(): Promise {\r\n const cacheKeys = this.inMemoryCache.getKeys();\r\n if (cacheKeys.length === 0) {\r\n try {\r\n this.logger.verbose(\r\n \"In-memory cache is empty, now querying persistent storage.\"\r\n );\r\n return await this.indexedDBCache.getKeys();\r\n } catch (e) {\r\n this.handleDatabaseAccessError(e);\r\n }\r\n }\r\n return cacheKeys;\r\n }\r\n\r\n /**\r\n * Returns true or false if the given key is present in the cache.\r\n * @param key\r\n */\r\n async containsKey(key: string): Promise {\r\n const containsKey = this.inMemoryCache.containsKey(key);\r\n if (!containsKey) {\r\n try {\r\n this.logger.verbose(\r\n \"Key not found in in-memory cache, now querying persistent storage.\"\r\n );\r\n return await this.indexedDBCache.containsKey(key);\r\n } catch (e) {\r\n this.handleDatabaseAccessError(e);\r\n }\r\n }\r\n return containsKey;\r\n }\r\n\r\n /**\r\n * Clears in-memory Map\r\n */\r\n clearInMemory(): void {\r\n // InMemory cache is a Map instance, clear is straightforward\r\n this.logger.verbose(`Deleting in-memory keystore`);\r\n this.inMemoryCache.clear();\r\n this.logger.verbose(`In-memory keystore deleted`);\r\n }\r\n\r\n /**\r\n * Tries to delete the IndexedDB database\r\n * @returns\r\n */\r\n async clearPersistent(): Promise {\r\n try {\r\n this.logger.verbose(\"Deleting persistent keystore\");\r\n const dbDeleted = await this.indexedDBCache.deleteDatabase();\r\n if (dbDeleted) {\r\n this.logger.verbose(\"Persistent keystore deleted\");\r\n }\r\n\r\n return dbDeleted;\r\n } catch (e) {\r\n this.handleDatabaseAccessError(e);\r\n return false;\r\n }\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n ICrypto,\r\n IPerformanceClient,\r\n JoseHeader,\r\n Logger,\r\n PerformanceEvents,\r\n ShrOptions,\r\n SignedHttpRequest,\r\n SignedHttpRequestParameters,\r\n} from \"@azure/msal-common/browser\";\r\nimport {\r\n base64Encode,\r\n urlEncode,\r\n urlEncodeArr,\r\n} from \"../encode/Base64Encode.js\";\r\nimport { base64Decode } from \"../encode/Base64Decode.js\";\r\nimport * as BrowserCrypto from \"./BrowserCrypto.js\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { AsyncMemoryStorage } from \"../cache/AsyncMemoryStorage.js\";\r\n\r\nexport type CachedKeyPair = {\r\n publicKey: CryptoKey;\r\n privateKey: CryptoKey;\r\n requestMethod?: string;\r\n requestUri?: string;\r\n};\r\n\r\n/**\r\n * This class implements MSAL's crypto interface, which allows it to perform base64 encoding and decoding, generating cryptographically random GUIDs and\r\n * implementing Proof Key for Code Exchange specs for the OAuth Authorization Code Flow using PKCE (rfc here: https://tools.ietf.org/html/rfc7636).\r\n */\r\nexport class CryptoOps implements ICrypto {\r\n private logger: Logger;\r\n\r\n /**\r\n * CryptoOps can be used in contexts outside a PCA instance,\r\n * meaning there won't be a performance manager available.\r\n */\r\n private performanceClient: IPerformanceClient | undefined;\r\n\r\n private static POP_KEY_USAGES: Array = [\"sign\", \"verify\"];\r\n private static EXTRACTABLE: boolean = true;\r\n private cache: AsyncMemoryStorage;\r\n\r\n constructor(\r\n logger: Logger,\r\n performanceClient?: IPerformanceClient,\r\n skipValidateSubtleCrypto?: boolean\r\n ) {\r\n this.logger = logger;\r\n // Browser crypto needs to be validated first before any other classes can be set.\r\n BrowserCrypto.validateCryptoAvailable(\r\n skipValidateSubtleCrypto ?? false\r\n );\r\n this.cache = new AsyncMemoryStorage(this.logger);\r\n this.performanceClient = performanceClient;\r\n }\r\n\r\n /**\r\n * Creates a new random GUID - used to populate state and nonce.\r\n * @returns string (GUID)\r\n */\r\n createNewGuid(): string {\r\n return BrowserCrypto.createNewGuid();\r\n }\r\n\r\n /**\r\n * Encodes input string to base64.\r\n * @param input\r\n */\r\n base64Encode(input: string): string {\r\n return base64Encode(input);\r\n }\r\n\r\n /**\r\n * Decodes input string from base64.\r\n * @param input\r\n */\r\n base64Decode(input: string): string {\r\n return base64Decode(input);\r\n }\r\n\r\n /**\r\n * Encodes input string to base64 URL safe string.\r\n * @param input\r\n */\r\n base64UrlEncode(input: string): string {\r\n return urlEncode(input);\r\n }\r\n\r\n /**\r\n * Stringifies and base64Url encodes input public key\r\n * @param inputKid\r\n * @returns Base64Url encoded public key\r\n */\r\n encodeKid(inputKid: string): string {\r\n return this.base64UrlEncode(JSON.stringify({ kid: inputKid }));\r\n }\r\n\r\n /**\r\n * Generates a keypair, stores it and returns a thumbprint\r\n * @param request\r\n */\r\n async getPublicKeyThumbprint(\r\n request: SignedHttpRequestParameters\r\n ): Promise {\r\n const publicKeyThumbMeasurement =\r\n this.performanceClient?.startMeasurement(\r\n PerformanceEvents.CryptoOptsGetPublicKeyThumbprint,\r\n request.correlationId\r\n );\r\n\r\n // Generate Keypair\r\n const keyPair: CryptoKeyPair = await BrowserCrypto.generateKeyPair(\r\n CryptoOps.EXTRACTABLE,\r\n CryptoOps.POP_KEY_USAGES\r\n );\r\n\r\n // Generate Thumbprint for Public Key\r\n const publicKeyJwk: JsonWebKey = await BrowserCrypto.exportJwk(\r\n keyPair.publicKey\r\n );\r\n\r\n const pubKeyThumprintObj: JsonWebKey = {\r\n e: publicKeyJwk.e,\r\n kty: publicKeyJwk.kty,\r\n n: publicKeyJwk.n,\r\n };\r\n\r\n const publicJwkString: string =\r\n getSortedObjectString(pubKeyThumprintObj);\r\n const publicJwkHash = await this.hashString(publicJwkString);\r\n\r\n // Generate Thumbprint for Private Key\r\n const privateKeyJwk: JsonWebKey = await BrowserCrypto.exportJwk(\r\n keyPair.privateKey\r\n );\r\n // Re-import private key to make it unextractable\r\n const unextractablePrivateKey: CryptoKey =\r\n await BrowserCrypto.importJwk(privateKeyJwk, false, [\"sign\"]);\r\n\r\n // Store Keypair data in keystore\r\n await this.cache.setItem(publicJwkHash, {\r\n privateKey: unextractablePrivateKey,\r\n publicKey: keyPair.publicKey,\r\n requestMethod: request.resourceRequestMethod,\r\n requestUri: request.resourceRequestUri,\r\n });\r\n\r\n if (publicKeyThumbMeasurement) {\r\n publicKeyThumbMeasurement.end({\r\n success: true,\r\n });\r\n }\r\n\r\n return publicJwkHash;\r\n }\r\n\r\n /**\r\n * Removes cryptographic keypair from key store matching the keyId passed in\r\n * @param kid\r\n */\r\n async removeTokenBindingKey(kid: string): Promise {\r\n await this.cache.removeItem(kid);\r\n const keyFound = await this.cache.containsKey(kid);\r\n if (keyFound) {\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.bindingKeyNotRemoved\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Removes all cryptographic keys from IndexedDB storage\r\n */\r\n async clearKeystore(): Promise {\r\n // Delete in-memory keystores\r\n this.cache.clearInMemory();\r\n\r\n /**\r\n * There is only one database, so calling clearPersistent on asymmetric keystore takes care of\r\n * every persistent keystore\r\n */\r\n try {\r\n await this.cache.clearPersistent();\r\n return true;\r\n } catch (e) {\r\n if (e instanceof Error) {\r\n this.logger.error(\r\n `Clearing keystore failed with error: ${e.message}`\r\n );\r\n } else {\r\n this.logger.error(\r\n \"Clearing keystore failed with unknown error\"\r\n );\r\n }\r\n\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Signs the given object as a jwt payload with private key retrieved by given kid.\r\n * @param payload\r\n * @param kid\r\n */\r\n async signJwt(\r\n payload: SignedHttpRequest,\r\n kid: string,\r\n shrOptions?: ShrOptions,\r\n correlationId?: string\r\n ): Promise {\r\n const signJwtMeasurement = this.performanceClient?.startMeasurement(\r\n PerformanceEvents.CryptoOptsSignJwt,\r\n correlationId\r\n );\r\n const cachedKeyPair = await this.cache.getItem(kid);\r\n\r\n if (!cachedKeyPair) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.cryptoKeyNotFound\r\n );\r\n }\r\n\r\n // Get public key as JWK\r\n const publicKeyJwk = await BrowserCrypto.exportJwk(\r\n cachedKeyPair.publicKey\r\n );\r\n const publicKeyJwkString = getSortedObjectString(publicKeyJwk);\r\n // Base64URL encode public key thumbprint with keyId only: BASE64URL({ kid: \"FULL_PUBLIC_KEY_HASH\" })\r\n const encodedKeyIdThumbprint = urlEncode(JSON.stringify({ kid: kid }));\r\n // Generate header\r\n const shrHeader = JoseHeader.getShrHeaderString({\r\n ...shrOptions?.header,\r\n alg: publicKeyJwk.alg,\r\n kid: encodedKeyIdThumbprint,\r\n });\r\n\r\n const encodedShrHeader = urlEncode(shrHeader);\r\n\r\n // Generate payload\r\n payload.cnf = {\r\n jwk: JSON.parse(publicKeyJwkString),\r\n };\r\n const encodedPayload = urlEncode(JSON.stringify(payload));\r\n\r\n // Form token string\r\n const tokenString = `${encodedShrHeader}.${encodedPayload}`;\r\n\r\n // Sign token\r\n const encoder = new TextEncoder();\r\n const tokenBuffer = encoder.encode(tokenString);\r\n const signatureBuffer = await BrowserCrypto.sign(\r\n cachedKeyPair.privateKey,\r\n tokenBuffer\r\n );\r\n const encodedSignature = urlEncodeArr(new Uint8Array(signatureBuffer));\r\n\r\n const signedJwt = `${tokenString}.${encodedSignature}`;\r\n\r\n if (signJwtMeasurement) {\r\n signJwtMeasurement.end({\r\n success: true,\r\n });\r\n }\r\n\r\n return signedJwt;\r\n }\r\n\r\n /**\r\n * Returns the SHA-256 hash of an input string\r\n * @param plainText\r\n */\r\n async hashString(plainText: string): Promise {\r\n return BrowserCrypto.hashString(plainText);\r\n }\r\n}\r\n\r\nfunction getSortedObjectString(obj: object): string {\r\n return JSON.stringify(obj, Object.keys(obj).sort());\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n ClientAuthErrorCodes,\r\n createClientAuthError,\r\n} from \"@azure/msal-common/browser\";\r\nimport { IWindowStorage } from \"./IWindowStorage.js\";\r\n\r\n// Cookie life calculation (hours * minutes * seconds * ms)\r\nconst COOKIE_LIFE_MULTIPLIER = 24 * 60 * 60 * 1000;\r\n\r\nexport const SameSiteOptions = {\r\n Lax: \"Lax\",\r\n None: \"None\",\r\n} as const;\r\nexport type SameSiteOptions =\r\n (typeof SameSiteOptions)[keyof typeof SameSiteOptions];\r\n\r\nexport class CookieStorage implements IWindowStorage {\r\n initialize(): Promise {\r\n return Promise.resolve();\r\n }\r\n\r\n getItem(key: string): string | null {\r\n const name = `${encodeURIComponent(key)}`;\r\n const cookieList = document.cookie.split(\";\");\r\n for (let i = 0; i < cookieList.length; i++) {\r\n const cookie = cookieList[i];\r\n const [key, ...rest] = decodeURIComponent(cookie).trim().split(\"=\");\r\n const value = rest.join(\"=\");\r\n\r\n if (key === name) {\r\n return value;\r\n }\r\n }\r\n return \"\";\r\n }\r\n\r\n getUserData(): string | null {\r\n throw createClientAuthError(ClientAuthErrorCodes.methodNotImplemented);\r\n }\r\n\r\n setItem(\r\n key: string,\r\n value: string,\r\n cookieLifeDays?: number,\r\n secure: boolean = true,\r\n sameSite: SameSiteOptions = SameSiteOptions.Lax\r\n ): void {\r\n let cookieStr = `${encodeURIComponent(key)}=${encodeURIComponent(\r\n value\r\n )};path=/;SameSite=${sameSite};`;\r\n\r\n if (cookieLifeDays) {\r\n const expireTime = getCookieExpirationTime(cookieLifeDays);\r\n cookieStr += `expires=${expireTime};`;\r\n }\r\n\r\n if (secure || sameSite === SameSiteOptions.None) {\r\n // SameSite None requires Secure flag\r\n cookieStr += \"Secure;\";\r\n }\r\n\r\n document.cookie = cookieStr;\r\n }\r\n\r\n async setUserData(): Promise {\r\n return Promise.reject(\r\n createClientAuthError(ClientAuthErrorCodes.methodNotImplemented)\r\n );\r\n }\r\n\r\n removeItem(key: string): void {\r\n // Setting expiration to -1 removes it\r\n this.setItem(key, \"\", -1);\r\n }\r\n\r\n getKeys(): string[] {\r\n const cookieList = document.cookie.split(\";\");\r\n const keys: Array = [];\r\n cookieList.forEach((cookie) => {\r\n const cookieParts = decodeURIComponent(cookie).trim().split(\"=\");\r\n keys.push(cookieParts[0]);\r\n });\r\n\r\n return keys;\r\n }\r\n\r\n containsKey(key: string): boolean {\r\n return this.getKeys().includes(key);\r\n }\r\n\r\n decryptData(): Promise {\r\n // Cookie storage does not support encryption, so this method is a no-op\r\n return Promise.resolve(null);\r\n }\r\n}\r\n\r\n/**\r\n * Get cookie expiration time\r\n * @param cookieLifeDays\r\n */\r\nexport function getCookieExpirationTime(cookieLifeDays: number): string {\r\n const today = new Date();\r\n const expr = new Date(\r\n today.getTime() + cookieLifeDays * COOKIE_LIFE_MULTIPLIER\r\n );\r\n return expr.toUTCString();\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { TokenKeys } from \"@azure/msal-common/browser\";\r\nimport { IWindowStorage } from \"./IWindowStorage.js\";\r\nimport * as CacheKeys from \"./CacheKeys.js\";\r\n\r\n/**\r\n * Returns a list of cache keys for all known accounts\r\n * @param storage\r\n * @returns\r\n */\r\nexport function getAccountKeys(\r\n storage: IWindowStorage,\r\n schemaVersion?: number\r\n): Array {\r\n const accountKeys = storage.getItem(\r\n CacheKeys.getAccountKeysCacheKey(schemaVersion)\r\n );\r\n if (accountKeys) {\r\n return JSON.parse(accountKeys);\r\n }\r\n\r\n return [];\r\n}\r\n\r\n/**\r\n * Returns a list of cache keys for all known tokens\r\n * @param clientId\r\n * @param storage\r\n * @returns\r\n */\r\nexport function getTokenKeys(\r\n clientId: string,\r\n storage: IWindowStorage,\r\n schemaVersion?: number\r\n): TokenKeys {\r\n const item = storage.getItem(\r\n CacheKeys.getTokenKeysCacheKey(clientId, schemaVersion)\r\n );\r\n if (item) {\r\n const tokenKeys = JSON.parse(item);\r\n if (\r\n tokenKeys &&\r\n tokenKeys.hasOwnProperty(\"idToken\") &&\r\n tokenKeys.hasOwnProperty(\"accessToken\") &&\r\n tokenKeys.hasOwnProperty(\"refreshToken\")\r\n ) {\r\n return tokenKeys as TokenKeys;\r\n }\r\n }\r\n\r\n return {\r\n idToken: [],\r\n accessToken: [],\r\n refreshToken: [],\r\n };\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport type EncryptedData = {\r\n id: string;\r\n nonce: string;\r\n data: string;\r\n lastUpdatedAt: string;\r\n};\r\n\r\nexport function isEncrypted(data: object): data is EncryptedData {\r\n return (\r\n data.hasOwnProperty(\"id\") &&\r\n data.hasOwnProperty(\"nonce\") &&\r\n data.hasOwnProperty(\"data\")\r\n );\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n TokenKeys,\r\n IPerformanceClient,\r\n invokeAsync,\r\n PerformanceEvents,\r\n Logger,\r\n invoke,\r\n} from \"@azure/msal-common/browser\";\r\nimport {\r\n createNewGuid,\r\n decrypt,\r\n encrypt,\r\n generateBaseKey,\r\n generateHKDF,\r\n} from \"../crypto/BrowserCrypto.js\";\r\nimport { base64DecToArr } from \"../encode/Base64Decode.js\";\r\nimport { urlEncodeArr } from \"../encode/Base64Encode.js\";\r\nimport {\r\n BrowserAuthErrorCodes,\r\n createBrowserAuthError,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport {\r\n BrowserConfigurationAuthErrorCodes,\r\n createBrowserConfigurationAuthError,\r\n} from \"../error/BrowserConfigurationAuthError.js\";\r\nimport { CookieStorage, SameSiteOptions } from \"./CookieStorage.js\";\r\nimport { IWindowStorage } from \"./IWindowStorage.js\";\r\nimport { MemoryStorage } from \"./MemoryStorage.js\";\r\nimport { getAccountKeys, getTokenKeys } from \"./CacheHelpers.js\";\r\nimport * as CacheKeys from \"./CacheKeys.js\";\r\nimport { EncryptedData, isEncrypted } from \"./EncryptedData.js\";\r\n\r\nconst ENCRYPTION_KEY = \"msal.cache.encryption\";\r\nconst BROADCAST_CHANNEL_NAME = \"msal.broadcast.cache\";\r\n\r\ntype EncryptionCookie = {\r\n id: string;\r\n key: CryptoKey;\r\n};\r\n\r\nexport class LocalStorage implements IWindowStorage {\r\n private clientId: string;\r\n private initialized: boolean;\r\n private memoryStorage: MemoryStorage;\r\n private performanceClient: IPerformanceClient;\r\n private logger: Logger;\r\n private encryptionCookie?: EncryptionCookie;\r\n private broadcast: BroadcastChannel;\r\n\r\n constructor(\r\n clientId: string,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient\r\n ) {\r\n if (!window.localStorage) {\r\n throw createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.storageNotSupported\r\n );\r\n }\r\n this.memoryStorage = new MemoryStorage();\r\n this.initialized = false;\r\n this.clientId = clientId;\r\n this.logger = logger;\r\n this.performanceClient = performanceClient;\r\n this.broadcast = new BroadcastChannel(BROADCAST_CHANNEL_NAME);\r\n }\r\n\r\n async initialize(correlationId: string): Promise {\r\n const cookies = new CookieStorage();\r\n const cookieString = cookies.getItem(ENCRYPTION_KEY);\r\n let parsedCookie = { key: \"\", id: \"\" };\r\n if (cookieString) {\r\n try {\r\n parsedCookie = JSON.parse(cookieString);\r\n } catch (e) {}\r\n }\r\n if (parsedCookie.key && parsedCookie.id) {\r\n // Encryption key already exists, import\r\n const baseKey = invoke(\r\n base64DecToArr,\r\n PerformanceEvents.Base64Decode,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(parsedCookie.key);\r\n this.encryptionCookie = {\r\n id: parsedCookie.id,\r\n key: await invokeAsync(\r\n generateHKDF,\r\n PerformanceEvents.GenerateHKDF,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(baseKey),\r\n };\r\n } else {\r\n // Encryption key doesn't exist or is invalid, generate a new one\r\n const id = createNewGuid();\r\n const baseKey = await invokeAsync(\r\n generateBaseKey,\r\n PerformanceEvents.GenerateBaseKey,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )();\r\n const keyStr = invoke(\r\n urlEncodeArr,\r\n PerformanceEvents.UrlEncodeArr,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(new Uint8Array(baseKey));\r\n this.encryptionCookie = {\r\n id: id,\r\n key: await invokeAsync(\r\n generateHKDF,\r\n PerformanceEvents.GenerateHKDF,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(baseKey),\r\n };\r\n\r\n const cookieData = {\r\n id: id,\r\n key: keyStr,\r\n };\r\n\r\n cookies.setItem(\r\n ENCRYPTION_KEY,\r\n JSON.stringify(cookieData),\r\n 0, // Expiration - 0 means cookie will be cleared at the end of the browser session\r\n true, // Secure flag\r\n SameSiteOptions.None // SameSite must be None to support iframed apps\r\n );\r\n }\r\n\r\n await invokeAsync(\r\n this.importExistingCache.bind(this),\r\n PerformanceEvents.ImportExistingCache,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(correlationId);\r\n\r\n // Register listener for cache updates in other tabs\r\n this.broadcast.addEventListener(\"message\", this.updateCache.bind(this));\r\n\r\n this.initialized = true;\r\n }\r\n\r\n getItem(key: string): string | null {\r\n return window.localStorage.getItem(key);\r\n }\r\n\r\n getUserData(key: string): string | null {\r\n if (!this.initialized) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.uninitializedPublicClientApplication\r\n );\r\n }\r\n return this.memoryStorage.getItem(key);\r\n }\r\n\r\n async decryptData(\r\n key: string,\r\n data: EncryptedData,\r\n correlationId: string\r\n ): Promise {\r\n if (!this.initialized || !this.encryptionCookie) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.uninitializedPublicClientApplication\r\n );\r\n }\r\n\r\n if (data.id !== this.encryptionCookie.id) {\r\n // Data was encrypted with a different key. It must be removed because it is from a previous session.\r\n this.performanceClient.incrementFields(\r\n { encryptedCacheExpiredCount: 1 },\r\n correlationId\r\n );\r\n return null;\r\n }\r\n\r\n const decryptedData = await invokeAsync(\r\n decrypt,\r\n PerformanceEvents.Decrypt,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n this.encryptionCookie.key,\r\n data.nonce,\r\n this.getContext(key),\r\n data.data\r\n );\r\n\r\n if (!decryptedData) {\r\n return null;\r\n }\r\n\r\n try {\r\n return JSON.parse(decryptedData);\r\n } catch (e) {\r\n this.performanceClient.incrementFields(\r\n { encryptedCacheCorruptionCount: 1 },\r\n correlationId\r\n );\r\n return null;\r\n }\r\n }\r\n\r\n setItem(key: string, value: string): void {\r\n window.localStorage.setItem(key, value);\r\n }\r\n\r\n async setUserData(\r\n key: string,\r\n value: string,\r\n correlationId: string,\r\n timestamp: string\r\n ): Promise {\r\n if (!this.initialized || !this.encryptionCookie) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.uninitializedPublicClientApplication\r\n );\r\n }\r\n\r\n const { data, nonce } = await invokeAsync(\r\n encrypt,\r\n PerformanceEvents.Encrypt,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(this.encryptionCookie.key, value, this.getContext(key));\r\n const encryptedData: EncryptedData = {\r\n id: this.encryptionCookie.id,\r\n nonce: nonce,\r\n data: data,\r\n lastUpdatedAt: timestamp,\r\n };\r\n\r\n this.memoryStorage.setItem(key, value);\r\n this.setItem(key, JSON.stringify(encryptedData));\r\n\r\n // Notify other frames to update their in-memory cache\r\n this.broadcast.postMessage({\r\n key: key,\r\n value: value,\r\n context: this.getContext(key),\r\n });\r\n }\r\n\r\n removeItem(key: string): void {\r\n if (this.memoryStorage.containsKey(key)) {\r\n this.memoryStorage.removeItem(key);\r\n this.broadcast.postMessage({\r\n key: key,\r\n value: null,\r\n context: this.getContext(key),\r\n });\r\n }\r\n window.localStorage.removeItem(key);\r\n }\r\n\r\n getKeys(): string[] {\r\n return Object.keys(window.localStorage);\r\n }\r\n\r\n containsKey(key: string): boolean {\r\n return window.localStorage.hasOwnProperty(key);\r\n }\r\n\r\n /**\r\n * Removes all known MSAL keys from the cache\r\n */\r\n clear(): void {\r\n // Removes all remaining MSAL cache items\r\n this.memoryStorage.clear();\r\n\r\n const accountKeys = getAccountKeys(this);\r\n accountKeys.forEach((key) => this.removeItem(key));\r\n const tokenKeys = getTokenKeys(this.clientId, this);\r\n tokenKeys.idToken.forEach((key) => this.removeItem(key));\r\n tokenKeys.accessToken.forEach((key) => this.removeItem(key));\r\n tokenKeys.refreshToken.forEach((key) => this.removeItem(key));\r\n\r\n // Clean up anything left\r\n this.getKeys().forEach((cacheKey: string) => {\r\n if (\r\n cacheKey.startsWith(CacheKeys.PREFIX) ||\r\n cacheKey.indexOf(this.clientId) !== -1\r\n ) {\r\n this.removeItem(cacheKey);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Helper to decrypt all known MSAL keys in localStorage and save them to inMemory storage\r\n * @returns\r\n */\r\n private async importExistingCache(correlationId: string): Promise {\r\n if (!this.encryptionCookie) {\r\n return;\r\n }\r\n\r\n let accountKeys = getAccountKeys(this);\r\n accountKeys = await this.importArray(accountKeys, correlationId);\r\n // Write valid account keys back to map\r\n if (accountKeys.length) {\r\n this.setItem(\r\n CacheKeys.getAccountKeysCacheKey(),\r\n JSON.stringify(accountKeys)\r\n );\r\n } else {\r\n this.removeItem(CacheKeys.getAccountKeysCacheKey());\r\n }\r\n\r\n const tokenKeys: TokenKeys = getTokenKeys(this.clientId, this);\r\n tokenKeys.idToken = await this.importArray(\r\n tokenKeys.idToken,\r\n correlationId\r\n );\r\n tokenKeys.accessToken = await this.importArray(\r\n tokenKeys.accessToken,\r\n correlationId\r\n );\r\n tokenKeys.refreshToken = await this.importArray(\r\n tokenKeys.refreshToken,\r\n correlationId\r\n );\r\n // Write valid token keys back to map\r\n if (\r\n tokenKeys.idToken.length ||\r\n tokenKeys.accessToken.length ||\r\n tokenKeys.refreshToken.length\r\n ) {\r\n this.setItem(\r\n CacheKeys.getTokenKeysCacheKey(this.clientId),\r\n JSON.stringify(tokenKeys)\r\n );\r\n } else {\r\n this.removeItem(CacheKeys.getTokenKeysCacheKey(this.clientId));\r\n }\r\n }\r\n\r\n /**\r\n * Helper to decrypt and save cache entries\r\n * @param key\r\n * @returns\r\n */\r\n private async getItemFromEncryptedCache(\r\n key: string,\r\n correlationId: string\r\n ): Promise {\r\n if (!this.encryptionCookie) {\r\n return null;\r\n }\r\n\r\n const rawCache = this.getItem(key);\r\n if (!rawCache) {\r\n return null;\r\n }\r\n\r\n let encObj: EncryptedData;\r\n try {\r\n encObj = JSON.parse(rawCache);\r\n } catch (e) {\r\n // Not a valid encrypted object, remove\r\n return null;\r\n }\r\n\r\n if (!isEncrypted(encObj)) {\r\n // Data is not encrypted\r\n this.performanceClient.incrementFields(\r\n { unencryptedCacheCount: 1 },\r\n correlationId\r\n );\r\n return encObj;\r\n }\r\n\r\n if (encObj.id !== this.encryptionCookie.id) {\r\n // Data was encrypted with a different key. It must be removed because it is from a previous session.\r\n this.performanceClient.incrementFields(\r\n { encryptedCacheExpiredCount: 1 },\r\n correlationId\r\n );\r\n return null;\r\n }\r\n\r\n return invokeAsync(\r\n decrypt,\r\n PerformanceEvents.Decrypt,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n this.encryptionCookie.key,\r\n encObj.nonce,\r\n this.getContext(key),\r\n encObj.data\r\n );\r\n }\r\n\r\n /**\r\n * Helper to decrypt and save an array of cache keys\r\n * @param arr\r\n * @returns Array of keys successfully imported\r\n */\r\n private async importArray(\r\n arr: Array,\r\n correlationId: string\r\n ): Promise> {\r\n const importedArr: Array = [];\r\n const promiseArr: Array> = [];\r\n arr.forEach((key) => {\r\n const promise = this.getItemFromEncryptedCache(\r\n key,\r\n correlationId\r\n ).then((value) => {\r\n if (value) {\r\n this.memoryStorage.setItem(key, value);\r\n importedArr.push(key);\r\n } else {\r\n // If value is empty, unencrypted or expired remove\r\n this.removeItem(key);\r\n }\r\n });\r\n promiseArr.push(promise);\r\n });\r\n\r\n await Promise.all(promiseArr);\r\n return importedArr;\r\n }\r\n\r\n /**\r\n * Gets encryption context for a given cache entry. This is clientId for app specific entries, empty string for shared entries\r\n * @param key\r\n * @returns\r\n */\r\n private getContext(key: string): string {\r\n let context = \"\";\r\n if (key.includes(this.clientId)) {\r\n context = this.clientId; // Used to bind encryption key to this appId\r\n }\r\n\r\n return context;\r\n }\r\n\r\n private updateCache(event: MessageEvent): void {\r\n this.logger.trace(\"Updating internal cache from broadcast event\");\r\n const perfMeasurement = this.performanceClient.startMeasurement(\r\n PerformanceEvents.LocalStorageUpdated\r\n );\r\n perfMeasurement.add({ isBackground: true });\r\n\r\n const { key, value, context } = event.data;\r\n if (!key) {\r\n this.logger.error(\"Broadcast event missing key\");\r\n perfMeasurement.end({ success: false, errorCode: \"noKey\" });\r\n return;\r\n }\r\n\r\n if (context && context !== this.clientId) {\r\n this.logger.trace(\r\n `Ignoring broadcast event from clientId: ${context}`\r\n );\r\n perfMeasurement.end({\r\n success: false,\r\n errorCode: \"contextMismatch\",\r\n });\r\n return;\r\n }\r\n\r\n if (!value) {\r\n this.memoryStorage.removeItem(key);\r\n this.logger.verbose(\"Removed item from internal cache\");\r\n } else {\r\n this.memoryStorage.setItem(key, value);\r\n this.logger.verbose(\"Updated item in internal cache\");\r\n }\r\n perfMeasurement.end({ success: true });\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n BrowserConfigurationAuthErrorCodes,\r\n createBrowserConfigurationAuthError,\r\n} from \"../error/BrowserConfigurationAuthError.js\";\r\nimport { IWindowStorage } from \"./IWindowStorage.js\";\r\n\r\nexport class SessionStorage implements IWindowStorage {\r\n constructor() {\r\n if (!window.sessionStorage) {\r\n throw createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.storageNotSupported\r\n );\r\n }\r\n }\r\n\r\n async initialize(): Promise {\r\n // Session storage does not require initialization\r\n }\r\n\r\n getItem(key: string): string | null {\r\n return window.sessionStorage.getItem(key);\r\n }\r\n\r\n getUserData(key: string): string | null {\r\n return this.getItem(key);\r\n }\r\n\r\n setItem(key: string, value: string): void {\r\n window.sessionStorage.setItem(key, value);\r\n }\r\n\r\n async setUserData(key: string, value: string): Promise {\r\n this.setItem(key, value);\r\n }\r\n\r\n removeItem(key: string): void {\r\n window.sessionStorage.removeItem(key);\r\n }\r\n\r\n getKeys(): string[] {\r\n return Object.keys(window.sessionStorage);\r\n }\r\n\r\n containsKey(key: string): boolean {\r\n return window.sessionStorage.hasOwnProperty(key);\r\n }\r\n\r\n decryptData(): Promise {\r\n // Session storage does not support encryption, so this method is a no-op\r\n return Promise.resolve(null);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport const EventType = {\r\n INITIALIZE_START: \"msal:initializeStart\",\r\n INITIALIZE_END: \"msal:initializeEnd\",\r\n ACCOUNT_ADDED: \"msal:accountAdded\",\r\n ACCOUNT_REMOVED: \"msal:accountRemoved\",\r\n ACTIVE_ACCOUNT_CHANGED: \"msal:activeAccountChanged\",\r\n LOGIN_START: \"msal:loginStart\",\r\n LOGIN_SUCCESS: \"msal:loginSuccess\",\r\n LOGIN_FAILURE: \"msal:loginFailure\",\r\n ACQUIRE_TOKEN_START: \"msal:acquireTokenStart\",\r\n ACQUIRE_TOKEN_SUCCESS: \"msal:acquireTokenSuccess\",\r\n ACQUIRE_TOKEN_FAILURE: \"msal:acquireTokenFailure\",\r\n ACQUIRE_TOKEN_NETWORK_START: \"msal:acquireTokenFromNetworkStart\",\r\n SSO_SILENT_START: \"msal:ssoSilentStart\",\r\n SSO_SILENT_SUCCESS: \"msal:ssoSilentSuccess\",\r\n SSO_SILENT_FAILURE: \"msal:ssoSilentFailure\",\r\n ACQUIRE_TOKEN_BY_CODE_START: \"msal:acquireTokenByCodeStart\",\r\n ACQUIRE_TOKEN_BY_CODE_SUCCESS: \"msal:acquireTokenByCodeSuccess\",\r\n ACQUIRE_TOKEN_BY_CODE_FAILURE: \"msal:acquireTokenByCodeFailure\",\r\n HANDLE_REDIRECT_START: \"msal:handleRedirectStart\",\r\n HANDLE_REDIRECT_END: \"msal:handleRedirectEnd\",\r\n POPUP_OPENED: \"msal:popupOpened\",\r\n LOGOUT_START: \"msal:logoutStart\",\r\n LOGOUT_SUCCESS: \"msal:logoutSuccess\",\r\n LOGOUT_FAILURE: \"msal:logoutFailure\",\r\n LOGOUT_END: \"msal:logoutEnd\",\r\n RESTORE_FROM_BFCACHE: \"msal:restoreFromBFCache\",\r\n BROKER_CONNECTION_ESTABLISHED: \"msal:brokerConnectionEstablished\",\r\n} as const;\r\nexport type EventType = (typeof EventType)[keyof typeof EventType];\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n/**\r\n * Utility function to remove an element from an array in place.\r\n * @param array - The array from which to remove the element.\r\n * @param element - The element to remove from the array.\r\n */\r\nexport function removeElementFromArray(\r\n array: Array,\r\n element: string\r\n): void {\r\n const index = array.indexOf(element);\r\n if (index > -1) {\r\n array.splice(index, 1);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n AccessTokenEntity,\r\n AccountEntity,\r\n AccountInfo,\r\n ActiveAccountFilters,\r\n AppMetadataEntity,\r\n AuthenticationScheme,\r\n AuthorityMetadataEntity,\r\n CacheError,\r\n CacheErrorCodes,\r\n CacheHelpers,\r\n CacheManager,\r\n CacheRecord,\r\n CommonAuthorizationUrlRequest,\r\n Constants,\r\n createCacheError,\r\n DEFAULT_CRYPTO_IMPLEMENTATION,\r\n ICrypto,\r\n IdTokenEntity,\r\n invokeAsync,\r\n IPerformanceClient,\r\n Logger,\r\n PerformanceEvents,\r\n PersistentCacheKeys,\r\n RefreshTokenEntity,\r\n ServerTelemetryEntity,\r\n StaticAuthorityOptions,\r\n StoreInCache,\r\n StringUtils,\r\n ThrottlingEntity,\r\n TimeUtils,\r\n TokenKeys,\r\n CredentialEntity,\r\n CredentialType,\r\n DEFAULT_TOKEN_RENEWAL_OFFSET_SEC,\r\n} from \"@azure/msal-common/browser\";\r\nimport { CacheOptions } from \"../config/Configuration.js\";\r\nimport {\r\n BrowserAuthErrorCodes,\r\n createBrowserAuthError,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport {\r\n BrowserCacheLocation,\r\n InMemoryCacheKeys,\r\n INTERACTION_TYPE,\r\n TemporaryCacheKeys,\r\n} from \"../utils/BrowserConstants.js\";\r\nimport * as CacheKeys from \"./CacheKeys.js\";\r\nimport { LocalStorage } from \"./LocalStorage.js\";\r\nimport { SessionStorage } from \"./SessionStorage.js\";\r\nimport { MemoryStorage } from \"./MemoryStorage.js\";\r\nimport { IWindowStorage } from \"./IWindowStorage.js\";\r\nimport { PlatformAuthRequest } from \"../broker/nativeBroker/PlatformAuthRequest.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { SilentRequest } from \"../request/SilentRequest.js\";\r\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\r\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\r\nimport { PopupRequest } from \"../request/PopupRequest.js\";\r\nimport { base64Decode } from \"../encode/Base64Decode.js\";\r\nimport { base64Encode } from \"../encode/Base64Encode.js\";\r\nimport { CookieStorage } from \"./CookieStorage.js\";\r\nimport { getAccountKeys, getTokenKeys } from \"./CacheHelpers.js\";\r\nimport { EventType } from \"../event/EventType.js\";\r\nimport { EventHandler } from \"../event/EventHandler.js\";\r\nimport { clearHash } from \"../utils/BrowserUtils.js\";\r\nimport { version } from \"../packageMetadata.js\";\r\nimport { removeElementFromArray } from \"../utils/Helpers.js\";\r\nimport { EncryptedData, isEncrypted } from \"./EncryptedData.js\";\r\n\r\n/**\r\n * This class implements the cache storage interface for MSAL through browser local or session storage.\r\n * Cookies are only used if storeAuthStateInCookie is true, and are only used for\r\n * parameters such as state and nonce, generally.\r\n */\r\nexport class BrowserCacheManager extends CacheManager {\r\n // Cache configuration, either set by user or default values.\r\n protected cacheConfig: Required;\r\n // Window storage object (either local or sessionStorage)\r\n protected browserStorage: IWindowStorage;\r\n // Internal in-memory storage object used for data used by msal that does not need to persist across page loads\r\n protected internalStorage: MemoryStorage;\r\n // Temporary cache\r\n protected temporaryCacheStorage: IWindowStorage;\r\n // Cookie storage\r\n protected cookieStorage: CookieStorage;\r\n // Logger instance\r\n protected logger: Logger;\r\n // Event Handler\r\n private eventHandler: EventHandler;\r\n\r\n constructor(\r\n clientId: string,\r\n cacheConfig: Required,\r\n cryptoImpl: ICrypto,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient,\r\n eventHandler: EventHandler,\r\n staticAuthorityOptions?: StaticAuthorityOptions\r\n ) {\r\n super(\r\n clientId,\r\n cryptoImpl,\r\n logger,\r\n performanceClient,\r\n staticAuthorityOptions\r\n );\r\n this.cacheConfig = cacheConfig;\r\n this.logger = logger;\r\n this.internalStorage = new MemoryStorage();\r\n this.browserStorage = getStorageImplementation(\r\n clientId,\r\n cacheConfig.cacheLocation,\r\n logger,\r\n performanceClient\r\n );\r\n this.temporaryCacheStorage = getStorageImplementation(\r\n clientId,\r\n cacheConfig.temporaryCacheLocation,\r\n logger,\r\n performanceClient\r\n );\r\n this.cookieStorage = new CookieStorage();\r\n this.eventHandler = eventHandler;\r\n }\r\n\r\n async initialize(correlationId: string): Promise {\r\n this.performanceClient.addFields(\r\n {\r\n cacheLocation: this.cacheConfig.cacheLocation,\r\n cacheRetentionDays: this.cacheConfig.cacheRetentionDays,\r\n },\r\n correlationId\r\n );\r\n await this.browserStorage.initialize(correlationId);\r\n await this.migrateExistingCache(correlationId);\r\n this.trackVersionChanges(correlationId);\r\n }\r\n\r\n /**\r\n * Migrates any existing cache data from previous versions of MSAL.js into the current cache structure.\r\n */\r\n async migrateExistingCache(correlationId: string): Promise {\r\n const accountKeys0 = getAccountKeys(this.browserStorage, 0);\r\n const tokenKeys0 = getTokenKeys(this.clientId, this.browserStorage, 0);\r\n this.performanceClient.addFields(\r\n {\r\n oldAccountCount: accountKeys0.length,\r\n oldAccessCount: tokenKeys0.accessToken.length,\r\n oldIdCount: tokenKeys0.idToken.length,\r\n oldRefreshCount: tokenKeys0.refreshToken.length,\r\n },\r\n correlationId\r\n );\r\n\r\n const accountKeys1 = getAccountKeys(this.browserStorage, 1);\r\n const tokenKeys1 = getTokenKeys(this.clientId, this.browserStorage, 1);\r\n this.performanceClient.addFields(\r\n {\r\n currAccountCount: accountKeys1.length,\r\n currAccessCount: tokenKeys1.accessToken.length,\r\n currIdCount: tokenKeys1.idToken.length,\r\n currRefreshCount: tokenKeys1.refreshToken.length,\r\n },\r\n correlationId\r\n );\r\n\r\n await Promise.all([\r\n this.updateV0ToCurrent(\r\n CacheKeys.ACCOUNT_SCHEMA_VERSION,\r\n accountKeys0,\r\n accountKeys1,\r\n correlationId\r\n ),\r\n this.updateV0ToCurrent(\r\n CacheKeys.CREDENTIAL_SCHEMA_VERSION,\r\n tokenKeys0.idToken,\r\n tokenKeys1.idToken,\r\n correlationId\r\n ),\r\n this.updateV0ToCurrent(\r\n CacheKeys.CREDENTIAL_SCHEMA_VERSION,\r\n tokenKeys0.accessToken,\r\n tokenKeys1.accessToken,\r\n correlationId\r\n ),\r\n this.updateV0ToCurrent(\r\n CacheKeys.CREDENTIAL_SCHEMA_VERSION,\r\n tokenKeys0.refreshToken,\r\n tokenKeys1.refreshToken,\r\n correlationId\r\n ),\r\n ]);\r\n\r\n if (accountKeys0.length > 0) {\r\n this.browserStorage.setItem(\r\n CacheKeys.getAccountKeysCacheKey(0),\r\n JSON.stringify(accountKeys0)\r\n );\r\n } else {\r\n this.browserStorage.removeItem(CacheKeys.getAccountKeysCacheKey(0));\r\n }\r\n\r\n if (accountKeys1.length > 0) {\r\n this.browserStorage.setItem(\r\n CacheKeys.getAccountKeysCacheKey(1),\r\n JSON.stringify(accountKeys1)\r\n );\r\n } else {\r\n this.browserStorage.removeItem(CacheKeys.getAccountKeysCacheKey(1));\r\n }\r\n\r\n this.setTokenKeys(tokenKeys0, correlationId, 0);\r\n this.setTokenKeys(tokenKeys1, correlationId, 1);\r\n }\r\n\r\n async updateV0ToCurrent(\r\n currentSchema: number,\r\n v0Keys: Array,\r\n v1Keys: Array,\r\n correlationId: string\r\n ): Promise {\r\n const upgradePromises: Array> = [];\r\n\r\n for (const v0Key of [...v0Keys]) {\r\n const rawV0Value = this.browserStorage.getItem(v0Key);\r\n const parsedV0Value = this.validateAndParseJson(\r\n rawV0Value || \"\"\r\n ) as CredentialEntity | AccountEntity | EncryptedData | null;\r\n\r\n if (!parsedV0Value) {\r\n removeElementFromArray(v0Keys, v0Key);\r\n continue;\r\n }\r\n\r\n if (!parsedV0Value.lastUpdatedAt) {\r\n // Add lastUpdatedAt to the existing v0 entry if it doesnt exist so we know when it's safe to remove it\r\n parsedV0Value.lastUpdatedAt = Date.now().toString();\r\n this.setItem(\r\n v0Key,\r\n JSON.stringify(parsedV0Value),\r\n correlationId\r\n );\r\n }\r\n\r\n const decryptedData = isEncrypted(parsedV0Value)\r\n ? await this.browserStorage.decryptData(\r\n v0Key,\r\n parsedV0Value,\r\n correlationId\r\n )\r\n : parsedV0Value;\r\n let expirationTime;\r\n if (decryptedData) {\r\n if (CacheHelpers.isAccessTokenEntity(decryptedData)) {\r\n expirationTime = decryptedData.expiresOn;\r\n } else if (CacheHelpers.isRefreshTokenEntity(decryptedData)) {\r\n expirationTime = decryptedData.expiresOn;\r\n }\r\n }\r\n if (\r\n !decryptedData ||\r\n TimeUtils.isCacheExpired(\r\n parsedV0Value.lastUpdatedAt,\r\n this.cacheConfig.cacheRetentionDays\r\n ) ||\r\n (expirationTime &&\r\n TimeUtils.isTokenExpired(\r\n expirationTime,\r\n DEFAULT_TOKEN_RENEWAL_OFFSET_SEC\r\n ))\r\n ) {\r\n this.browserStorage.removeItem(v0Key);\r\n removeElementFromArray(v0Keys, v0Key);\r\n this.performanceClient.incrementFields(\r\n { expiredCacheRemovedCount: 1 },\r\n correlationId\r\n );\r\n continue;\r\n }\r\n\r\n if (\r\n this.cacheConfig.cacheLocation !==\r\n BrowserCacheLocation.LocalStorage ||\r\n isEncrypted(parsedV0Value)\r\n ) {\r\n const v1Key = `${CacheKeys.PREFIX}.${currentSchema}${CacheKeys.CACHE_KEY_SEPARATOR}${v0Key}`;\r\n const rawV1Entry = this.browserStorage.getItem(v1Key);\r\n if (!rawV1Entry) {\r\n upgradePromises.push(\r\n this.setUserData(\r\n v1Key,\r\n JSON.stringify(decryptedData),\r\n correlationId,\r\n parsedV0Value.lastUpdatedAt\r\n ).then(() => {\r\n v1Keys.push(v1Key);\r\n this.performanceClient.incrementFields(\r\n { upgradedCacheCount: 1 },\r\n correlationId\r\n );\r\n })\r\n );\r\n continue;\r\n } else {\r\n const parsedV1Entry = this.validateAndParseJson(\r\n rawV1Entry\r\n ) as CredentialEntity | AccountEntity | EncryptedData;\r\n // If the entry already exists but is older than the v0 entry, replace it\r\n if (\r\n Number(parsedV0Value.lastUpdatedAt) >\r\n Number(parsedV1Entry.lastUpdatedAt)\r\n ) {\r\n upgradePromises.push(\r\n this.setUserData(\r\n v1Key,\r\n JSON.stringify(decryptedData),\r\n correlationId,\r\n parsedV0Value.lastUpdatedAt\r\n ).then(() => {\r\n this.performanceClient.incrementFields(\r\n { updatedCacheFromV0Count: 1 },\r\n correlationId\r\n );\r\n })\r\n );\r\n continue;\r\n }\r\n }\r\n }\r\n /*\r\n * Note: If we reach here for unencrypted localStorage data, we continue without migrating\r\n * as we can't migrate unencrypted localStorage data right now since we can't guarantee KMSI=no\r\n */\r\n }\r\n\r\n return Promise.all(upgradePromises);\r\n }\r\n\r\n /**\r\n * Tracks upgrades and downgrades for telemetry and debugging purposes\r\n */\r\n private trackVersionChanges(correlationId: string): void {\r\n const previousVersion = this.browserStorage.getItem(\r\n CacheKeys.VERSION_CACHE_KEY\r\n );\r\n if (previousVersion) {\r\n this.logger.info(\r\n `MSAL.js was last initialized by version: ${previousVersion}`\r\n );\r\n this.performanceClient.addFields(\r\n { previousLibraryVersion: previousVersion },\r\n correlationId\r\n );\r\n }\r\n\r\n if (previousVersion !== version) {\r\n this.setItem(CacheKeys.VERSION_CACHE_KEY, version, correlationId);\r\n }\r\n }\r\n\r\n /**\r\n * Parses passed value as JSON object, JSON.parse() will throw an error.\r\n * @param input\r\n */\r\n protected validateAndParseJson(jsonValue: string): object | null {\r\n if (!jsonValue) {\r\n return null;\r\n }\r\n try {\r\n const parsedJson = JSON.parse(jsonValue);\r\n /**\r\n * There are edge cases in which JSON.parse will successfully parse a non-valid JSON object\r\n * (e.g. JSON.parse will parse an escaped string into an unescaped string), so adding a type check\r\n * of the parsed value is necessary in order to be certain that the string represents a valid JSON object.\r\n *\r\n */\r\n return parsedJson && typeof parsedJson === \"object\"\r\n ? parsedJson\r\n : null;\r\n } catch (error) {\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Helper to setItem in browser storage, with cleanup in case of quota errors\r\n * @param key\r\n * @param value\r\n */\r\n setItem(key: string, value: string, correlationId: string): void {\r\n let tokenKeysV0Count = 0;\r\n let accessTokenKeys: Array = [];\r\n const maxRetries = 20;\r\n for (let i = 0; i <= maxRetries; i++) {\r\n try {\r\n this.browserStorage.setItem(key, value);\r\n if (i > 0) {\r\n // Finally update the token keys array with the tokens removed\r\n if (i <= tokenKeysV0Count) {\r\n this.removeAccessTokenKeys(\r\n accessTokenKeys.slice(0, i),\r\n correlationId,\r\n 0\r\n );\r\n } else {\r\n this.removeAccessTokenKeys(\r\n accessTokenKeys.slice(0, tokenKeysV0Count),\r\n correlationId,\r\n 0\r\n );\r\n this.removeAccessTokenKeys(\r\n accessTokenKeys.slice(tokenKeysV0Count, i),\r\n correlationId\r\n );\r\n }\r\n }\r\n break; // If setItem succeeds, exit the loop\r\n } catch (e) {\r\n const cacheError = createCacheError(e);\r\n if (\r\n cacheError.errorCode ===\r\n CacheErrorCodes.cacheQuotaExceeded &&\r\n i < maxRetries\r\n ) {\r\n if (!accessTokenKeys.length) {\r\n // If we are currently trying to set the token keys, use the value we're trying to set\r\n const tokenKeys0 =\r\n key ===\r\n CacheKeys.getTokenKeysCacheKey(this.clientId, 0)\r\n ? (JSON.parse(value) as TokenKeys).accessToken\r\n : this.getTokenKeys(0).accessToken;\r\n const tokenKeys1 =\r\n key ===\r\n CacheKeys.getTokenKeysCacheKey(this.clientId)\r\n ? (JSON.parse(value) as TokenKeys).accessToken\r\n : this.getTokenKeys().accessToken;\r\n accessTokenKeys = [...tokenKeys0, ...tokenKeys1];\r\n tokenKeysV0Count = tokenKeys0.length;\r\n }\r\n if (accessTokenKeys.length <= i) {\r\n // Nothing to remove, rethrow the error\r\n throw cacheError;\r\n }\r\n // When cache quota is exceeded, start removing access tokens until we can successfully set the item\r\n this.removeAccessToken(\r\n accessTokenKeys[i],\r\n correlationId,\r\n false // Don't save token keys yet, do it at the end\r\n );\r\n } else {\r\n // If the error is not a quota exceeded error, rethrow it\r\n throw cacheError;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Helper to setUserData in browser storage, with cleanup in case of quota errors\r\n * @param key\r\n * @param value\r\n * @param correlationId\r\n */\r\n async setUserData(\r\n key: string,\r\n value: string,\r\n correlationId: string,\r\n timestamp: string\r\n ): Promise {\r\n let tokenKeysV0Count = 0;\r\n let accessTokenKeys: Array = [];\r\n const maxRetries = 20;\r\n for (let i = 0; i <= maxRetries; i++) {\r\n try {\r\n await invokeAsync(\r\n this.browserStorage.setUserData.bind(this.browserStorage),\r\n PerformanceEvents.SetUserData,\r\n this.logger,\r\n this.performanceClient\r\n )(key, value, correlationId, timestamp);\r\n if (i > 0) {\r\n // Finally update the token keys array with the tokens removed\r\n if (i <= tokenKeysV0Count) {\r\n this.removeAccessTokenKeys(\r\n accessTokenKeys.slice(0, i),\r\n correlationId,\r\n 0\r\n );\r\n } else {\r\n this.removeAccessTokenKeys(\r\n accessTokenKeys.slice(0, tokenKeysV0Count),\r\n correlationId,\r\n 0\r\n );\r\n this.removeAccessTokenKeys(\r\n accessTokenKeys.slice(tokenKeysV0Count, i),\r\n correlationId\r\n );\r\n }\r\n }\r\n break; // If setItem succeeds, exit the loop\r\n } catch (e) {\r\n const cacheError = createCacheError(e);\r\n if (\r\n cacheError.errorCode ===\r\n CacheErrorCodes.cacheQuotaExceeded &&\r\n i < maxRetries\r\n ) {\r\n if (!accessTokenKeys.length) {\r\n const tokenKeys0 = this.getTokenKeys(0).accessToken;\r\n const tokenKeys1 = this.getTokenKeys().accessToken;\r\n accessTokenKeys = [...tokenKeys0, ...tokenKeys1];\r\n tokenKeysV0Count = tokenKeys0.length;\r\n }\r\n if (accessTokenKeys.length <= i) {\r\n // Nothing left to remove, rethrow the error\r\n throw cacheError;\r\n }\r\n // When cache quota is exceeded, start removing access tokens until we can successfully set the item\r\n this.removeAccessToken(\r\n accessTokenKeys[i],\r\n correlationId,\r\n false // Don't save token keys yet, do it at the end\r\n );\r\n } else {\r\n // If the error is not a quota exceeded error, rethrow it\r\n throw cacheError;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Reads account from cache, deserializes it into an account entity and returns it.\r\n * If account is not found from the key, returns null and removes key from map.\r\n * @param accountKey\r\n * @returns\r\n */\r\n getAccount(\r\n accountKey: string,\r\n correlationId: string\r\n ): AccountEntity | null {\r\n this.logger.trace(\"BrowserCacheManager.getAccount called\");\r\n const serializedAccount = this.browserStorage.getUserData(accountKey);\r\n if (!serializedAccount) {\r\n this.removeAccountKeyFromMap(accountKey, correlationId);\r\n return null;\r\n }\r\n\r\n const parsedAccount = this.validateAndParseJson(serializedAccount);\r\n if (!parsedAccount || !AccountEntity.isAccountEntity(parsedAccount)) {\r\n return null;\r\n }\r\n\r\n return CacheManager.toObject(\r\n new AccountEntity(),\r\n parsedAccount\r\n );\r\n }\r\n\r\n /**\r\n * set account entity in the platform cache\r\n * @param account\r\n */\r\n async setAccount(\r\n account: AccountEntity,\r\n correlationId: string\r\n ): Promise {\r\n this.logger.trace(\"BrowserCacheManager.setAccount called\");\r\n const key = this.generateAccountKey(account.getAccountInfo());\r\n const timestamp = Date.now().toString();\r\n account.lastUpdatedAt = timestamp;\r\n await this.setUserData(\r\n key,\r\n JSON.stringify(account),\r\n correlationId,\r\n timestamp\r\n );\r\n const wasAdded = this.addAccountKeyToMap(key, correlationId);\r\n\r\n /**\r\n * @deprecated - Remove this in next major version in favor of more consistent LOGIN event\r\n */\r\n if (\r\n this.cacheConfig.cacheLocation ===\r\n BrowserCacheLocation.LocalStorage &&\r\n wasAdded\r\n ) {\r\n this.eventHandler.emitEvent(\r\n EventType.ACCOUNT_ADDED,\r\n undefined,\r\n account.getAccountInfo()\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Returns the array of account keys currently cached\r\n * @returns\r\n */\r\n getAccountKeys(): Array {\r\n return getAccountKeys(this.browserStorage);\r\n }\r\n\r\n /**\r\n * Add a new account to the key map\r\n * @param key\r\n */\r\n addAccountKeyToMap(key: string, correlationId: string): boolean {\r\n this.logger.trace(\"BrowserCacheManager.addAccountKeyToMap called\");\r\n this.logger.tracePii(\r\n `BrowserCacheManager.addAccountKeyToMap called with key: ${key}`\r\n );\r\n const accountKeys = this.getAccountKeys();\r\n if (accountKeys.indexOf(key) === -1) {\r\n // Only add key if it does not already exist in the map\r\n accountKeys.push(key);\r\n this.setItem(\r\n CacheKeys.getAccountKeysCacheKey(),\r\n JSON.stringify(accountKeys),\r\n correlationId\r\n );\r\n this.logger.verbose(\r\n \"BrowserCacheManager.addAccountKeyToMap account key added\"\r\n );\r\n return true;\r\n } else {\r\n this.logger.verbose(\r\n \"BrowserCacheManager.addAccountKeyToMap account key already exists in map\"\r\n );\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Remove an account from the key map\r\n * @param key\r\n */\r\n removeAccountKeyFromMap(key: string, correlationId: string): void {\r\n this.logger.trace(\"BrowserCacheManager.removeAccountKeyFromMap called\");\r\n this.logger.tracePii(\r\n `BrowserCacheManager.removeAccountKeyFromMap called with key: ${key}`\r\n );\r\n const accountKeys = this.getAccountKeys();\r\n const removalIndex = accountKeys.indexOf(key);\r\n if (removalIndex > -1) {\r\n accountKeys.splice(removalIndex, 1);\r\n if (accountKeys.length === 0) {\r\n // If no keys left, remove the map\r\n this.removeItem(CacheKeys.getAccountKeysCacheKey());\r\n return;\r\n } else {\r\n this.setItem(\r\n CacheKeys.getAccountKeysCacheKey(),\r\n JSON.stringify(accountKeys),\r\n correlationId\r\n );\r\n }\r\n this.logger.trace(\r\n \"BrowserCacheManager.removeAccountKeyFromMap account key removed\"\r\n );\r\n } else {\r\n this.logger.trace(\r\n \"BrowserCacheManager.removeAccountKeyFromMap key not found in existing map\"\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Extends inherited removeAccount function to include removal of the account key from the map\r\n * @param key\r\n */\r\n removeAccount(account: AccountInfo, correlationId: string): void {\r\n const activeAccount = this.getActiveAccount(correlationId);\r\n if (\r\n activeAccount?.homeAccountId === account.homeAccountId &&\r\n activeAccount?.environment === account.environment\r\n ) {\r\n this.setActiveAccount(null, correlationId);\r\n }\r\n\r\n super.removeAccount(account, correlationId);\r\n this.removeAccountKeyFromMap(\r\n this.generateAccountKey(account),\r\n correlationId\r\n );\r\n\r\n // Remove all other associated cache items\r\n this.browserStorage.getKeys().forEach((key) => {\r\n if (\r\n key.includes(account.homeAccountId) &&\r\n key.includes(account.environment)\r\n ) {\r\n this.browserStorage.removeItem(key);\r\n }\r\n });\r\n\r\n /**\r\n * @deprecated - Remove this in next major version in favor of more consistent LOGOUT event\r\n */\r\n if (\r\n this.cacheConfig.cacheLocation === BrowserCacheLocation.LocalStorage\r\n ) {\r\n this.eventHandler.emitEvent(\r\n EventType.ACCOUNT_REMOVED,\r\n undefined,\r\n account\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Removes given idToken from the cache and from the key map\r\n * @param key\r\n */\r\n removeIdToken(key: string, correlationId: string): void {\r\n super.removeIdToken(key, correlationId);\r\n const tokenKeys = this.getTokenKeys();\r\n const idRemoval = tokenKeys.idToken.indexOf(key);\r\n if (idRemoval > -1) {\r\n this.logger.info(\"idToken removed from tokenKeys map\");\r\n tokenKeys.idToken.splice(idRemoval, 1);\r\n this.setTokenKeys(tokenKeys, correlationId);\r\n }\r\n }\r\n\r\n /**\r\n * Removes given accessToken from the cache and from the key map\r\n * @param key\r\n */\r\n removeAccessToken(\r\n key: string,\r\n correlationId: string,\r\n updateTokenKeys: boolean = true\r\n ): void {\r\n super.removeAccessToken(key, correlationId);\r\n updateTokenKeys && this.removeAccessTokenKeys([key], correlationId);\r\n }\r\n\r\n /**\r\n * Remove access token key from the key map\r\n * @param key\r\n * @param correlationId\r\n * @param tokenKeys\r\n */\r\n removeAccessTokenKeys(\r\n keys: Array,\r\n correlationId: string,\r\n schemaVersion: number = CacheKeys.CREDENTIAL_SCHEMA_VERSION\r\n ): void {\r\n this.logger.trace(\"removeAccessTokenKey called\");\r\n const tokenKeys = this.getTokenKeys(schemaVersion);\r\n let keysRemoved = 0;\r\n keys.forEach((key) => {\r\n const accessRemoval = tokenKeys.accessToken.indexOf(key);\r\n if (accessRemoval > -1) {\r\n tokenKeys.accessToken.splice(accessRemoval, 1);\r\n keysRemoved++;\r\n }\r\n });\r\n\r\n if (keysRemoved > 0) {\r\n this.logger.info(\r\n `removed ${keysRemoved} accessToken keys from tokenKeys map`\r\n );\r\n this.setTokenKeys(tokenKeys, correlationId, schemaVersion);\r\n return;\r\n }\r\n }\r\n\r\n /**\r\n * Removes given refreshToken from the cache and from the key map\r\n * @param key\r\n */\r\n removeRefreshToken(key: string, correlationId: string): void {\r\n super.removeRefreshToken(key, correlationId);\r\n const tokenKeys = this.getTokenKeys();\r\n const refreshRemoval = tokenKeys.refreshToken.indexOf(key);\r\n if (refreshRemoval > -1) {\r\n this.logger.info(\"refreshToken removed from tokenKeys map\");\r\n tokenKeys.refreshToken.splice(refreshRemoval, 1);\r\n this.setTokenKeys(tokenKeys, correlationId);\r\n }\r\n }\r\n\r\n /**\r\n * Gets the keys for the cached tokens associated with this clientId\r\n * @returns\r\n */\r\n getTokenKeys(\r\n schemaVersion: number = CacheKeys.CREDENTIAL_SCHEMA_VERSION\r\n ): TokenKeys {\r\n return getTokenKeys(this.clientId, this.browserStorage, schemaVersion);\r\n }\r\n\r\n /**\r\n * Stores the token keys in the cache\r\n * @param tokenKeys\r\n * @param correlationId\r\n * @returns\r\n */\r\n setTokenKeys(\r\n tokenKeys: TokenKeys,\r\n correlationId: string,\r\n schemaVersion: number = CacheKeys.CREDENTIAL_SCHEMA_VERSION\r\n ): void {\r\n if (\r\n tokenKeys.idToken.length === 0 &&\r\n tokenKeys.accessToken.length === 0 &&\r\n tokenKeys.refreshToken.length === 0\r\n ) {\r\n // If no keys left, remove the map\r\n this.removeItem(\r\n CacheKeys.getTokenKeysCacheKey(this.clientId, schemaVersion)\r\n );\r\n return;\r\n } else {\r\n this.setItem(\r\n CacheKeys.getTokenKeysCacheKey(this.clientId, schemaVersion),\r\n JSON.stringify(tokenKeys),\r\n correlationId\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * generates idToken entity from a string\r\n * @param idTokenKey\r\n */\r\n getIdTokenCredential(\r\n idTokenKey: string,\r\n correlationId: string\r\n ): IdTokenEntity | null {\r\n const value = this.browserStorage.getUserData(idTokenKey);\r\n if (!value) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getIdTokenCredential: called, no cache hit\"\r\n );\r\n this.removeIdToken(idTokenKey, correlationId);\r\n return null;\r\n }\r\n\r\n const parsedIdToken = this.validateAndParseJson(value);\r\n if (!parsedIdToken || !CacheHelpers.isIdTokenEntity(parsedIdToken)) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getIdTokenCredential: called, no cache hit\"\r\n );\r\n return null;\r\n }\r\n\r\n this.logger.trace(\r\n \"BrowserCacheManager.getIdTokenCredential: cache hit\"\r\n );\r\n return parsedIdToken as IdTokenEntity;\r\n }\r\n\r\n /**\r\n * set IdToken credential to the platform cache\r\n * @param idToken\r\n */\r\n async setIdTokenCredential(\r\n idToken: IdTokenEntity,\r\n correlationId: string\r\n ): Promise {\r\n this.logger.trace(\"BrowserCacheManager.setIdTokenCredential called\");\r\n const idTokenKey = this.generateCredentialKey(idToken);\r\n const timestamp = Date.now().toString();\r\n idToken.lastUpdatedAt = timestamp;\r\n\r\n await this.setUserData(\r\n idTokenKey,\r\n JSON.stringify(idToken),\r\n correlationId,\r\n timestamp\r\n );\r\n\r\n const tokenKeys = this.getTokenKeys();\r\n if (tokenKeys.idToken.indexOf(idTokenKey) === -1) {\r\n this.logger.info(\r\n \"BrowserCacheManager: addTokenKey - idToken added to map\"\r\n );\r\n tokenKeys.idToken.push(idTokenKey);\r\n this.setTokenKeys(tokenKeys, correlationId);\r\n }\r\n }\r\n\r\n /**\r\n * generates accessToken entity from a string\r\n * @param key\r\n */\r\n getAccessTokenCredential(\r\n accessTokenKey: string,\r\n correlationId: string\r\n ): AccessTokenEntity | null {\r\n const value = this.browserStorage.getUserData(accessTokenKey);\r\n if (!value) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getAccessTokenCredential: called, no cache hit\"\r\n );\r\n this.removeAccessTokenKeys([accessTokenKey], correlationId);\r\n return null;\r\n }\r\n const parsedAccessToken = this.validateAndParseJson(value);\r\n if (\r\n !parsedAccessToken ||\r\n !CacheHelpers.isAccessTokenEntity(parsedAccessToken)\r\n ) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getAccessTokenCredential: called, no cache hit\"\r\n );\r\n return null;\r\n }\r\n\r\n this.logger.trace(\r\n \"BrowserCacheManager.getAccessTokenCredential: cache hit\"\r\n );\r\n return parsedAccessToken as AccessTokenEntity;\r\n }\r\n\r\n /**\r\n * set accessToken credential to the platform cache\r\n * @param accessToken\r\n */\r\n async setAccessTokenCredential(\r\n accessToken: AccessTokenEntity,\r\n correlationId: string\r\n ): Promise {\r\n this.logger.trace(\r\n \"BrowserCacheManager.setAccessTokenCredential called\"\r\n );\r\n const accessTokenKey = this.generateCredentialKey(accessToken);\r\n const timestamp = Date.now().toString();\r\n accessToken.lastUpdatedAt = timestamp;\r\n\r\n await this.setUserData(\r\n accessTokenKey,\r\n JSON.stringify(accessToken),\r\n correlationId,\r\n timestamp\r\n );\r\n\r\n const tokenKeys = this.getTokenKeys();\r\n const index = tokenKeys.accessToken.indexOf(accessTokenKey);\r\n if (index !== -1) {\r\n tokenKeys.accessToken.splice(index, 1); // Remove existing key before pushing to the end\r\n }\r\n this.logger.trace(\r\n `access token ${index === -1 ? \"added to\" : \"updated in\"} map`\r\n );\r\n tokenKeys.accessToken.push(accessTokenKey);\r\n this.setTokenKeys(tokenKeys, correlationId);\r\n }\r\n\r\n /**\r\n * generates refreshToken entity from a string\r\n * @param refreshTokenKey\r\n */\r\n getRefreshTokenCredential(\r\n refreshTokenKey: string,\r\n correlationId: string\r\n ): RefreshTokenEntity | null {\r\n const value = this.browserStorage.getUserData(refreshTokenKey);\r\n if (!value) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getRefreshTokenCredential: called, no cache hit\"\r\n );\r\n this.removeRefreshToken(refreshTokenKey, correlationId);\r\n return null;\r\n }\r\n const parsedRefreshToken = this.validateAndParseJson(value);\r\n if (\r\n !parsedRefreshToken ||\r\n !CacheHelpers.isRefreshTokenEntity(parsedRefreshToken)\r\n ) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getRefreshTokenCredential: called, no cache hit\"\r\n );\r\n return null;\r\n }\r\n\r\n this.logger.trace(\r\n \"BrowserCacheManager.getRefreshTokenCredential: cache hit\"\r\n );\r\n return parsedRefreshToken as RefreshTokenEntity;\r\n }\r\n\r\n /**\r\n * set refreshToken credential to the platform cache\r\n * @param refreshToken\r\n */\r\n async setRefreshTokenCredential(\r\n refreshToken: RefreshTokenEntity,\r\n correlationId: string\r\n ): Promise {\r\n this.logger.trace(\r\n \"BrowserCacheManager.setRefreshTokenCredential called\"\r\n );\r\n const refreshTokenKey = this.generateCredentialKey(refreshToken);\r\n const timestamp = Date.now().toString();\r\n refreshToken.lastUpdatedAt = timestamp;\r\n\r\n await this.setUserData(\r\n refreshTokenKey,\r\n JSON.stringify(refreshToken),\r\n correlationId,\r\n timestamp\r\n );\r\n\r\n const tokenKeys = this.getTokenKeys();\r\n if (tokenKeys.refreshToken.indexOf(refreshTokenKey) === -1) {\r\n this.logger.info(\r\n \"BrowserCacheManager: addTokenKey - refreshToken added to map\"\r\n );\r\n tokenKeys.refreshToken.push(refreshTokenKey);\r\n this.setTokenKeys(tokenKeys, correlationId);\r\n }\r\n }\r\n\r\n /**\r\n * fetch appMetadata entity from the platform cache\r\n * @param appMetadataKey\r\n */\r\n getAppMetadata(appMetadataKey: string): AppMetadataEntity | null {\r\n const value = this.browserStorage.getItem(appMetadataKey);\r\n if (!value) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getAppMetadata: called, no cache hit\"\r\n );\r\n return null;\r\n }\r\n\r\n const parsedMetadata = this.validateAndParseJson(value);\r\n if (\r\n !parsedMetadata ||\r\n !CacheHelpers.isAppMetadataEntity(appMetadataKey, parsedMetadata)\r\n ) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getAppMetadata: called, no cache hit\"\r\n );\r\n return null;\r\n }\r\n\r\n this.logger.trace(\"BrowserCacheManager.getAppMetadata: cache hit\");\r\n return parsedMetadata as AppMetadataEntity;\r\n }\r\n\r\n /**\r\n * set appMetadata entity to the platform cache\r\n * @param appMetadata\r\n */\r\n setAppMetadata(\r\n appMetadata: AppMetadataEntity,\r\n correlationId: string\r\n ): void {\r\n this.logger.trace(\"BrowserCacheManager.setAppMetadata called\");\r\n const appMetadataKey = CacheHelpers.generateAppMetadataKey(appMetadata);\r\n this.setItem(\r\n appMetadataKey,\r\n JSON.stringify(appMetadata),\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * fetch server telemetry entity from the platform cache\r\n * @param serverTelemetryKey\r\n */\r\n getServerTelemetry(\r\n serverTelemetryKey: string\r\n ): ServerTelemetryEntity | null {\r\n const value = this.browserStorage.getItem(serverTelemetryKey);\r\n if (!value) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getServerTelemetry: called, no cache hit\"\r\n );\r\n return null;\r\n }\r\n const parsedEntity = this.validateAndParseJson(value);\r\n if (\r\n !parsedEntity ||\r\n !CacheHelpers.isServerTelemetryEntity(\r\n serverTelemetryKey,\r\n parsedEntity\r\n )\r\n ) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getServerTelemetry: called, no cache hit\"\r\n );\r\n return null;\r\n }\r\n\r\n this.logger.trace(\"BrowserCacheManager.getServerTelemetry: cache hit\");\r\n return parsedEntity as ServerTelemetryEntity;\r\n }\r\n\r\n /**\r\n * set server telemetry entity to the platform cache\r\n * @param serverTelemetryKey\r\n * @param serverTelemetry\r\n */\r\n setServerTelemetry(\r\n serverTelemetryKey: string,\r\n serverTelemetry: ServerTelemetryEntity,\r\n correlationId: string\r\n ): void {\r\n this.logger.trace(\"BrowserCacheManager.setServerTelemetry called\");\r\n this.setItem(\r\n serverTelemetryKey,\r\n JSON.stringify(serverTelemetry),\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n *\r\n */\r\n getAuthorityMetadata(key: string): AuthorityMetadataEntity | null {\r\n const value = this.internalStorage.getItem(key);\r\n if (!value) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getAuthorityMetadata: called, no cache hit\"\r\n );\r\n return null;\r\n }\r\n const parsedMetadata = this.validateAndParseJson(value);\r\n if (\r\n parsedMetadata &&\r\n CacheHelpers.isAuthorityMetadataEntity(key, parsedMetadata)\r\n ) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getAuthorityMetadata: cache hit\"\r\n );\r\n return parsedMetadata as AuthorityMetadataEntity;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n *\r\n */\r\n getAuthorityMetadataKeys(): Array {\r\n const allKeys = this.internalStorage.getKeys();\r\n return allKeys.filter((key) => {\r\n return this.isAuthorityMetadata(key);\r\n });\r\n }\r\n\r\n /**\r\n * Sets wrapper metadata in memory\r\n * @param wrapperSKU\r\n * @param wrapperVersion\r\n */\r\n setWrapperMetadata(wrapperSKU: string, wrapperVersion: string): void {\r\n this.internalStorage.setItem(InMemoryCacheKeys.WRAPPER_SKU, wrapperSKU);\r\n this.internalStorage.setItem(\r\n InMemoryCacheKeys.WRAPPER_VER,\r\n wrapperVersion\r\n );\r\n }\r\n\r\n /**\r\n * Returns wrapper metadata from in-memory storage\r\n */\r\n getWrapperMetadata(): [string, string] {\r\n const sku =\r\n this.internalStorage.getItem(InMemoryCacheKeys.WRAPPER_SKU) ||\r\n Constants.EMPTY_STRING;\r\n const version =\r\n this.internalStorage.getItem(InMemoryCacheKeys.WRAPPER_VER) ||\r\n Constants.EMPTY_STRING;\r\n return [sku, version];\r\n }\r\n\r\n /**\r\n *\r\n * @param entity\r\n */\r\n setAuthorityMetadata(key: string, entity: AuthorityMetadataEntity): void {\r\n this.logger.trace(\"BrowserCacheManager.setAuthorityMetadata called\");\r\n this.internalStorage.setItem(key, JSON.stringify(entity));\r\n }\r\n\r\n /**\r\n * Gets the active account\r\n */\r\n getActiveAccount(correlationId: string): AccountInfo | null {\r\n const activeAccountKeyFilters = this.generateCacheKey(\r\n PersistentCacheKeys.ACTIVE_ACCOUNT_FILTERS\r\n );\r\n const activeAccountValueFilters = this.browserStorage.getItem(\r\n activeAccountKeyFilters\r\n );\r\n if (!activeAccountValueFilters) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getActiveAccount: No active account filters found\"\r\n );\r\n return null;\r\n }\r\n const activeAccountValueObj = this.validateAndParseJson(\r\n activeAccountValueFilters\r\n ) as AccountInfo;\r\n if (activeAccountValueObj) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getActiveAccount: Active account filters schema found\"\r\n );\r\n return this.getAccountInfoFilteredBy(\r\n {\r\n homeAccountId: activeAccountValueObj.homeAccountId,\r\n localAccountId: activeAccountValueObj.localAccountId,\r\n tenantId: activeAccountValueObj.tenantId,\r\n },\r\n correlationId\r\n );\r\n }\r\n this.logger.trace(\r\n \"BrowserCacheManager.getActiveAccount: No active account found\"\r\n );\r\n return null;\r\n }\r\n\r\n /**\r\n * Sets the active account's localAccountId in cache\r\n * @param account\r\n */\r\n setActiveAccount(account: AccountInfo | null, correlationId: string): void {\r\n const activeAccountKey = this.generateCacheKey(\r\n PersistentCacheKeys.ACTIVE_ACCOUNT_FILTERS\r\n );\r\n if (account) {\r\n this.logger.verbose(\"setActiveAccount: Active account set\");\r\n const activeAccountValue: ActiveAccountFilters = {\r\n homeAccountId: account.homeAccountId,\r\n localAccountId: account.localAccountId,\r\n tenantId: account.tenantId,\r\n lastUpdatedAt: TimeUtils.nowSeconds().toString(),\r\n };\r\n this.setItem(\r\n activeAccountKey,\r\n JSON.stringify(activeAccountValue),\r\n correlationId\r\n );\r\n } else {\r\n this.logger.verbose(\r\n \"setActiveAccount: No account passed, active account not set\"\r\n );\r\n this.browserStorage.removeItem(activeAccountKey);\r\n }\r\n this.eventHandler.emitEvent(EventType.ACTIVE_ACCOUNT_CHANGED);\r\n }\r\n\r\n /**\r\n * fetch throttling entity from the platform cache\r\n * @param throttlingCacheKey\r\n */\r\n getThrottlingCache(throttlingCacheKey: string): ThrottlingEntity | null {\r\n const value = this.browserStorage.getItem(throttlingCacheKey);\r\n if (!value) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getThrottlingCache: called, no cache hit\"\r\n );\r\n return null;\r\n }\r\n\r\n const parsedThrottlingCache = this.validateAndParseJson(value);\r\n if (\r\n !parsedThrottlingCache ||\r\n !CacheHelpers.isThrottlingEntity(\r\n throttlingCacheKey,\r\n parsedThrottlingCache\r\n )\r\n ) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getThrottlingCache: called, no cache hit\"\r\n );\r\n return null;\r\n }\r\n\r\n this.logger.trace(\"BrowserCacheManager.getThrottlingCache: cache hit\");\r\n return parsedThrottlingCache as ThrottlingEntity;\r\n }\r\n\r\n /**\r\n * set throttling entity to the platform cache\r\n * @param throttlingCacheKey\r\n * @param throttlingCache\r\n */\r\n setThrottlingCache(\r\n throttlingCacheKey: string,\r\n throttlingCache: ThrottlingEntity,\r\n correlationId: string\r\n ): void {\r\n this.logger.trace(\"BrowserCacheManager.setThrottlingCache called\");\r\n this.setItem(\r\n throttlingCacheKey,\r\n JSON.stringify(throttlingCache),\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Gets cache item with given key.\r\n * Will retrieve from cookies if storeAuthStateInCookie is set to true.\r\n * @param key\r\n */\r\n getTemporaryCache(cacheKey: string, generateKey?: boolean): string | null {\r\n const key = generateKey ? this.generateCacheKey(cacheKey) : cacheKey;\r\n if (this.cacheConfig.storeAuthStateInCookie) {\r\n const itemCookie = this.cookieStorage.getItem(key);\r\n if (itemCookie) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getTemporaryCache: storeAuthStateInCookies set to true, retrieving from cookies\"\r\n );\r\n return itemCookie;\r\n }\r\n }\r\n\r\n const value = this.temporaryCacheStorage.getItem(key);\r\n if (!value) {\r\n // If temp cache item not found in session/memory, check local storage for items set by old versions\r\n if (\r\n this.cacheConfig.cacheLocation ===\r\n BrowserCacheLocation.LocalStorage\r\n ) {\r\n const item = this.browserStorage.getItem(key);\r\n if (item) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getTemporaryCache: Temporary cache item found in local storage\"\r\n );\r\n return item;\r\n }\r\n }\r\n this.logger.trace(\r\n \"BrowserCacheManager.getTemporaryCache: No cache item found in local storage\"\r\n );\r\n return null;\r\n }\r\n this.logger.trace(\r\n \"BrowserCacheManager.getTemporaryCache: Temporary cache item returned\"\r\n );\r\n return value;\r\n }\r\n\r\n /**\r\n * Sets the cache item with the key and value given.\r\n * Stores in cookie if storeAuthStateInCookie is set to true.\r\n * This can cause cookie overflow if used incorrectly.\r\n * @param key\r\n * @param value\r\n */\r\n setTemporaryCache(\r\n cacheKey: string,\r\n value: string,\r\n generateKey?: boolean\r\n ): void {\r\n const key = generateKey ? this.generateCacheKey(cacheKey) : cacheKey;\r\n\r\n this.temporaryCacheStorage.setItem(key, value);\r\n if (this.cacheConfig.storeAuthStateInCookie) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.setTemporaryCache: storeAuthStateInCookie set to true, setting item cookie\"\r\n );\r\n this.cookieStorage.setItem(\r\n key,\r\n value,\r\n undefined,\r\n this.cacheConfig.secureCookies\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Removes the cache item with the given key.\r\n * @param key\r\n */\r\n removeItem(key: string): void {\r\n this.browserStorage.removeItem(key);\r\n }\r\n\r\n /**\r\n * Removes the temporary cache item with the given key.\r\n * Will also clear the cookie item if storeAuthStateInCookie is set to true.\r\n * @param key\r\n */\r\n removeTemporaryItem(key: string): void {\r\n this.temporaryCacheStorage.removeItem(key);\r\n if (this.cacheConfig.storeAuthStateInCookie) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.removeItem: storeAuthStateInCookie is true, clearing item cookie\"\r\n );\r\n this.cookieStorage.removeItem(key);\r\n }\r\n }\r\n\r\n /**\r\n * Gets all keys in window.\r\n */\r\n getKeys(): string[] {\r\n return this.browserStorage.getKeys();\r\n }\r\n\r\n /**\r\n * Clears all cache entries created by MSAL.\r\n */\r\n clear(correlationId: string): void {\r\n // Removes all accounts and their credentials\r\n this.removeAllAccounts(correlationId);\r\n this.removeAppMetadata(correlationId);\r\n\r\n // Remove temp storage first to make sure any cookies are cleared\r\n this.temporaryCacheStorage.getKeys().forEach((cacheKey: string) => {\r\n if (\r\n cacheKey.indexOf(CacheKeys.PREFIX) !== -1 ||\r\n cacheKey.indexOf(this.clientId) !== -1\r\n ) {\r\n this.removeTemporaryItem(cacheKey);\r\n }\r\n });\r\n\r\n // Removes all remaining MSAL cache items\r\n this.browserStorage.getKeys().forEach((cacheKey: string) => {\r\n if (\r\n cacheKey.indexOf(CacheKeys.PREFIX) !== -1 ||\r\n cacheKey.indexOf(this.clientId) !== -1\r\n ) {\r\n this.browserStorage.removeItem(cacheKey);\r\n }\r\n });\r\n\r\n this.internalStorage.clear();\r\n }\r\n\r\n /**\r\n * Clears all access tokes that have claims prior to saving the current one\r\n * @param performanceClient {IPerformanceClient}\r\n * @param correlationId {string} correlation id\r\n * @returns\r\n */\r\n clearTokensAndKeysWithClaims(correlationId: string): void {\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.ClearTokensAndKeysWithClaims,\r\n correlationId\r\n );\r\n\r\n const tokenKeys = this.getTokenKeys();\r\n let removedAccessTokens = 0;\r\n tokenKeys.accessToken.forEach((key: string) => {\r\n // if the access token has claims in its key, remove the token key and the token\r\n const credential = this.getAccessTokenCredential(\r\n key,\r\n correlationId\r\n );\r\n if (\r\n credential?.requestedClaimsHash &&\r\n key.includes(credential.requestedClaimsHash.toLowerCase())\r\n ) {\r\n this.removeAccessToken(key, correlationId);\r\n removedAccessTokens++;\r\n }\r\n });\r\n\r\n // warn if any access tokens are removed\r\n if (removedAccessTokens > 0) {\r\n this.logger.warning(\r\n `${removedAccessTokens} access tokens with claims in the cache keys have been removed from the cache.`\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Prepend msal. to each key\r\n * @param key\r\n * @param addInstanceId\r\n */\r\n generateCacheKey(key: string): string {\r\n if (StringUtils.startsWith(key, CacheKeys.PREFIX)) {\r\n return key;\r\n }\r\n return `${CacheKeys.PREFIX}.${this.clientId}.${key}`;\r\n }\r\n\r\n /**\r\n * Cache Key: msal.--------\r\n * IdToken Example: uid.utid-login.microsoftonline.com-idtoken-app_client_id-contoso.com\r\n * AccessToken Example: uid.utid-login.microsoftonline.com-accesstoken-app_client_id-contoso.com-scope1 scope2--pop\r\n * RefreshToken Example: uid.utid-login.microsoftonline.com-refreshtoken-1-contoso.com\r\n * @param credentialEntity\r\n * @returns\r\n */\r\n generateCredentialKey(credential: CredentialEntity): string {\r\n const familyId =\r\n (credential.credentialType === CredentialType.REFRESH_TOKEN &&\r\n credential.familyId) ||\r\n credential.clientId;\r\n const scheme =\r\n credential.tokenType &&\r\n credential.tokenType.toLowerCase() !==\r\n AuthenticationScheme.BEARER.toLowerCase()\r\n ? credential.tokenType.toLowerCase()\r\n : \"\";\r\n const credentialKey = [\r\n `${CacheKeys.PREFIX}.${CacheKeys.CREDENTIAL_SCHEMA_VERSION}`,\r\n credential.homeAccountId,\r\n credential.environment,\r\n credential.credentialType,\r\n familyId,\r\n credential.realm || \"\",\r\n credential.target || \"\",\r\n credential.requestedClaimsHash || \"\",\r\n scheme,\r\n ];\r\n\r\n return credentialKey.join(CacheKeys.CACHE_KEY_SEPARATOR).toLowerCase();\r\n }\r\n\r\n /**\r\n * Cache Key: msal....\r\n * @param account\r\n * @returns\r\n */\r\n generateAccountKey(account: AccountInfo): string {\r\n const homeTenantId = account.homeAccountId.split(\".\")[1];\r\n const accountKey = [\r\n `${CacheKeys.PREFIX}.${CacheKeys.ACCOUNT_SCHEMA_VERSION}`,\r\n account.homeAccountId,\r\n account.environment,\r\n homeTenantId || account.tenantId || \"\",\r\n ];\r\n\r\n return accountKey.join(CacheKeys.CACHE_KEY_SEPARATOR).toLowerCase();\r\n }\r\n\r\n /**\r\n * Reset all temporary cache items\r\n * @param state\r\n */\r\n resetRequestCache(): void {\r\n this.logger.trace(\"BrowserCacheManager.resetRequestCache called\");\r\n\r\n this.removeTemporaryItem(\r\n this.generateCacheKey(TemporaryCacheKeys.REQUEST_PARAMS)\r\n );\r\n this.removeTemporaryItem(\r\n this.generateCacheKey(TemporaryCacheKeys.VERIFIER)\r\n );\r\n this.removeTemporaryItem(\r\n this.generateCacheKey(TemporaryCacheKeys.ORIGIN_URI)\r\n );\r\n this.removeTemporaryItem(\r\n this.generateCacheKey(TemporaryCacheKeys.URL_HASH)\r\n );\r\n this.removeTemporaryItem(\r\n this.generateCacheKey(TemporaryCacheKeys.NATIVE_REQUEST)\r\n );\r\n this.setInteractionInProgress(false);\r\n }\r\n\r\n cacheAuthorizeRequest(\r\n authCodeRequest: CommonAuthorizationUrlRequest,\r\n codeVerifier?: string\r\n ): void {\r\n this.logger.trace(\"BrowserCacheManager.cacheAuthorizeRequest called\");\r\n\r\n const encodedValue = base64Encode(JSON.stringify(authCodeRequest));\r\n this.setTemporaryCache(\r\n TemporaryCacheKeys.REQUEST_PARAMS,\r\n encodedValue,\r\n true\r\n );\r\n\r\n if (codeVerifier) {\r\n const encodedVerifier = base64Encode(codeVerifier);\r\n this.setTemporaryCache(\r\n TemporaryCacheKeys.VERIFIER,\r\n encodedVerifier,\r\n true\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Gets the token exchange parameters from the cache. Throws an error if nothing is found.\r\n */\r\n getCachedRequest(): [CommonAuthorizationUrlRequest, string] {\r\n this.logger.trace(\"BrowserCacheManager.getCachedRequest called\");\r\n // Get token request from cache and parse as TokenExchangeParameters.\r\n const encodedTokenRequest = this.getTemporaryCache(\r\n TemporaryCacheKeys.REQUEST_PARAMS,\r\n true\r\n );\r\n if (!encodedTokenRequest) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.noTokenRequestCacheError\r\n );\r\n }\r\n const encodedVerifier = this.getTemporaryCache(\r\n TemporaryCacheKeys.VERIFIER,\r\n true\r\n );\r\n\r\n let parsedRequest: CommonAuthorizationUrlRequest;\r\n let verifier = \"\";\r\n try {\r\n parsedRequest = JSON.parse(base64Decode(encodedTokenRequest));\r\n if (encodedVerifier) {\r\n verifier = base64Decode(encodedVerifier);\r\n }\r\n } catch (e) {\r\n this.logger.errorPii(`Attempted to parse: ${encodedTokenRequest}`);\r\n this.logger.error(\r\n `Parsing cached token request threw with error: ${e}`\r\n );\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.unableToParseTokenRequestCacheError\r\n );\r\n }\r\n\r\n return [parsedRequest, verifier];\r\n }\r\n\r\n /**\r\n * Gets cached native request for redirect flows\r\n */\r\n getCachedNativeRequest(): PlatformAuthRequest | null {\r\n this.logger.trace(\"BrowserCacheManager.getCachedNativeRequest called\");\r\n const cachedRequest = this.getTemporaryCache(\r\n TemporaryCacheKeys.NATIVE_REQUEST,\r\n true\r\n );\r\n if (!cachedRequest) {\r\n this.logger.trace(\r\n \"BrowserCacheManager.getCachedNativeRequest: No cached native request found\"\r\n );\r\n return null;\r\n }\r\n\r\n const parsedRequest = this.validateAndParseJson(\r\n cachedRequest\r\n ) as PlatformAuthRequest;\r\n if (!parsedRequest) {\r\n this.logger.error(\r\n \"BrowserCacheManager.getCachedNativeRequest: Unable to parse native request\"\r\n );\r\n return null;\r\n }\r\n\r\n return parsedRequest;\r\n }\r\n\r\n isInteractionInProgress(matchClientId?: boolean): boolean {\r\n const clientId = this.getInteractionInProgress()?.clientId;\r\n\r\n if (matchClientId) {\r\n return clientId === this.clientId;\r\n } else {\r\n return !!clientId;\r\n }\r\n }\r\n\r\n getInteractionInProgress(): {\r\n clientId: string;\r\n type: INTERACTION_TYPE;\r\n } | null {\r\n const key = `${CacheKeys.PREFIX}.${TemporaryCacheKeys.INTERACTION_STATUS_KEY}`;\r\n const value = this.getTemporaryCache(key, false);\r\n try {\r\n return value ? JSON.parse(value) : null;\r\n } catch (e) {\r\n // Remove interaction and other temp keys if interaction status can't be parsed\r\n this.logger.error(\r\n `Cannot parse interaction status. Removing temporary cache items and clearing url hash. Retrying interaction should fix the error`\r\n );\r\n this.removeTemporaryItem(key);\r\n this.resetRequestCache();\r\n clearHash(window);\r\n return null;\r\n }\r\n }\r\n\r\n setInteractionInProgress(\r\n inProgress: boolean,\r\n type: INTERACTION_TYPE = INTERACTION_TYPE.SIGNIN\r\n ): void {\r\n // Ensure we don't overwrite interaction in progress for a different clientId\r\n const key = `${CacheKeys.PREFIX}.${TemporaryCacheKeys.INTERACTION_STATUS_KEY}`;\r\n if (inProgress) {\r\n if (this.getInteractionInProgress()) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.interactionInProgress\r\n );\r\n } else {\r\n // No interaction is in progress\r\n this.setTemporaryCache(\r\n key,\r\n JSON.stringify({ clientId: this.clientId, type }),\r\n false\r\n );\r\n }\r\n } else if (\r\n !inProgress &&\r\n this.getInteractionInProgress()?.clientId === this.clientId\r\n ) {\r\n this.removeTemporaryItem(key);\r\n }\r\n }\r\n\r\n /**\r\n * Builds credential entities from AuthenticationResult object and saves the resulting credentials to the cache\r\n * @param result\r\n * @param request\r\n */\r\n async hydrateCache(\r\n result: AuthenticationResult,\r\n request:\r\n | SilentRequest\r\n | SsoSilentRequest\r\n | RedirectRequest\r\n | PopupRequest\r\n ): Promise {\r\n const idTokenEntity = CacheHelpers.createIdTokenEntity(\r\n result.account?.homeAccountId,\r\n result.account?.environment,\r\n result.idToken,\r\n this.clientId,\r\n result.tenantId\r\n );\r\n\r\n let claimsHash;\r\n if (request.claims) {\r\n claimsHash = await this.cryptoImpl.hashString(request.claims);\r\n }\r\n\r\n /**\r\n * meta data for cache stores time in seconds from epoch\r\n * AuthenticationResult returns expiresOn and extExpiresOn in milliseconds (as a Date object which is in ms)\r\n * We need to map these for the cache when building tokens from AuthenticationResult\r\n *\r\n * The next MSAL VFuture should map these both to same value if possible\r\n */\r\n\r\n const accessTokenEntity = CacheHelpers.createAccessTokenEntity(\r\n result.account?.homeAccountId,\r\n result.account.environment,\r\n result.accessToken,\r\n this.clientId,\r\n result.tenantId,\r\n result.scopes.join(\" \"),\r\n // Access token expiresOn stored in seconds, converting from AuthenticationResult expiresOn stored as Date\r\n result.expiresOn\r\n ? TimeUtils.toSecondsFromDate(result.expiresOn)\r\n : 0,\r\n result.extExpiresOn\r\n ? TimeUtils.toSecondsFromDate(result.extExpiresOn)\r\n : 0,\r\n base64Decode,\r\n undefined, // refreshOn\r\n result.tokenType as AuthenticationScheme,\r\n undefined, // userAssertionHash\r\n request.sshKid,\r\n request.claims,\r\n claimsHash\r\n );\r\n\r\n const cacheRecord = {\r\n idToken: idTokenEntity,\r\n accessToken: accessTokenEntity,\r\n };\r\n return this.saveCacheRecord(cacheRecord, result.correlationId);\r\n }\r\n\r\n /**\r\n * saves a cache record\r\n * @param cacheRecord {CacheRecord}\r\n * @param storeInCache {?StoreInCache}\r\n * @param correlationId {?string} correlation id\r\n */\r\n async saveCacheRecord(\r\n cacheRecord: CacheRecord,\r\n correlationId: string,\r\n storeInCache?: StoreInCache\r\n ): Promise {\r\n try {\r\n await super.saveCacheRecord(\r\n cacheRecord,\r\n correlationId,\r\n storeInCache\r\n );\r\n } catch (e) {\r\n if (\r\n e instanceof CacheError &&\r\n this.performanceClient &&\r\n correlationId\r\n ) {\r\n try {\r\n const tokenKeys = this.getTokenKeys();\r\n\r\n this.performanceClient.addFields(\r\n {\r\n cacheRtCount: tokenKeys.refreshToken.length,\r\n cacheIdCount: tokenKeys.idToken.length,\r\n cacheAtCount: tokenKeys.accessToken.length,\r\n },\r\n correlationId\r\n );\r\n } catch (e) {}\r\n }\r\n\r\n throw e;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Returns a window storage class implementing the IWindowStorage interface that corresponds to the configured cacheLocation.\r\n * @param cacheLocation\r\n */\r\nfunction getStorageImplementation(\r\n clientId: string,\r\n cacheLocation: BrowserCacheLocation | string,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient\r\n): IWindowStorage {\r\n try {\r\n switch (cacheLocation) {\r\n case BrowserCacheLocation.LocalStorage:\r\n return new LocalStorage(clientId, logger, performanceClient);\r\n case BrowserCacheLocation.SessionStorage:\r\n return new SessionStorage();\r\n case BrowserCacheLocation.MemoryStorage:\r\n default:\r\n break;\r\n }\r\n } catch (e) {\r\n logger.error(e as string);\r\n }\r\n\r\n return new MemoryStorage();\r\n}\r\n\r\nexport const DEFAULT_BROWSER_CACHE_MANAGER = (\r\n clientId: string,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient,\r\n eventHandler: EventHandler\r\n): BrowserCacheManager => {\r\n const cacheOptions: Required = {\r\n cacheLocation: BrowserCacheLocation.MemoryStorage,\r\n cacheRetentionDays: 5,\r\n temporaryCacheLocation: BrowserCacheLocation.MemoryStorage,\r\n storeAuthStateInCookie: false,\r\n secureCookies: false,\r\n cacheMigrationEnabled: false,\r\n claimsBasedCachingEnabled: false,\r\n };\r\n return new BrowserCacheManager(\r\n clientId,\r\n cacheOptions,\r\n DEFAULT_CRYPTO_IMPLEMENTATION,\r\n logger,\r\n performanceClient,\r\n eventHandler\r\n );\r\n};\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AccountInfo, AccountFilter, Logger } from \"@azure/msal-common/browser\";\r\nimport { BrowserCacheManager } from \"./BrowserCacheManager.js\";\r\n\r\n/**\r\n * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.\r\n * @param accountFilter - (Optional) filter to narrow down the accounts returned\r\n * @returns Array of AccountInfo objects in cache\r\n */\r\nexport function getAllAccounts(\r\n logger: Logger,\r\n browserStorage: BrowserCacheManager,\r\n isInBrowser: boolean,\r\n correlationId: string,\r\n accountFilter?: AccountFilter\r\n): AccountInfo[] {\r\n logger.verbose(\"getAllAccounts called\");\r\n return isInBrowser\r\n ? browserStorage.getAllAccounts(accountFilter || {}, correlationId)\r\n : [];\r\n}\r\n\r\n/**\r\n * Returns the first account found in the cache that matches the account filter passed in.\r\n * @param accountFilter\r\n * @returns The first account found in the cache matching the provided filter or null if no account could be found.\r\n */\r\nexport function getAccount(\r\n accountFilter: AccountFilter,\r\n logger: Logger,\r\n browserStorage: BrowserCacheManager,\r\n correlationId: string\r\n): AccountInfo | null {\r\n const account: AccountInfo | null = browserStorage.getAccountInfoFilteredBy(\r\n accountFilter,\r\n correlationId\r\n );\r\n\r\n if (account) {\r\n logger.verbose(\r\n \"getAccount: Account matching provided filter found, returning\"\r\n );\r\n return account;\r\n } else {\r\n logger.verbose(\"getAccount: No matching account found, returning null\");\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Returns the signed in account matching username.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found.\r\n * This API is provided for convenience but getAccountById should be used for best reliability\r\n * @param username\r\n * @returns The account object stored in MSAL\r\n */\r\nexport function getAccountByUsername(\r\n username: string,\r\n logger: Logger,\r\n browserStorage: BrowserCacheManager,\r\n correlationId: string\r\n): AccountInfo | null {\r\n logger.trace(\"getAccountByUsername called\");\r\n if (!username) {\r\n logger.warning(\"getAccountByUsername: No username provided\");\r\n return null;\r\n }\r\n\r\n const account = browserStorage.getAccountInfoFilteredBy(\r\n {\r\n username,\r\n },\r\n correlationId\r\n );\r\n if (account) {\r\n logger.verbose(\r\n \"getAccountByUsername: Account matching username found, returning\"\r\n );\r\n logger.verbosePii(\r\n `getAccountByUsername: Returning signed-in accounts matching username: ${username}`\r\n );\r\n return account;\r\n } else {\r\n logger.verbose(\r\n \"getAccountByUsername: No matching account found, returning null\"\r\n );\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Returns the signed in account matching homeAccountId.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found\r\n * @param homeAccountId\r\n * @returns The account object stored in MSAL\r\n */\r\nexport function getAccountByHomeId(\r\n homeAccountId: string,\r\n logger: Logger,\r\n browserStorage: BrowserCacheManager,\r\n correlationId: string\r\n): AccountInfo | null {\r\n logger.trace(\"getAccountByHomeId called\");\r\n if (!homeAccountId) {\r\n logger.warning(\"getAccountByHomeId: No homeAccountId provided\");\r\n return null;\r\n }\r\n\r\n const account = browserStorage.getAccountInfoFilteredBy(\r\n {\r\n homeAccountId,\r\n },\r\n correlationId\r\n );\r\n if (account) {\r\n logger.verbose(\r\n \"getAccountByHomeId: Account matching homeAccountId found, returning\"\r\n );\r\n logger.verbosePii(\r\n `getAccountByHomeId: Returning signed-in accounts matching homeAccountId: ${homeAccountId}`\r\n );\r\n return account;\r\n } else {\r\n logger.verbose(\r\n \"getAccountByHomeId: No matching account found, returning null\"\r\n );\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Returns the signed in account matching localAccountId.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found\r\n * @param localAccountId\r\n * @returns The account object stored in MSAL\r\n */\r\nexport function getAccountByLocalId(\r\n localAccountId: string,\r\n logger: Logger,\r\n browserStorage: BrowserCacheManager,\r\n correlationId: string\r\n): AccountInfo | null {\r\n logger.trace(\"getAccountByLocalId called\");\r\n if (!localAccountId) {\r\n logger.warning(\"getAccountByLocalId: No localAccountId provided\");\r\n return null;\r\n }\r\n\r\n const account = browserStorage.getAccountInfoFilteredBy(\r\n {\r\n localAccountId,\r\n },\r\n correlationId\r\n );\r\n if (account) {\r\n logger.verbose(\r\n \"getAccountByLocalId: Account matching localAccountId found, returning\"\r\n );\r\n logger.verbosePii(\r\n `getAccountByLocalId: Returning signed-in accounts matching localAccountId: ${localAccountId}`\r\n );\r\n return account;\r\n } else {\r\n logger.verbose(\r\n \"getAccountByLocalId: No matching account found, returning null\"\r\n );\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Sets the account to use as the active account. If no account is passed to the acquireToken APIs, then MSAL will use this active account.\r\n * @param account\r\n */\r\nexport function setActiveAccount(\r\n account: AccountInfo | null,\r\n browserStorage: BrowserCacheManager,\r\n correlationId: string\r\n): void {\r\n browserStorage.setActiveAccount(account, correlationId);\r\n}\r\n\r\n/**\r\n * Gets the currently active account\r\n */\r\nexport function getActiveAccount(\r\n browserStorage: BrowserCacheManager,\r\n correlationId: string\r\n): AccountInfo | null {\r\n return browserStorage.getActiveAccount(correlationId);\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { Logger } from \"@azure/msal-common/browser\";\r\nimport { InteractionType } from \"../utils/BrowserConstants.js\";\r\nimport {\r\n EventCallbackFunction,\r\n EventError,\r\n EventMessage,\r\n EventPayload,\r\n} from \"./EventMessage.js\";\r\nimport { EventType } from \"./EventType.js\";\r\nimport { createGuid } from \"../utils/BrowserUtils.js\";\r\n\r\nconst BROADCAST_CHANNEL_NAME = \"msal.broadcast.event\";\r\n\r\nexport class EventHandler {\r\n // Callback for subscribing to events\r\n private eventCallbacks: Map<\r\n string,\r\n [EventCallbackFunction, Array]\r\n >;\r\n private logger: Logger;\r\n private broadcastChannel?: BroadcastChannel;\r\n\r\n constructor(logger?: Logger) {\r\n this.eventCallbacks = new Map();\r\n this.logger = logger || new Logger({});\r\n if (typeof BroadcastChannel !== \"undefined\") {\r\n this.broadcastChannel = new BroadcastChannel(\r\n BROADCAST_CHANNEL_NAME\r\n );\r\n }\r\n this.invokeCrossTabCallbacks = this.invokeCrossTabCallbacks.bind(this);\r\n }\r\n\r\n /**\r\n * Adds event callbacks to array\r\n * @param callback - callback to be invoked when an event is raised\r\n * @param eventTypes - list of events that this callback will be invoked for, if not provided callback will be invoked for all events\r\n * @param callbackId - Identifier for the callback, used to locate and remove the callback when no longer required\r\n */\r\n addEventCallback(\r\n callback: EventCallbackFunction,\r\n eventTypes?: Array,\r\n callbackId?: string\r\n ): string | null {\r\n if (typeof window !== \"undefined\") {\r\n const id = callbackId || createGuid();\r\n if (this.eventCallbacks.has(id)) {\r\n this.logger.error(\r\n `Event callback with id: ${id} is already registered. Please provide a unique id or remove the existing callback and try again.`\r\n );\r\n return null;\r\n }\r\n this.eventCallbacks.set(id, [callback, eventTypes || []]);\r\n this.logger.verbose(`Event callback registered with id: ${id}`);\r\n\r\n return id;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Removes callback with provided id from callback array\r\n * @param callbackId\r\n */\r\n removeEventCallback(callbackId: string): void {\r\n this.eventCallbacks.delete(callbackId);\r\n this.logger.verbose(`Event callback ${callbackId} removed.`);\r\n }\r\n\r\n /**\r\n * Emits events by calling callback with event message\r\n * @param eventType\r\n * @param interactionType\r\n * @param payload\r\n * @param error\r\n */\r\n emitEvent(\r\n eventType: EventType,\r\n interactionType?: InteractionType,\r\n payload?: EventPayload,\r\n error?: EventError\r\n ): void {\r\n const message: EventMessage = {\r\n eventType: eventType,\r\n interactionType: interactionType || null,\r\n payload: payload || null,\r\n error: error || null,\r\n timestamp: Date.now(),\r\n };\r\n\r\n switch (eventType) {\r\n case EventType.ACCOUNT_ADDED:\r\n case EventType.ACCOUNT_REMOVED:\r\n case EventType.ACTIVE_ACCOUNT_CHANGED:\r\n // Send event to other open tabs / MSAL instances on same domain\r\n this.broadcastChannel?.postMessage(message);\r\n break;\r\n default:\r\n // Emit event to callbacks registered in this instance\r\n this.invokeCallbacks(message);\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Invoke registered callbacks\r\n * @param message\r\n */\r\n private invokeCallbacks(message: EventMessage): void {\r\n this.eventCallbacks.forEach(\r\n (\r\n [callback, eventTypes]: [\r\n EventCallbackFunction,\r\n Array\r\n ],\r\n callbackId: string\r\n ) => {\r\n if (\r\n eventTypes.length === 0 ||\r\n eventTypes.includes(message.eventType)\r\n ) {\r\n this.logger.verbose(\r\n `Emitting event to callback ${callbackId}: ${message.eventType}`\r\n );\r\n callback.apply(null, [message]);\r\n }\r\n }\r\n );\r\n }\r\n\r\n /**\r\n * Wrapper around invokeCallbacks to handle broadcast events received from other tabs/instances\r\n * @param event\r\n */\r\n private invokeCrossTabCallbacks(event: MessageEvent): void {\r\n const message = event.data as EventMessage;\r\n this.invokeCallbacks(message);\r\n }\r\n\r\n /**\r\n * Listen for events broadcasted from other tabs/instances\r\n */\r\n subscribeCrossTab(): void {\r\n this.broadcastChannel?.addEventListener(\r\n \"message\",\r\n this.invokeCrossTabCallbacks\r\n );\r\n }\r\n\r\n /**\r\n * Unsubscribe from broadcast events\r\n */\r\n unsubscribeCrossTab(): void {\r\n this.broadcastChannel?.removeEventListener(\r\n \"message\",\r\n this.invokeCrossTabCallbacks\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n ICrypto,\r\n INetworkModule,\r\n Logger,\r\n AccountInfo,\r\n UrlString,\r\n ServerTelemetryManager,\r\n ServerTelemetryRequest,\r\n createClientConfigurationError,\r\n ClientConfigurationErrorCodes,\r\n Authority,\r\n AuthorityOptions,\r\n AuthorityFactory,\r\n IPerformanceClient,\r\n PerformanceEvents,\r\n AzureCloudOptions,\r\n invokeAsync,\r\n StringDict,\r\n} from \"@azure/msal-common/browser\";\r\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\r\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\r\nimport { EventHandler } from \"../event/EventHandler.js\";\r\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\r\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\r\nimport { PopupRequest } from \"../request/PopupRequest.js\";\r\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\r\nimport { version } from \"../packageMetadata.js\";\r\nimport { BrowserConstants } from \"../utils/BrowserConstants.js\";\r\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\r\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\r\nimport { createNewGuid } from \"../crypto/BrowserCrypto.js\";\r\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\r\n\r\nexport abstract class BaseInteractionClient {\r\n protected config: BrowserConfiguration;\r\n protected browserStorage: BrowserCacheManager;\r\n protected browserCrypto: ICrypto;\r\n protected networkClient: INetworkModule;\r\n protected logger: Logger;\r\n protected eventHandler: EventHandler;\r\n protected navigationClient: INavigationClient;\r\n protected platformAuthProvider: IPlatformAuthHandler | undefined;\r\n protected correlationId: string;\r\n protected performanceClient: IPerformanceClient;\r\n\r\n constructor(\r\n config: BrowserConfiguration,\r\n storageImpl: BrowserCacheManager,\r\n browserCrypto: ICrypto,\r\n logger: Logger,\r\n eventHandler: EventHandler,\r\n navigationClient: INavigationClient,\r\n performanceClient: IPerformanceClient,\r\n platformAuthProvider?: IPlatformAuthHandler,\r\n correlationId?: string\r\n ) {\r\n this.config = config;\r\n this.browserStorage = storageImpl;\r\n this.browserCrypto = browserCrypto;\r\n this.networkClient = this.config.system.networkClient;\r\n this.eventHandler = eventHandler;\r\n this.navigationClient = navigationClient;\r\n this.platformAuthProvider = platformAuthProvider;\r\n this.correlationId = correlationId || createNewGuid();\r\n this.logger = logger.clone(\r\n BrowserConstants.MSAL_SKU,\r\n version,\r\n this.correlationId\r\n );\r\n this.performanceClient = performanceClient;\r\n }\r\n\r\n abstract acquireToken(\r\n request: RedirectRequest | PopupRequest | SsoSilentRequest\r\n ): Promise;\r\n\r\n abstract logout(\r\n request: EndSessionRequest | ClearCacheRequest | undefined\r\n ): Promise;\r\n\r\n protected async clearCacheOnLogout(\r\n correlationId: string,\r\n account?: AccountInfo | null\r\n ): Promise {\r\n if (account) {\r\n // Clear given account.\r\n try {\r\n this.browserStorage.removeAccount(account, correlationId);\r\n this.logger.verbose(\r\n \"Cleared cache items belonging to the account provided in the logout request.\"\r\n );\r\n } catch (error) {\r\n this.logger.error(\r\n \"Account provided in logout request was not found. Local cache unchanged.\"\r\n );\r\n }\r\n } else {\r\n try {\r\n this.logger.verbose(\r\n \"No account provided in logout request, clearing all cache items.\",\r\n this.correlationId\r\n );\r\n // Clear all accounts and tokens\r\n this.browserStorage.clear(correlationId);\r\n // Clear any stray keys from IndexedDB\r\n await this.browserCrypto.clearKeystore();\r\n } catch (e) {\r\n this.logger.error(\r\n \"Attempted to clear all MSAL cache items and failed. Local cache unchanged.\"\r\n );\r\n }\r\n }\r\n }\r\n\r\n /**\r\n *\r\n * Use to get the redirect uri configured in MSAL or null.\r\n * @param requestRedirectUri\r\n * @returns Redirect URL\r\n *\r\n */\r\n getRedirectUri(requestRedirectUri?: string): string {\r\n this.logger.verbose(\"getRedirectUri called\");\r\n const redirectUri = requestRedirectUri || this.config.auth.redirectUri;\r\n return UrlString.getAbsoluteUrl(\r\n redirectUri,\r\n BrowserUtils.getCurrentUri()\r\n );\r\n }\r\n\r\n /**\r\n *\r\n * @param apiId\r\n * @param correlationId\r\n * @param forceRefresh\r\n */\r\n protected initializeServerTelemetryManager(\r\n apiId: number,\r\n forceRefresh?: boolean\r\n ): ServerTelemetryManager {\r\n this.logger.verbose(\"initializeServerTelemetryManager called\");\r\n const telemetryPayload: ServerTelemetryRequest = {\r\n clientId: this.config.auth.clientId,\r\n correlationId: this.correlationId,\r\n apiId: apiId,\r\n forceRefresh: forceRefresh || false,\r\n wrapperSKU: this.browserStorage.getWrapperMetadata()[0],\r\n wrapperVer: this.browserStorage.getWrapperMetadata()[1],\r\n };\r\n\r\n return new ServerTelemetryManager(\r\n telemetryPayload,\r\n this.browserStorage\r\n );\r\n }\r\n\r\n /**\r\n * Used to get a discovered version of the default authority.\r\n * @param params {\r\n * requestAuthority?: string;\r\n * requestAzureCloudOptions?: AzureCloudOptions;\r\n * requestExtraQueryParameters?: StringDict;\r\n * account?: AccountInfo;\r\n * }\r\n */\r\n protected async getDiscoveredAuthority(params: {\r\n requestAuthority?: string;\r\n requestAzureCloudOptions?: AzureCloudOptions;\r\n requestExtraQueryParameters?: StringDict;\r\n account?: AccountInfo;\r\n }): Promise {\r\n const { account } = params;\r\n const instanceAwareEQ =\r\n params.requestExtraQueryParameters &&\r\n params.requestExtraQueryParameters.hasOwnProperty(\"instance_aware\")\r\n ? params.requestExtraQueryParameters[\"instance_aware\"]\r\n : undefined;\r\n\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\r\n this.correlationId\r\n );\r\n const authorityOptions: AuthorityOptions = {\r\n protocolMode: this.config.auth.protocolMode,\r\n OIDCOptions: this.config.auth.OIDCOptions,\r\n knownAuthorities: this.config.auth.knownAuthorities,\r\n cloudDiscoveryMetadata: this.config.auth.cloudDiscoveryMetadata,\r\n authorityMetadata: this.config.auth.authorityMetadata,\r\n skipAuthorityMetadataCache:\r\n this.config.auth.skipAuthorityMetadataCache,\r\n };\r\n\r\n // build authority string based on auth params, precedence - azureCloudInstance + tenant >> authority\r\n const resolvedAuthority =\r\n params.requestAuthority || this.config.auth.authority;\r\n const resolvedInstanceAware = instanceAwareEQ?.length\r\n ? instanceAwareEQ === \"true\"\r\n : this.config.auth.instanceAware;\r\n\r\n const userAuthority =\r\n account && resolvedInstanceAware\r\n ? this.config.auth.authority.replace(\r\n UrlString.getDomainFromUrl(resolvedAuthority),\r\n account.environment\r\n )\r\n : resolvedAuthority;\r\n\r\n // fall back to the authority from config\r\n const builtAuthority = Authority.generateAuthority(\r\n userAuthority,\r\n params.requestAzureCloudOptions ||\r\n this.config.auth.azureCloudOptions\r\n );\r\n const discoveredAuthority = await invokeAsync(\r\n AuthorityFactory.createDiscoveredInstance,\r\n PerformanceEvents.AuthorityFactoryCreateDiscoveredInstance,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(\r\n builtAuthority,\r\n this.config.system.networkClient,\r\n this.browserStorage,\r\n authorityOptions,\r\n this.logger,\r\n this.correlationId,\r\n this.performanceClient\r\n );\r\n\r\n if (account && !discoveredAuthority.isAlias(account.environment)) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.authorityMismatch\r\n );\r\n }\r\n\r\n return discoveredAuthority;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n AccountInfo,\r\n AuthenticationScheme,\r\n BaseAuthRequest,\r\n ClientConfigurationErrorCodes,\r\n CommonSilentFlowRequest,\r\n HttpMethod,\r\n IPerformanceClient,\r\n Logger,\r\n PerformanceEvents,\r\n ProtocolMode,\r\n StringUtils,\r\n createClientConfigurationError,\r\n invokeAsync,\r\n} from \"@azure/msal-common/browser\";\r\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\r\nimport { SilentRequest } from \"./SilentRequest.js\";\r\nimport { hashString } from \"../crypto/BrowserCrypto.js\";\r\nimport { PopupRequest } from \"./PopupRequest.js\";\r\nimport { RedirectRequest } from \"./RedirectRequest.js\";\r\n\r\n/**\r\n * Initializer function for all request APIs\r\n * @param request\r\n */\r\nexport async function initializeBaseRequest(\r\n request: Partial & { correlationId: string },\r\n config: BrowserConfiguration,\r\n performanceClient: IPerformanceClient,\r\n logger: Logger\r\n): Promise {\r\n performanceClient.addQueueMeasurement(\r\n PerformanceEvents.InitializeBaseRequest,\r\n request.correlationId\r\n );\r\n const authority = request.authority || config.auth.authority;\r\n\r\n const scopes = [...((request && request.scopes) || [])];\r\n\r\n const validatedRequest: BaseAuthRequest = {\r\n ...request,\r\n correlationId: request.correlationId,\r\n authority,\r\n scopes,\r\n };\r\n\r\n // Set authenticationScheme to BEARER if not explicitly set in the request\r\n if (!validatedRequest.authenticationScheme) {\r\n validatedRequest.authenticationScheme = AuthenticationScheme.BEARER;\r\n logger.verbose(\r\n 'Authentication Scheme wasn\\'t explicitly set in request, defaulting to \"Bearer\" request'\r\n );\r\n } else {\r\n if (\r\n validatedRequest.authenticationScheme === AuthenticationScheme.SSH\r\n ) {\r\n if (!request.sshJwk) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.missingSshJwk\r\n );\r\n }\r\n if (!request.sshKid) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.missingSshKid\r\n );\r\n }\r\n }\r\n logger.verbose(\r\n `Authentication Scheme set to \"${validatedRequest.authenticationScheme}\" as configured in Auth request`\r\n );\r\n }\r\n\r\n // Set requested claims hash if claims-based caching is enabled and claims were requested\r\n if (\r\n config.cache.claimsBasedCachingEnabled &&\r\n request.claims &&\r\n // Checks for empty stringified object \"{}\" which doesn't qualify as requested claims\r\n !StringUtils.isEmptyObj(request.claims)\r\n ) {\r\n validatedRequest.requestedClaimsHash = await hashString(request.claims);\r\n }\r\n\r\n return validatedRequest;\r\n}\r\n\r\nexport async function initializeSilentRequest(\r\n request: SilentRequest & { correlationId: string },\r\n account: AccountInfo,\r\n config: BrowserConfiguration,\r\n performanceClient: IPerformanceClient,\r\n logger: Logger\r\n): Promise {\r\n performanceClient.addQueueMeasurement(\r\n PerformanceEvents.InitializeSilentRequest,\r\n request.correlationId\r\n );\r\n\r\n const baseRequest = await invokeAsync(\r\n initializeBaseRequest,\r\n PerformanceEvents.InitializeBaseRequest,\r\n logger,\r\n performanceClient,\r\n request.correlationId\r\n )(request, config, performanceClient, logger);\r\n return {\r\n ...request,\r\n ...baseRequest,\r\n account: account,\r\n forceRefresh: request.forceRefresh || false,\r\n };\r\n}\r\n\r\n/**\r\n * Validates that the combination of request method, protocol mode and authorize body parameters is correct.\r\n * Returns the validated or defaulted HTTP method or throws if the configured combination is invalid.\r\n * @param interactionRequest\r\n * @param protocolMode\r\n * @returns\r\n */\r\nexport function validateRequestMethod(\r\n interactionRequest: BaseAuthRequest | PopupRequest | RedirectRequest,\r\n protocolMode: ProtocolMode\r\n): HttpMethod {\r\n let httpMethod: HttpMethod | undefined;\r\n const requestMethod = interactionRequest.httpMethod;\r\n\r\n if (protocolMode === ProtocolMode.EAR) {\r\n // Don't override httpMethod if it is already set, default to POST if not set\r\n httpMethod = requestMethod || HttpMethod.POST;\r\n // Validate that method is not GET if protocol mode is EAR\r\n if (httpMethod !== HttpMethod.POST) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.invalidRequestMethodForEAR\r\n );\r\n }\r\n } else {\r\n // For non-EAR protocol modes, default to GET if httpMethod is not set\r\n httpMethod = requestMethod || HttpMethod.GET;\r\n }\r\n\r\n // Regardless of protocolMode, if there are authorizePostBodyParameters, validate the request method is POST\r\n if (\r\n interactionRequest.authorizePostBodyParameters &&\r\n httpMethod !== HttpMethod.POST\r\n ) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.invalidAuthorizePostBodyParameters\r\n );\r\n }\r\n\r\n return httpMethod;\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n ServerTelemetryManager,\r\n Constants,\r\n AuthorizationCodeClient,\r\n ClientConfiguration,\r\n UrlString,\r\n CommonEndSessionRequest,\r\n ProtocolUtils,\r\n ResponseMode,\r\n IdTokenClaims,\r\n AccountInfo,\r\n AzureCloudOptions,\r\n PerformanceEvents,\r\n invokeAsync,\r\n BaseAuthRequest,\r\n StringDict,\r\n CommonAuthorizationUrlRequest,\r\n} from \"@azure/msal-common/browser\";\r\nimport { BaseInteractionClient } from \"./BaseInteractionClient.js\";\r\nimport {\r\n BrowserConstants,\r\n InteractionType,\r\n} from \"../utils/BrowserConstants.js\";\r\nimport { version } from \"../packageMetadata.js\";\r\nimport { BrowserStateObject } from \"../utils/BrowserProtocolUtils.js\";\r\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\r\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\r\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\r\nimport { PopupRequest } from \"../request/PopupRequest.js\";\r\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\r\nimport { createNewGuid } from \"../crypto/BrowserCrypto.js\";\r\nimport {\r\n initializeBaseRequest,\r\n validateRequestMethod,\r\n} from \"../request/RequestHelpers.js\";\r\n\r\n/**\r\n * Defines the class structure and helper functions used by the \"standard\", non-brokered auth flows (popup, redirect, silent (RT), silent (iframe))\r\n */\r\nexport abstract class StandardInteractionClient extends BaseInteractionClient {\r\n /**\r\n * Initializer for the logout request.\r\n * @param logoutRequest\r\n */\r\n protected initializeLogoutRequest(\r\n logoutRequest?: EndSessionRequest\r\n ): CommonEndSessionRequest {\r\n this.logger.verbose(\r\n \"initializeLogoutRequest called\",\r\n logoutRequest?.correlationId\r\n );\r\n\r\n const validLogoutRequest: CommonEndSessionRequest = {\r\n correlationId: this.correlationId || createNewGuid(),\r\n ...logoutRequest,\r\n };\r\n\r\n /**\r\n * Set logout_hint to be login_hint from ID Token Claims if present\r\n * and logoutHint attribute wasn't manually set in logout request\r\n */\r\n if (logoutRequest) {\r\n // If logoutHint isn't set and an account was passed in, try to extract logoutHint from ID Token Claims\r\n if (!logoutRequest.logoutHint) {\r\n if (logoutRequest.account) {\r\n const logoutHint = this.getLogoutHintFromIdTokenClaims(\r\n logoutRequest.account\r\n );\r\n if (logoutHint) {\r\n this.logger.verbose(\r\n \"Setting logoutHint to login_hint ID Token Claim value for the account provided\"\r\n );\r\n validLogoutRequest.logoutHint = logoutHint;\r\n }\r\n } else {\r\n this.logger.verbose(\r\n \"logoutHint was not set and account was not passed into logout request, logoutHint will not be set\"\r\n );\r\n }\r\n } else {\r\n this.logger.verbose(\r\n \"logoutHint has already been set in logoutRequest\"\r\n );\r\n }\r\n } else {\r\n this.logger.verbose(\r\n \"logoutHint will not be set since no logout request was configured\"\r\n );\r\n }\r\n\r\n /*\r\n * Only set redirect uri if logout request isn't provided or the set uri isn't null.\r\n * Otherwise, use passed uri, config, or current page.\r\n */\r\n if (!logoutRequest || logoutRequest.postLogoutRedirectUri !== null) {\r\n if (logoutRequest && logoutRequest.postLogoutRedirectUri) {\r\n this.logger.verbose(\r\n \"Setting postLogoutRedirectUri to uri set on logout request\",\r\n validLogoutRequest.correlationId\r\n );\r\n validLogoutRequest.postLogoutRedirectUri =\r\n UrlString.getAbsoluteUrl(\r\n logoutRequest.postLogoutRedirectUri,\r\n BrowserUtils.getCurrentUri()\r\n );\r\n } else if (this.config.auth.postLogoutRedirectUri === null) {\r\n this.logger.verbose(\r\n \"postLogoutRedirectUri configured as null and no uri set on request, not passing post logout redirect\",\r\n validLogoutRequest.correlationId\r\n );\r\n } else if (this.config.auth.postLogoutRedirectUri) {\r\n this.logger.verbose(\r\n \"Setting postLogoutRedirectUri to configured uri\",\r\n validLogoutRequest.correlationId\r\n );\r\n validLogoutRequest.postLogoutRedirectUri =\r\n UrlString.getAbsoluteUrl(\r\n this.config.auth.postLogoutRedirectUri,\r\n BrowserUtils.getCurrentUri()\r\n );\r\n } else {\r\n this.logger.verbose(\r\n \"Setting postLogoutRedirectUri to current page\",\r\n validLogoutRequest.correlationId\r\n );\r\n validLogoutRequest.postLogoutRedirectUri =\r\n UrlString.getAbsoluteUrl(\r\n BrowserUtils.getCurrentUri(),\r\n BrowserUtils.getCurrentUri()\r\n );\r\n }\r\n } else {\r\n this.logger.verbose(\r\n \"postLogoutRedirectUri passed as null, not setting post logout redirect uri\",\r\n validLogoutRequest.correlationId\r\n );\r\n }\r\n\r\n return validLogoutRequest;\r\n }\r\n\r\n /**\r\n * Parses login_hint ID Token Claim out of AccountInfo object to be used as\r\n * logout_hint in end session request.\r\n * @param account\r\n */\r\n protected getLogoutHintFromIdTokenClaims(\r\n account: AccountInfo\r\n ): string | null {\r\n const idTokenClaims: IdTokenClaims | undefined = account.idTokenClaims;\r\n if (idTokenClaims) {\r\n if (idTokenClaims.login_hint) {\r\n return idTokenClaims.login_hint;\r\n } else {\r\n this.logger.verbose(\r\n \"The ID Token Claims tied to the provided account do not contain a login_hint claim, logoutHint will not be added to logout request\"\r\n );\r\n }\r\n } else {\r\n this.logger.verbose(\r\n \"The provided account does not contain ID Token Claims, logoutHint will not be added to logout request\"\r\n );\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Creates an Authorization Code Client with the given authority, or the default authority.\r\n * @param params {\r\n * serverTelemetryManager: ServerTelemetryManager;\r\n * authorityUrl?: string;\r\n * requestAzureCloudOptions?: AzureCloudOptions;\r\n * requestExtraQueryParameters?: StringDict;\r\n * account?: AccountInfo;\r\n * }\r\n */\r\n protected async createAuthCodeClient(params: {\r\n serverTelemetryManager: ServerTelemetryManager;\r\n requestAuthority?: string;\r\n requestAzureCloudOptions?: AzureCloudOptions;\r\n requestExtraQueryParameters?: StringDict;\r\n account?: AccountInfo;\r\n }): Promise {\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\r\n this.correlationId\r\n );\r\n // Create auth module.\r\n const clientConfig = await invokeAsync(\r\n this.getClientConfiguration.bind(this),\r\n PerformanceEvents.StandardInteractionClientGetClientConfiguration,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(params);\r\n\r\n return new AuthorizationCodeClient(\r\n clientConfig,\r\n this.performanceClient\r\n );\r\n }\r\n\r\n /**\r\n * Creates a Client Configuration object with the given request authority, or the default authority.\r\n * @param params {\r\n * serverTelemetryManager: ServerTelemetryManager;\r\n * requestAuthority?: string;\r\n * requestAzureCloudOptions?: AzureCloudOptions;\r\n * requestExtraQueryParameters?: boolean;\r\n * account?: AccountInfo;\r\n * }\r\n */\r\n protected async getClientConfiguration(params: {\r\n serverTelemetryManager: ServerTelemetryManager;\r\n requestAuthority?: string;\r\n requestAzureCloudOptions?: AzureCloudOptions;\r\n requestExtraQueryParameters?: StringDict;\r\n account?: AccountInfo;\r\n }): Promise {\r\n const {\r\n serverTelemetryManager,\r\n requestAuthority,\r\n requestAzureCloudOptions,\r\n requestExtraQueryParameters,\r\n account,\r\n } = params;\r\n\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.StandardInteractionClientGetClientConfiguration,\r\n this.correlationId\r\n );\r\n const discoveredAuthority = await invokeAsync(\r\n this.getDiscoveredAuthority.bind(this),\r\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )({\r\n requestAuthority,\r\n requestAzureCloudOptions,\r\n requestExtraQueryParameters,\r\n account,\r\n });\r\n const logger = this.config.system.loggerOptions;\r\n\r\n return {\r\n authOptions: {\r\n clientId: this.config.auth.clientId,\r\n authority: discoveredAuthority,\r\n clientCapabilities: this.config.auth.clientCapabilities,\r\n redirectUri: this.config.auth.redirectUri,\r\n },\r\n systemOptions: {\r\n tokenRenewalOffsetSeconds:\r\n this.config.system.tokenRenewalOffsetSeconds,\r\n preventCorsPreflight: true,\r\n },\r\n loggerOptions: {\r\n loggerCallback: logger.loggerCallback,\r\n piiLoggingEnabled: logger.piiLoggingEnabled,\r\n logLevel: logger.logLevel,\r\n correlationId: this.correlationId,\r\n },\r\n cacheOptions: {\r\n claimsBasedCachingEnabled:\r\n this.config.cache.claimsBasedCachingEnabled,\r\n },\r\n cryptoInterface: this.browserCrypto,\r\n networkInterface: this.networkClient,\r\n storageInterface: this.browserStorage,\r\n serverTelemetryManager: serverTelemetryManager,\r\n libraryInfo: {\r\n sku: BrowserConstants.MSAL_SKU,\r\n version: version,\r\n cpu: Constants.EMPTY_STRING,\r\n os: Constants.EMPTY_STRING,\r\n },\r\n telemetry: this.config.telemetry,\r\n };\r\n }\r\n\r\n /**\r\n * Helper to initialize required request parameters for interactive APIs and ssoSilent()\r\n * @param request\r\n * @param interactionType\r\n */\r\n protected async initializeAuthorizationRequest(\r\n request: RedirectRequest | PopupRequest | SsoSilentRequest,\r\n interactionType: InteractionType\r\n ): Promise {\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,\r\n this.correlationId\r\n );\r\n\r\n const redirectUri = this.getRedirectUri(request.redirectUri);\r\n const browserState: BrowserStateObject = {\r\n interactionType: interactionType,\r\n };\r\n const state = ProtocolUtils.setRequestState(\r\n this.browserCrypto,\r\n (request && request.state) || Constants.EMPTY_STRING,\r\n browserState\r\n );\r\n\r\n const baseRequest: BaseAuthRequest = await invokeAsync(\r\n initializeBaseRequest,\r\n PerformanceEvents.InitializeBaseRequest,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(\r\n { ...request, correlationId: this.correlationId },\r\n this.config,\r\n this.performanceClient,\r\n this.logger\r\n );\r\n\r\n const interactionRequest: CommonAuthorizationUrlRequest = {\r\n ...baseRequest,\r\n redirectUri: redirectUri,\r\n state: state,\r\n nonce: request.nonce || createNewGuid(),\r\n responseMode: this.config.auth.OIDCOptions\r\n .serverResponseType as ResponseMode,\r\n };\r\n\r\n const validatedRequest = {\r\n ...interactionRequest,\r\n httpMethod: validateRequestMethod(\r\n interactionRequest,\r\n this.config.auth.protocolMode\r\n ),\r\n };\r\n\r\n // Skip active account lookup if either login hint or session id is set\r\n if (request.loginHint || request.sid) {\r\n return validatedRequest;\r\n }\r\n\r\n const account =\r\n request.account ||\r\n this.browserStorage.getActiveAccount(this.correlationId);\r\n if (account) {\r\n this.logger.verbose(\r\n \"Setting validated request account\",\r\n this.correlationId\r\n );\r\n this.logger.verbosePii(\r\n `Setting validated request account: ${account.homeAccountId}`,\r\n this.correlationId\r\n );\r\n validatedRequest.account = account;\r\n }\r\n\r\n return validatedRequest;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { InteractionType } from \"./BrowserConstants.js\";\r\nimport {\r\n ICrypto,\r\n RequestStateObject,\r\n ProtocolUtils,\r\n createClientAuthError,\r\n ClientAuthErrorCodes,\r\n} from \"@azure/msal-common/browser\";\r\n\r\nexport type BrowserStateObject = {\r\n interactionType: InteractionType;\r\n};\r\n\r\n/**\r\n * Extracts the BrowserStateObject from the state string.\r\n * @param browserCrypto\r\n * @param state\r\n */\r\nexport function extractBrowserRequestState(\r\n browserCrypto: ICrypto,\r\n state: string\r\n): BrowserStateObject | null {\r\n if (!state) {\r\n return null;\r\n }\r\n\r\n try {\r\n const requestStateObj: RequestStateObject =\r\n ProtocolUtils.parseRequestState(browserCrypto, state);\r\n return requestStateObj.libraryState.meta as BrowserStateObject;\r\n } catch (e) {\r\n throw createClientAuthError(ClientAuthErrorCodes.invalidState);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n ICrypto,\r\n Logger,\r\n AuthorizeResponse,\r\n UrlUtils,\r\n} from \"@azure/msal-common/browser\";\r\nimport {\r\n BrowserAuthErrorCodes,\r\n createBrowserAuthError,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { extractBrowserRequestState } from \"../utils/BrowserProtocolUtils.js\";\r\nimport { InteractionType } from \"../utils/BrowserConstants.js\";\r\n\r\nexport function deserializeResponse(\r\n responseString: string,\r\n responseLocation: string,\r\n logger: Logger\r\n): AuthorizeResponse {\r\n // Deserialize hash fragment response parameters.\r\n const serverParams = UrlUtils.getDeserializedResponse(responseString);\r\n if (!serverParams) {\r\n if (!UrlUtils.stripLeadingHashOrQuery(responseString)) {\r\n // Hash or Query string is empty\r\n logger.error(\r\n `The request has returned to the redirectUri but a ${responseLocation} is not present. It's likely that the ${responseLocation} has been removed or the page has been redirected by code running on the redirectUri page.`\r\n );\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.hashEmptyError);\r\n } else {\r\n logger.error(\r\n `A ${responseLocation} is present in the iframe but it does not contain known properties. It's likely that the ${responseLocation} has been replaced by code running on the redirectUri page.`\r\n );\r\n logger.errorPii(\r\n `The ${responseLocation} detected is: ${responseString}`\r\n );\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.hashDoesNotContainKnownProperties\r\n );\r\n }\r\n }\r\n return serverParams;\r\n}\r\n\r\n/**\r\n * Returns the interaction type that the response object belongs to\r\n */\r\nexport function validateInteractionType(\r\n response: AuthorizeResponse,\r\n browserCrypto: ICrypto,\r\n interactionType: InteractionType\r\n): void {\r\n if (!response.state) {\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.noStateInHash);\r\n }\r\n\r\n const platformStateObj = extractBrowserRequestState(\r\n browserCrypto,\r\n response.state\r\n );\r\n if (!platformStateObj) {\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.unableToParseState);\r\n }\r\n\r\n if (platformStateObj.interactionType !== interactionType) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.stateInteractionTypeMismatch\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n AuthorizationCodePayload,\r\n CommonAuthorizationCodeRequest,\r\n AuthorizationCodeClient,\r\n CcsCredential,\r\n Logger,\r\n ServerError,\r\n IPerformanceClient,\r\n PerformanceEvents,\r\n invokeAsync,\r\n CcsCredentialType,\r\n AuthorizeResponse,\r\n AuthorizeProtocol,\r\n CommonAuthorizationUrlRequest,\r\n} from \"@azure/msal-common/browser\";\r\n\r\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\n\r\n/**\r\n * Abstract class which defines operations for a browser interaction handling class.\r\n */\r\nexport class InteractionHandler {\r\n protected authModule: AuthorizationCodeClient;\r\n protected browserStorage: BrowserCacheManager;\r\n protected authCodeRequest: CommonAuthorizationCodeRequest;\r\n protected logger: Logger;\r\n protected performanceClient: IPerformanceClient;\r\n\r\n constructor(\r\n authCodeModule: AuthorizationCodeClient,\r\n storageImpl: BrowserCacheManager,\r\n authCodeRequest: CommonAuthorizationCodeRequest,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient\r\n ) {\r\n this.authModule = authCodeModule;\r\n this.browserStorage = storageImpl;\r\n this.authCodeRequest = authCodeRequest;\r\n this.logger = logger;\r\n this.performanceClient = performanceClient;\r\n }\r\n\r\n /**\r\n * Function to handle response parameters from hash.\r\n * @param locationHash\r\n */\r\n async handleCodeResponse(\r\n response: AuthorizeResponse,\r\n request: CommonAuthorizationUrlRequest\r\n ): Promise {\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.HandleCodeResponse,\r\n request.correlationId\r\n );\r\n\r\n let authCodeResponse;\r\n try {\r\n authCodeResponse = AuthorizeProtocol.getAuthorizationCodePayload(\r\n response,\r\n request.state\r\n );\r\n } catch (e) {\r\n if (\r\n e instanceof ServerError &&\r\n e.subError === BrowserAuthErrorCodes.userCancelled\r\n ) {\r\n // Translate server error caused by user closing native prompt to corresponding first class MSAL error\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.userCancelled\r\n );\r\n } else {\r\n throw e;\r\n }\r\n }\r\n\r\n return invokeAsync(\r\n this.handleCodeResponseFromServer.bind(this),\r\n PerformanceEvents.HandleCodeResponseFromServer,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(authCodeResponse, request);\r\n }\r\n\r\n /**\r\n * Process auth code response from AAD\r\n * @param authCodeResponse\r\n * @param state\r\n * @param authority\r\n * @param networkModule\r\n * @returns\r\n */\r\n async handleCodeResponseFromServer(\r\n authCodeResponse: AuthorizationCodePayload,\r\n request: CommonAuthorizationUrlRequest,\r\n validateNonce: boolean = true\r\n ): Promise {\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.HandleCodeResponseFromServer,\r\n request.correlationId\r\n );\r\n this.logger.trace(\r\n \"InteractionHandler.handleCodeResponseFromServer called\"\r\n );\r\n\r\n // Assign code to request\r\n this.authCodeRequest.code = authCodeResponse.code;\r\n\r\n // Check for new cloud instance\r\n if (authCodeResponse.cloud_instance_host_name) {\r\n await invokeAsync(\r\n this.authModule.updateAuthority.bind(this.authModule),\r\n PerformanceEvents.UpdateTokenEndpointAuthority,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(authCodeResponse.cloud_instance_host_name, request.correlationId);\r\n }\r\n\r\n // Nonce validation not needed when redirect not involved (e.g. hybrid spa, renewing token via rt)\r\n if (validateNonce) {\r\n // TODO: Assigning \"response nonce\" to \"request nonce\" is confusing. Refactor the function doing validation to accept request nonce directly\r\n authCodeResponse.nonce = request.nonce || undefined;\r\n }\r\n\r\n authCodeResponse.state = request.state;\r\n\r\n // Add CCS parameters if available\r\n if (authCodeResponse.client_info) {\r\n this.authCodeRequest.clientInfo = authCodeResponse.client_info;\r\n } else {\r\n const ccsCred = this.createCcsCredentials(request);\r\n if (ccsCred) {\r\n this.authCodeRequest.ccsCredential = ccsCred;\r\n }\r\n }\r\n\r\n // Acquire token with retrieved code.\r\n const tokenResponse = (await invokeAsync(\r\n this.authModule.acquireToken.bind(this.authModule),\r\n PerformanceEvents.AuthClientAcquireToken,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(this.authCodeRequest, authCodeResponse)) as AuthenticationResult;\r\n return tokenResponse;\r\n }\r\n\r\n /**\r\n * Build ccs creds if available\r\n */\r\n protected createCcsCredentials(\r\n request: CommonAuthorizationUrlRequest\r\n ): CcsCredential | null {\r\n if (request.account) {\r\n return {\r\n credential: request.account.homeAccountId,\r\n type: CcsCredentialType.HOME_ACCOUNT_ID,\r\n };\r\n } else if (request.loginHint) {\r\n return {\r\n credential: request.loginHint,\r\n type: CcsCredentialType.UPN,\r\n };\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nexport const contentError = \"ContentError\";\r\nexport const userSwitch = \"user_switch\";\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\n// Status Codes that can be thrown by WAM\r\nexport const USER_INTERACTION_REQUIRED = \"USER_INTERACTION_REQUIRED\";\r\nexport const USER_CANCEL = \"USER_CANCEL\";\r\nexport const NO_NETWORK = \"NO_NETWORK\";\r\nexport const TRANSIENT_ERROR = \"TRANSIENT_ERROR\";\r\nexport const PERSISTENT_ERROR = \"PERSISTENT_ERROR\";\r\nexport const DISABLED = \"DISABLED\";\r\nexport const ACCOUNT_UNAVAILABLE = \"ACCOUNT_UNAVAILABLE\";\r\nexport const UX_NOT_ALLOWED = \"UX_NOT_ALLOWED\";\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n AuthError,\r\n InteractionRequiredAuthError,\r\n InteractionRequiredAuthErrorCodes,\r\n createInteractionRequiredAuthError,\r\n} from \"@azure/msal-common/browser\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"./BrowserAuthError.js\";\r\n\r\nimport * as NativeAuthErrorCodes from \"./NativeAuthErrorCodes.js\";\r\nimport * as NativeStatusCodes from \"../broker/nativeBroker/NativeStatusCodes.js\";\r\nexport { NativeAuthErrorCodes };\r\n\r\nexport type OSError = {\r\n error?: number;\r\n protocol_error?: string;\r\n properties?: object;\r\n status?: string;\r\n retryable?: boolean;\r\n};\r\n\r\nconst INVALID_METHOD_ERROR = -2147186943;\r\n\r\nexport const NativeAuthErrorMessages = {\r\n [NativeAuthErrorCodes.userSwitch]:\r\n \"User attempted to switch accounts in the native broker, which is not allowed. All new accounts must sign-in through the standard web flow first, please try again.\",\r\n};\r\n\r\nexport class NativeAuthError extends AuthError {\r\n ext: OSError | undefined;\r\n\r\n constructor(errorCode: string, description?: string, ext?: OSError) {\r\n super(errorCode, description);\r\n\r\n Object.setPrototypeOf(this, NativeAuthError.prototype);\r\n this.name = \"NativeAuthError\";\r\n this.ext = ext;\r\n }\r\n}\r\n\r\n/**\r\n * These errors should result in a fallback to the 'standard' browser based auth flow.\r\n */\r\nexport function isFatalNativeAuthError(error: NativeAuthError): boolean {\r\n if (\r\n error.ext &&\r\n error.ext.status &&\r\n error.ext.status === NativeStatusCodes.DISABLED\r\n ) {\r\n return true;\r\n }\r\n\r\n if (\r\n error.ext &&\r\n error.ext.error &&\r\n error.ext.error === INVALID_METHOD_ERROR\r\n ) {\r\n return true;\r\n }\r\n\r\n switch (error.errorCode) {\r\n case NativeAuthErrorCodes.contentError:\r\n return true;\r\n default:\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Create the appropriate error object based on the WAM status code.\r\n * @param code\r\n * @param description\r\n * @param ext\r\n * @returns\r\n */\r\nexport function createNativeAuthError(\r\n code: string,\r\n description?: string,\r\n ext?: OSError\r\n): AuthError {\r\n if (ext && ext.status) {\r\n switch (ext.status) {\r\n case NativeStatusCodes.ACCOUNT_UNAVAILABLE:\r\n return createInteractionRequiredAuthError(\r\n InteractionRequiredAuthErrorCodes.nativeAccountUnavailable\r\n );\r\n case NativeStatusCodes.USER_INTERACTION_REQUIRED:\r\n return new InteractionRequiredAuthError(code, description);\r\n case NativeStatusCodes.USER_CANCEL:\r\n return createBrowserAuthError(\r\n BrowserAuthErrorCodes.userCancelled\r\n );\r\n case NativeStatusCodes.NO_NETWORK:\r\n return createBrowserAuthError(\r\n BrowserAuthErrorCodes.noNetworkConnectivity\r\n );\r\n case NativeStatusCodes.UX_NOT_ALLOWED:\r\n return createInteractionRequiredAuthError(\r\n InteractionRequiredAuthErrorCodes.uxNotAllowed\r\n );\r\n }\r\n }\r\n\r\n return new NativeAuthError(\r\n code,\r\n NativeAuthErrorMessages[code] || description,\r\n ext\r\n );\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { StandardInteractionClient } from \"./StandardInteractionClient.js\";\r\nimport {\r\n CommonSilentFlowRequest,\r\n SilentFlowClient,\r\n PerformanceEvents,\r\n invokeAsync,\r\n} from \"@azure/msal-common/browser\";\r\nimport { ApiId } from \"../utils/BrowserConstants.js\";\r\nimport {\r\n BrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\r\n\r\nexport class SilentCacheClient extends StandardInteractionClient {\r\n /**\r\n * Returns unexpired tokens from the cache, if available\r\n * @param silentRequest\r\n */\r\n async acquireToken(\r\n silentRequest: CommonSilentFlowRequest\r\n ): Promise {\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.SilentCacheClientAcquireToken,\r\n silentRequest.correlationId\r\n );\r\n // Telemetry manager only used to increment cacheHits here\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(\r\n ApiId.acquireTokenSilent_silentFlow\r\n );\r\n\r\n const clientConfig = await invokeAsync(\r\n this.getClientConfiguration.bind(this),\r\n PerformanceEvents.StandardInteractionClientGetClientConfiguration,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )({\r\n serverTelemetryManager,\r\n requestAuthority: silentRequest.authority,\r\n requestAzureCloudOptions: silentRequest.azureCloudOptions,\r\n account: silentRequest.account,\r\n });\r\n const silentAuthClient = new SilentFlowClient(\r\n clientConfig,\r\n this.performanceClient\r\n );\r\n this.logger.verbose(\"Silent auth client created\");\r\n\r\n try {\r\n const response = await invokeAsync(\r\n silentAuthClient.acquireCachedToken.bind(silentAuthClient),\r\n PerformanceEvents.SilentFlowClientAcquireCachedToken,\r\n this.logger,\r\n this.performanceClient,\r\n silentRequest.correlationId\r\n )(silentRequest);\r\n const authResponse = response[0] as AuthenticationResult;\r\n\r\n this.performanceClient.addFields(\r\n {\r\n fromCache: true,\r\n },\r\n silentRequest.correlationId\r\n );\r\n return authResponse;\r\n } catch (error) {\r\n if (\r\n error instanceof BrowserAuthError &&\r\n error.errorCode === BrowserAuthErrorCodes.cryptoKeyNotFound\r\n ) {\r\n this.logger.verbose(\r\n \"Signing keypair for bound access token not found. Refreshing bound access token and generating a new crypto keypair.\"\r\n );\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * API to silenty clear the browser cache.\r\n * @param logoutRequest\r\n */\r\n logout(logoutRequest?: ClearCacheRequest): Promise {\r\n this.logger.verbose(\"logoutRedirect called\");\r\n const validLogoutRequest = this.initializeLogoutRequest(logoutRequest);\r\n return this.clearCacheOnLogout(\r\n validLogoutRequest.correlationId,\r\n validLogoutRequest?.account\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n Logger,\r\n ICrypto,\r\n PromptValue,\r\n AuthToken,\r\n Constants,\r\n AccountEntity,\r\n AuthorityType,\r\n ScopeSet,\r\n TimeUtils,\r\n AuthenticationScheme,\r\n UrlString,\r\n OIDC_DEFAULT_SCOPES,\r\n PopTokenGenerator,\r\n SignedHttpRequestParameters,\r\n IPerformanceClient,\r\n PerformanceEvents,\r\n IdTokenEntity,\r\n AccessTokenEntity,\r\n AuthError,\r\n CommonSilentFlowRequest,\r\n AccountInfo,\r\n AADServerParamKeys,\r\n TokenClaims,\r\n createClientAuthError,\r\n ClientAuthErrorCodes,\r\n invokeAsync,\r\n updateAccountTenantProfileData,\r\n CacheHelpers,\r\n buildAccountToCache,\r\n InProgressPerformanceEvent,\r\n ServerTelemetryManager,\r\n} from \"@azure/msal-common/browser\";\r\nimport { BaseInteractionClient } from \"./BaseInteractionClient.js\";\r\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\r\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\r\nimport { EventHandler } from \"../event/EventHandler.js\";\r\nimport { PopupRequest } from \"../request/PopupRequest.js\";\r\nimport { SilentRequest } from \"../request/SilentRequest.js\";\r\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\r\nimport {\r\n ApiId,\r\n TemporaryCacheKeys,\r\n PlatformAuthConstants,\r\n BrowserConstants,\r\n CacheLookupPolicy,\r\n} from \"../utils/BrowserConstants.js\";\r\nimport { PlatformAuthRequest } from \"../broker/nativeBroker/PlatformAuthRequest.js\";\r\nimport {\r\n MATS,\r\n PlatformAuthResponse,\r\n} from \"../broker/nativeBroker/PlatformAuthResponse.js\";\r\nimport {\r\n NativeAuthError,\r\n NativeAuthErrorCodes,\r\n createNativeAuthError,\r\n isFatalNativeAuthError,\r\n} from \"../error/NativeAuthError.js\";\r\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\r\nimport { NavigationOptions } from \"../navigation/NavigationOptions.js\";\r\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { SilentCacheClient } from \"./SilentCacheClient.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { base64Decode } from \"../encode/Base64Decode.js\";\r\nimport { version } from \"../packageMetadata.js\";\r\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\r\n\r\nexport class PlatformAuthInteractionClient extends BaseInteractionClient {\r\n protected apiId: ApiId;\r\n protected accountId: string;\r\n protected platformAuthProvider: IPlatformAuthHandler;\r\n protected silentCacheClient: SilentCacheClient;\r\n protected nativeStorageManager: BrowserCacheManager;\r\n protected skus: string;\r\n\r\n constructor(\r\n config: BrowserConfiguration,\r\n browserStorage: BrowserCacheManager,\r\n browserCrypto: ICrypto,\r\n logger: Logger,\r\n eventHandler: EventHandler,\r\n navigationClient: INavigationClient,\r\n apiId: ApiId,\r\n performanceClient: IPerformanceClient,\r\n provider: IPlatformAuthHandler,\r\n accountId: string,\r\n nativeStorageImpl: BrowserCacheManager,\r\n correlationId?: string\r\n ) {\r\n super(\r\n config,\r\n browserStorage,\r\n browserCrypto,\r\n logger,\r\n eventHandler,\r\n navigationClient,\r\n performanceClient,\r\n provider,\r\n correlationId\r\n );\r\n this.apiId = apiId;\r\n this.accountId = accountId;\r\n this.platformAuthProvider = provider;\r\n this.nativeStorageManager = nativeStorageImpl;\r\n this.silentCacheClient = new SilentCacheClient(\r\n config,\r\n this.nativeStorageManager,\r\n browserCrypto,\r\n logger,\r\n eventHandler,\r\n navigationClient,\r\n performanceClient,\r\n provider,\r\n correlationId\r\n );\r\n\r\n const extensionName = this.platformAuthProvider.getExtensionName();\r\n\r\n this.skus = ServerTelemetryManager.makeExtraSkuString({\r\n libraryName: BrowserConstants.MSAL_SKU,\r\n libraryVersion: version,\r\n extensionName: extensionName,\r\n extensionVersion: this.platformAuthProvider.getExtensionVersion(),\r\n });\r\n }\r\n\r\n /**\r\n * Adds SKUs to request extra query parameters\r\n * @param request {PlatformAuthRequest}\r\n * @private\r\n */\r\n private addRequestSKUs(request: PlatformAuthRequest): void {\r\n request.extraParameters = {\r\n ...request.extraParameters,\r\n [AADServerParamKeys.X_CLIENT_EXTRA_SKU]: this.skus,\r\n };\r\n }\r\n\r\n /**\r\n * Acquire token from native platform via browser extension\r\n * @param request\r\n */\r\n async acquireToken(\r\n request: PopupRequest | SilentRequest | SsoSilentRequest,\r\n cacheLookupPolicy?: CacheLookupPolicy\r\n ): Promise {\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.NativeInteractionClientAcquireToken,\r\n this.correlationId\r\n );\r\n this.logger.trace(\"NativeInteractionClient - acquireToken called.\");\r\n\r\n // start the perf measurement\r\n const nativeATMeasurement = this.performanceClient.startMeasurement(\r\n PerformanceEvents.NativeInteractionClientAcquireToken,\r\n this.correlationId\r\n );\r\n const reqTimestamp = TimeUtils.nowSeconds();\r\n\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(\r\n this.apiId\r\n );\r\n\r\n try {\r\n // initialize native request\r\n const nativeRequest = await this.initializeNativeRequest(request);\r\n\r\n // check if the tokens can be retrieved from internal cache\r\n try {\r\n const result = await this.acquireTokensFromCache(\r\n this.accountId,\r\n nativeRequest\r\n );\r\n nativeATMeasurement.end({\r\n success: true,\r\n isNativeBroker: false, // Should be true only when the result is coming directly from the broker\r\n fromCache: true,\r\n });\r\n return result;\r\n } catch (e) {\r\n if (cacheLookupPolicy === CacheLookupPolicy.AccessToken) {\r\n this.logger.info(\r\n \"MSAL internal Cache does not contain tokens, return error as per cache policy\"\r\n );\r\n nativeATMeasurement.end({\r\n success: false,\r\n brokerErrorCode: \"cache_request_failed\",\r\n });\r\n throw e;\r\n }\r\n // continue with a native call for any and all errors\r\n this.logger.info(\r\n \"MSAL internal Cache does not contain tokens, proceed to make a native call\"\r\n );\r\n }\r\n\r\n const validatedResponse: PlatformAuthResponse =\r\n await this.platformAuthProvider.sendMessage(nativeRequest);\r\n\r\n return await this.handleNativeResponse(\r\n validatedResponse,\r\n nativeRequest,\r\n reqTimestamp\r\n )\r\n .then((result: AuthenticationResult) => {\r\n nativeATMeasurement.end({\r\n success: true,\r\n isNativeBroker: true,\r\n requestId: result.requestId,\r\n });\r\n serverTelemetryManager.clearNativeBrokerErrorCode();\r\n return result;\r\n })\r\n .catch((error: AuthError) => {\r\n nativeATMeasurement.end({\r\n success: false,\r\n errorCode: error.errorCode,\r\n subErrorCode: error.subError,\r\n });\r\n throw error;\r\n });\r\n } catch (e) {\r\n if (e instanceof NativeAuthError) {\r\n serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);\r\n }\r\n nativeATMeasurement.end({\r\n success: false,\r\n });\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Creates silent flow request\r\n * @param request\r\n * @param cachedAccount\r\n * @returns CommonSilentFlowRequest\r\n */\r\n private createSilentCacheRequest(\r\n request: PlatformAuthRequest,\r\n cachedAccount: AccountInfo\r\n ): CommonSilentFlowRequest {\r\n return {\r\n authority: request.authority,\r\n correlationId: this.correlationId,\r\n scopes: ScopeSet.fromString(request.scope).asArray(),\r\n account: cachedAccount,\r\n forceRefresh: false,\r\n };\r\n }\r\n\r\n /**\r\n * Fetches the tokens from the cache if un-expired\r\n * @param nativeAccountId\r\n * @param request\r\n * @returns authenticationResult\r\n */\r\n protected async acquireTokensFromCache(\r\n nativeAccountId: string,\r\n request: PlatformAuthRequest\r\n ): Promise {\r\n if (!nativeAccountId) {\r\n this.logger.warning(\r\n \"NativeInteractionClient:acquireTokensFromCache - No nativeAccountId provided\"\r\n );\r\n throw createClientAuthError(ClientAuthErrorCodes.noAccountFound);\r\n }\r\n // fetch the account from browser cache\r\n const account = this.browserStorage.getBaseAccountInfo(\r\n {\r\n nativeAccountId,\r\n },\r\n this.correlationId\r\n );\r\n\r\n if (!account) {\r\n throw createClientAuthError(ClientAuthErrorCodes.noAccountFound);\r\n }\r\n\r\n // leverage silent flow for cached tokens retrieval\r\n try {\r\n const silentRequest = this.createSilentCacheRequest(\r\n request,\r\n account\r\n );\r\n const result = await this.silentCacheClient.acquireToken(\r\n silentRequest\r\n );\r\n\r\n const fullAccount = {\r\n ...account,\r\n idTokenClaims: result?.idTokenClaims as TokenClaims,\r\n idToken: result?.idToken,\r\n };\r\n\r\n return {\r\n ...result,\r\n account: fullAccount,\r\n };\r\n } catch (e) {\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Acquires a token from native platform then redirects to the redirectUri instead of returning the response\r\n * @param {RedirectRequest} request\r\n * @param {InProgressPerformanceEvent} rootMeasurement\r\n */\r\n async acquireTokenRedirect(\r\n request: RedirectRequest,\r\n rootMeasurement: InProgressPerformanceEvent\r\n ): Promise {\r\n this.logger.trace(\r\n \"NativeInteractionClient - acquireTokenRedirect called.\"\r\n );\r\n\r\n const { ...remainingParameters } = request;\r\n delete remainingParameters.onRedirectNavigate;\r\n\r\n const nativeRequest = await this.initializeNativeRequest(\r\n remainingParameters\r\n );\r\n\r\n try {\r\n await this.platformAuthProvider.sendMessage(nativeRequest);\r\n } catch (e) {\r\n // Only throw fatal errors here to allow application to fallback to regular redirect. Otherwise proceed and the error will be thrown in handleRedirectPromise\r\n if (e instanceof NativeAuthError) {\r\n const serverTelemetryManager =\r\n this.initializeServerTelemetryManager(this.apiId);\r\n serverTelemetryManager.setNativeBrokerErrorCode(e.errorCode);\r\n if (isFatalNativeAuthError(e)) {\r\n throw e;\r\n }\r\n }\r\n }\r\n this.browserStorage.setTemporaryCache(\r\n TemporaryCacheKeys.NATIVE_REQUEST,\r\n JSON.stringify(nativeRequest),\r\n true\r\n );\r\n\r\n const navigationOptions: NavigationOptions = {\r\n apiId: ApiId.acquireTokenRedirect,\r\n timeout: this.config.system.redirectNavigationTimeout,\r\n noHistory: false,\r\n };\r\n const redirectUri = this.config.auth.navigateToLoginRequestUrl\r\n ? window.location.href\r\n : this.getRedirectUri(request.redirectUri);\r\n rootMeasurement.end({ success: true });\r\n await this.navigationClient.navigateExternal(\r\n redirectUri,\r\n navigationOptions\r\n ); // Need to treat this as external to ensure handleRedirectPromise is run again\r\n }\r\n\r\n /**\r\n * If the previous page called native platform for a token using redirect APIs, send the same request again and return the response\r\n * @param performanceClient {IPerformanceClient?}\r\n * @param correlationId {string?} correlation identifier\r\n */\r\n async handleRedirectPromise(\r\n performanceClient?: IPerformanceClient,\r\n correlationId?: string\r\n ): Promise {\r\n this.logger.trace(\r\n \"NativeInteractionClient - handleRedirectPromise called.\"\r\n );\r\n if (!this.browserStorage.isInteractionInProgress(true)) {\r\n this.logger.info(\r\n \"handleRedirectPromise called but there is no interaction in progress, returning null.\"\r\n );\r\n return null;\r\n }\r\n\r\n // remove prompt from the request to prevent WAM from prompting twice\r\n const cachedRequest = this.browserStorage.getCachedNativeRequest();\r\n if (!cachedRequest) {\r\n this.logger.verbose(\r\n \"NativeInteractionClient - handleRedirectPromise called but there is no cached request, returning null.\"\r\n );\r\n if (performanceClient && correlationId) {\r\n performanceClient?.addFields(\r\n { errorCode: \"no_cached_request\" },\r\n correlationId\r\n );\r\n }\r\n return null;\r\n }\r\n\r\n const { prompt, ...request } = cachedRequest;\r\n if (prompt) {\r\n this.logger.verbose(\r\n \"NativeInteractionClient - handleRedirectPromise called and prompt was included in the original request, removing prompt from cached request to prevent second interaction with native broker window.\"\r\n );\r\n }\r\n\r\n this.browserStorage.removeItem(\r\n this.browserStorage.generateCacheKey(\r\n TemporaryCacheKeys.NATIVE_REQUEST\r\n )\r\n );\r\n\r\n const reqTimestamp = TimeUtils.nowSeconds();\r\n\r\n try {\r\n this.logger.verbose(\r\n \"NativeInteractionClient - handleRedirectPromise sending message to native broker.\"\r\n );\r\n const response: PlatformAuthResponse =\r\n await this.platformAuthProvider.sendMessage(request);\r\n const authResult = await this.handleNativeResponse(\r\n response,\r\n request,\r\n reqTimestamp\r\n );\r\n\r\n const serverTelemetryManager =\r\n this.initializeServerTelemetryManager(this.apiId);\r\n serverTelemetryManager.clearNativeBrokerErrorCode();\r\n if (performanceClient && this.correlationId) {\r\n this.performanceClient.addFields(\r\n { isNativeBroker: true },\r\n this.correlationId\r\n );\r\n }\r\n return authResult;\r\n } catch (e) {\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Logout from native platform via browser extension\r\n * @param request\r\n */\r\n logout(): Promise {\r\n this.logger.trace(\"NativeInteractionClient - logout called.\");\r\n return Promise.reject(\"Logout not implemented yet\");\r\n }\r\n\r\n /**\r\n * Transform response from native platform into AuthenticationResult object which will be returned to the end user\r\n * @param response\r\n * @param request\r\n * @param reqTimestamp\r\n */\r\n protected async handleNativeResponse(\r\n response: PlatformAuthResponse,\r\n request: PlatformAuthRequest,\r\n reqTimestamp: number\r\n ): Promise {\r\n this.logger.trace(\r\n \"NativeInteractionClient - handleNativeResponse called.\"\r\n );\r\n\r\n // generate identifiers\r\n const idTokenClaims = AuthToken.extractTokenClaims(\r\n response.id_token,\r\n base64Decode\r\n );\r\n\r\n const homeAccountIdentifier = this.createHomeAccountIdentifier(\r\n response,\r\n idTokenClaims\r\n );\r\n\r\n const cachedhomeAccountId =\r\n this.browserStorage.getAccountInfoFilteredBy(\r\n {\r\n nativeAccountId: request.accountId,\r\n },\r\n this.correlationId\r\n )?.homeAccountId;\r\n\r\n // add exception for double brokering, please note this is temporary and will be fortified in future\r\n if (\r\n request.extraParameters?.child_client_id &&\r\n response.account.id !== request.accountId\r\n ) {\r\n this.logger.info(\r\n \"handleNativeServerResponse: Double broker flow detected, ignoring accountId mismatch\"\r\n );\r\n } else if (\r\n homeAccountIdentifier !== cachedhomeAccountId &&\r\n response.account.id !== request.accountId\r\n ) {\r\n // User switch in native broker prompt is not supported. All users must first sign in through web flow to ensure server state is in sync\r\n throw createNativeAuthError(NativeAuthErrorCodes.userSwitch);\r\n }\r\n\r\n // Get the preferred_cache domain for the given authority\r\n const authority = await this.getDiscoveredAuthority({\r\n requestAuthority: request.authority,\r\n });\r\n\r\n const baseAccount = buildAccountToCache(\r\n this.browserStorage,\r\n authority,\r\n homeAccountIdentifier,\r\n base64Decode,\r\n this.correlationId,\r\n idTokenClaims,\r\n response.client_info,\r\n undefined, // environment\r\n idTokenClaims.tid,\r\n undefined, // auth code payload\r\n response.account.id,\r\n this.logger\r\n );\r\n\r\n // Ensure expires_in is in number format\r\n response.expires_in = Number(response.expires_in);\r\n\r\n // generate authenticationResult\r\n const result = await this.generateAuthenticationResult(\r\n response,\r\n request,\r\n idTokenClaims,\r\n baseAccount,\r\n authority.canonicalAuthority,\r\n reqTimestamp\r\n );\r\n\r\n // cache accounts and tokens in the appropriate storage\r\n await this.cacheAccount(baseAccount, this.correlationId);\r\n await this.cacheNativeTokens(\r\n response,\r\n request,\r\n homeAccountIdentifier,\r\n idTokenClaims,\r\n response.access_token,\r\n result.tenantId,\r\n reqTimestamp\r\n );\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * creates an homeAccountIdentifier for the account\r\n * @param response\r\n * @param idTokenObj\r\n * @returns\r\n */\r\n protected createHomeAccountIdentifier(\r\n response: PlatformAuthResponse,\r\n idTokenClaims: TokenClaims\r\n ): string {\r\n // Save account in browser storage\r\n const homeAccountIdentifier = AccountEntity.generateHomeAccountId(\r\n response.client_info || Constants.EMPTY_STRING,\r\n AuthorityType.Default,\r\n this.logger,\r\n this.browserCrypto,\r\n idTokenClaims\r\n );\r\n\r\n return homeAccountIdentifier;\r\n }\r\n\r\n /**\r\n * Helper to generate scopes\r\n * @param response\r\n * @param request\r\n * @returns\r\n */\r\n generateScopes(requestScopes: string, responseScopes?: string): ScopeSet {\r\n return responseScopes\r\n ? ScopeSet.fromString(responseScopes)\r\n : ScopeSet.fromString(requestScopes);\r\n }\r\n\r\n /**\r\n * If PoP token is requesred, records the PoP token if returned from the WAM, else generates one in the browser\r\n * @param request\r\n * @param response\r\n */\r\n async generatePopAccessToken(\r\n response: PlatformAuthResponse,\r\n request: PlatformAuthRequest\r\n ): Promise {\r\n if (\r\n request.tokenType === AuthenticationScheme.POP &&\r\n request.signPopToken\r\n ) {\r\n /**\r\n * This code prioritizes SHR returned from the native layer. In case of error/SHR not calculated from WAM and the AT\r\n * is still received, SHR is calculated locally\r\n */\r\n\r\n // Check if native layer returned an SHR token\r\n if (response.shr) {\r\n this.logger.trace(\r\n \"handleNativeServerResponse: SHR is enabled in native layer\"\r\n );\r\n return response.shr;\r\n }\r\n\r\n // Generate SHR in msal js if WAM does not compute it when POP is enabled\r\n const popTokenGenerator: PopTokenGenerator = new PopTokenGenerator(\r\n this.browserCrypto\r\n );\r\n const shrParameters: SignedHttpRequestParameters = {\r\n resourceRequestMethod: request.resourceRequestMethod,\r\n resourceRequestUri: request.resourceRequestUri,\r\n shrClaims: request.shrClaims,\r\n shrNonce: request.shrNonce,\r\n };\r\n\r\n /**\r\n * KeyID must be present in the native request from when the PoP key was generated in order for\r\n * PopTokenGenerator to query the full key for signing\r\n */\r\n if (!request.keyId) {\r\n throw createClientAuthError(ClientAuthErrorCodes.keyIdMissing);\r\n }\r\n return popTokenGenerator.signPopToken(\r\n response.access_token,\r\n request.keyId,\r\n shrParameters\r\n );\r\n } else {\r\n return response.access_token;\r\n }\r\n }\r\n\r\n /**\r\n * Generates authentication result\r\n * @param response\r\n * @param request\r\n * @param idTokenObj\r\n * @param accountEntity\r\n * @param authority\r\n * @param reqTimestamp\r\n * @returns\r\n */\r\n protected async generateAuthenticationResult(\r\n response: PlatformAuthResponse,\r\n request: PlatformAuthRequest,\r\n idTokenClaims: TokenClaims,\r\n accountEntity: AccountEntity,\r\n authority: string,\r\n reqTimestamp: number\r\n ): Promise {\r\n // Add Native Broker fields to Telemetry\r\n const mats = this.addTelemetryFromNativeResponse(\r\n response.properties.MATS\r\n );\r\n\r\n // If scopes not returned in server response, use request scopes\r\n const responseScopes = this.generateScopes(\r\n request.scope,\r\n response.scope\r\n );\r\n\r\n const accountProperties = response.account.properties || {};\r\n const uid =\r\n accountProperties[\"UID\"] ||\r\n idTokenClaims.oid ||\r\n idTokenClaims.sub ||\r\n Constants.EMPTY_STRING;\r\n const tid =\r\n accountProperties[\"TenantId\"] ||\r\n idTokenClaims.tid ||\r\n Constants.EMPTY_STRING;\r\n\r\n const accountInfo: AccountInfo | null = updateAccountTenantProfileData(\r\n accountEntity.getAccountInfo(),\r\n undefined, // tenantProfile optional\r\n idTokenClaims,\r\n response.id_token\r\n );\r\n\r\n /**\r\n * In pairwise broker flows, this check prevents the broker's native account id\r\n * from being returned over the embedded app's account id.\r\n */\r\n if (accountInfo.nativeAccountId !== response.account.id) {\r\n accountInfo.nativeAccountId = response.account.id;\r\n }\r\n\r\n // generate PoP token as needed\r\n const responseAccessToken = await this.generatePopAccessToken(\r\n response,\r\n request\r\n );\r\n const tokenType =\r\n request.tokenType === AuthenticationScheme.POP\r\n ? AuthenticationScheme.POP\r\n : AuthenticationScheme.BEARER;\r\n\r\n const result: AuthenticationResult = {\r\n authority: authority,\r\n uniqueId: uid,\r\n tenantId: tid,\r\n scopes: responseScopes.asArray(),\r\n account: accountInfo,\r\n idToken: response.id_token,\r\n idTokenClaims: idTokenClaims,\r\n accessToken: responseAccessToken,\r\n fromCache: mats ? this.isResponseFromCache(mats) : false,\r\n // Request timestamp and NativeResponse expires_in are in seconds, converting to Date for AuthenticationResult\r\n expiresOn: TimeUtils.toDateFromSeconds(\r\n reqTimestamp + response.expires_in\r\n ),\r\n tokenType: tokenType,\r\n correlationId: this.correlationId,\r\n state: response.state,\r\n fromNativeBroker: true,\r\n };\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * cache the account entity in browser storage\r\n * @param accountEntity\r\n */\r\n async cacheAccount(\r\n accountEntity: AccountEntity,\r\n correlationId: string\r\n ): Promise {\r\n // Store the account info and hence `nativeAccountId` in browser cache\r\n await this.browserStorage.setAccount(accountEntity, this.correlationId);\r\n // Remove any existing cached tokens for this account in browser storage\r\n this.browserStorage.removeAccountContext(\r\n accountEntity.getAccountInfo(),\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Stores the access_token and id_token in inmemory storage\r\n * @param response\r\n * @param request\r\n * @param homeAccountIdentifier\r\n * @param idTokenObj\r\n * @param responseAccessToken\r\n * @param tenantId\r\n * @param reqTimestamp\r\n */\r\n cacheNativeTokens(\r\n response: PlatformAuthResponse,\r\n request: PlatformAuthRequest,\r\n homeAccountIdentifier: string,\r\n idTokenClaims: TokenClaims,\r\n responseAccessToken: string,\r\n tenantId: string,\r\n reqTimestamp: number\r\n ): Promise {\r\n const cachedIdToken: IdTokenEntity | null =\r\n CacheHelpers.createIdTokenEntity(\r\n homeAccountIdentifier,\r\n request.authority,\r\n response.id_token || \"\",\r\n request.clientId,\r\n idTokenClaims.tid || \"\"\r\n );\r\n\r\n // cache accessToken in inmemory storage\r\n const expiresIn: number =\r\n request.tokenType === AuthenticationScheme.POP\r\n ? Constants.SHR_NONCE_VALIDITY\r\n : (typeof response.expires_in === \"string\"\r\n ? parseInt(response.expires_in, 10)\r\n : response.expires_in) || 0;\r\n const tokenExpirationSeconds = reqTimestamp + expiresIn;\r\n const responseScopes = this.generateScopes(\r\n response.scope,\r\n request.scope\r\n );\r\n\r\n const cachedAccessToken: AccessTokenEntity | null =\r\n CacheHelpers.createAccessTokenEntity(\r\n homeAccountIdentifier,\r\n request.authority,\r\n responseAccessToken,\r\n request.clientId,\r\n idTokenClaims.tid || tenantId,\r\n responseScopes.printScopes(),\r\n tokenExpirationSeconds,\r\n 0,\r\n base64Decode,\r\n undefined,\r\n request.tokenType as AuthenticationScheme,\r\n undefined,\r\n request.keyId\r\n );\r\n\r\n const nativeCacheRecord = {\r\n idToken: cachedIdToken,\r\n accessToken: cachedAccessToken,\r\n };\r\n\r\n return this.nativeStorageManager.saveCacheRecord(\r\n nativeCacheRecord,\r\n this.correlationId,\r\n request.storeInCache\r\n );\r\n }\r\n\r\n getExpiresInValue(\r\n tokenType: string,\r\n expiresIn: string | number | undefined\r\n ): number {\r\n return tokenType === AuthenticationScheme.POP\r\n ? Constants.SHR_NONCE_VALIDITY\r\n : (typeof expiresIn === \"string\"\r\n ? parseInt(expiresIn, 10)\r\n : expiresIn) || 0;\r\n }\r\n\r\n protected addTelemetryFromNativeResponse(\r\n matsResponse?: string\r\n ): MATS | null {\r\n const mats = this.getMATSFromResponse(matsResponse);\r\n\r\n if (!mats) {\r\n return null;\r\n }\r\n\r\n this.performanceClient.addFields(\r\n {\r\n extensionId: this.platformAuthProvider.getExtensionId(),\r\n extensionVersion:\r\n this.platformAuthProvider.getExtensionVersion(),\r\n matsBrokerVersion: mats.broker_version,\r\n matsAccountJoinOnStart: mats.account_join_on_start,\r\n matsAccountJoinOnEnd: mats.account_join_on_end,\r\n matsDeviceJoin: mats.device_join,\r\n matsPromptBehavior: mats.prompt_behavior,\r\n matsApiErrorCode: mats.api_error_code,\r\n matsUiVisible: mats.ui_visible,\r\n matsSilentCode: mats.silent_code,\r\n matsSilentBiSubCode: mats.silent_bi_sub_code,\r\n matsSilentMessage: mats.silent_message,\r\n matsSilentStatus: mats.silent_status,\r\n matsHttpStatus: mats.http_status,\r\n matsHttpEventCount: mats.http_event_count,\r\n },\r\n this.correlationId\r\n );\r\n\r\n return mats;\r\n }\r\n\r\n /**\r\n * Gets MATS telemetry from native response\r\n * @param response\r\n * @returns\r\n */\r\n private getMATSFromResponse(matsResponse: string | undefined): MATS | null {\r\n if (matsResponse) {\r\n try {\r\n return JSON.parse(matsResponse);\r\n } catch (e) {\r\n this.logger.error(\r\n \"NativeInteractionClient - Error parsing MATS telemetry, returning null instead\"\r\n );\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Returns whether or not response came from native cache\r\n * @param response\r\n * @returns\r\n */\r\n protected isResponseFromCache(mats: MATS): boolean {\r\n if (typeof mats.is_cached === \"undefined\") {\r\n this.logger.verbose(\r\n \"NativeInteractionClient - MATS telemetry does not contain field indicating if response was served from cache. Returning false.\"\r\n );\r\n return false;\r\n }\r\n\r\n return !!mats.is_cached;\r\n }\r\n\r\n /**\r\n * Translates developer provided request object into NativeRequest object\r\n * @param request\r\n */\r\n protected async initializeNativeRequest(\r\n request: PopupRequest | SsoSilentRequest\r\n ): Promise {\r\n this.logger.trace(\r\n \"NativeInteractionClient - initializeNativeRequest called\"\r\n );\r\n\r\n const canonicalAuthority = await this.getCanonicalAuthority(request);\r\n\r\n // scopes are expected to be received by the native broker as \"scope\" and will be added to the request below. Other properties that should be dropped from the request to the native broker can be included in the object destructuring here.\r\n const { scopes, ...remainingProperties } = request;\r\n const scopeSet = new ScopeSet(scopes || []);\r\n scopeSet.appendScopes(OIDC_DEFAULT_SCOPES);\r\n\r\n const validatedRequest: PlatformAuthRequest = {\r\n ...remainingProperties,\r\n accountId: this.accountId,\r\n clientId: this.config.auth.clientId,\r\n authority: canonicalAuthority.urlString,\r\n scope: scopeSet.printScopes(),\r\n redirectUri: this.getRedirectUri(request.redirectUri),\r\n prompt: this.getPrompt(request.prompt),\r\n correlationId: this.correlationId,\r\n tokenType: request.authenticationScheme,\r\n windowTitleSubstring: document.title,\r\n extraParameters: {\r\n ...request.extraQueryParameters,\r\n ...request.tokenQueryParameters,\r\n },\r\n extendedExpiryToken: false, // Make this configurable?\r\n keyId: request.popKid,\r\n };\r\n\r\n // Check for PoP token requests: signPopToken should only be set to true if popKid is not set\r\n if (validatedRequest.signPopToken && !!request.popKid) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.invalidPopTokenRequest\r\n );\r\n }\r\n\r\n this.handleExtraBrokerParams(validatedRequest);\r\n validatedRequest.extraParameters =\r\n validatedRequest.extraParameters || {};\r\n validatedRequest.extraParameters.telemetry =\r\n PlatformAuthConstants.MATS_TELEMETRY;\r\n\r\n if (request.authenticationScheme === AuthenticationScheme.POP) {\r\n // add POP request type\r\n const shrParameters: SignedHttpRequestParameters = {\r\n resourceRequestUri: request.resourceRequestUri,\r\n resourceRequestMethod: request.resourceRequestMethod,\r\n shrClaims: request.shrClaims,\r\n shrNonce: request.shrNonce,\r\n };\r\n\r\n const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);\r\n\r\n // generate reqCnf if not provided in the request\r\n let reqCnfData;\r\n if (!validatedRequest.keyId) {\r\n const generatedReqCnfData = await invokeAsync(\r\n popTokenGenerator.generateCnf.bind(popTokenGenerator),\r\n PerformanceEvents.PopTokenGenerateCnf,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(shrParameters, this.logger);\r\n reqCnfData = generatedReqCnfData.reqCnfString;\r\n validatedRequest.keyId = generatedReqCnfData.kid;\r\n validatedRequest.signPopToken = true;\r\n } else {\r\n reqCnfData = this.browserCrypto.base64UrlEncode(\r\n JSON.stringify({ kid: validatedRequest.keyId })\r\n );\r\n validatedRequest.signPopToken = false;\r\n }\r\n\r\n // SPAs require whole string to be passed to broker\r\n validatedRequest.reqCnf = reqCnfData;\r\n }\r\n this.addRequestSKUs(validatedRequest);\r\n\r\n return validatedRequest;\r\n }\r\n\r\n private async getCanonicalAuthority(\r\n request: PopupRequest | SsoSilentRequest\r\n ): Promise {\r\n const requestAuthority =\r\n request.authority || this.config.auth.authority;\r\n\r\n if (request.account) {\r\n // validate authority\r\n await this.getDiscoveredAuthority({\r\n requestAuthority,\r\n requestAzureCloudOptions: request.azureCloudOptions,\r\n account: request.account,\r\n });\r\n }\r\n\r\n const canonicalAuthority = new UrlString(requestAuthority);\r\n canonicalAuthority.validateAsUri();\r\n return canonicalAuthority;\r\n }\r\n\r\n private getPrompt(prompt?: string): string | undefined {\r\n // If request is silent, prompt is always none\r\n switch (this.apiId) {\r\n case ApiId.ssoSilent:\r\n case ApiId.acquireTokenSilent_silentFlow:\r\n this.logger.trace(\r\n \"initializeNativeRequest: silent request sets prompt to none\"\r\n );\r\n return PromptValue.NONE;\r\n default:\r\n break;\r\n }\r\n\r\n // Prompt not provided, request may proceed and native broker decides if it needs to prompt\r\n if (!prompt) {\r\n this.logger.trace(\r\n \"initializeNativeRequest: prompt was not provided\"\r\n );\r\n return undefined;\r\n }\r\n\r\n // If request is interactive, check if prompt provided is allowed to go directly to native broker\r\n switch (prompt) {\r\n case PromptValue.NONE:\r\n case PromptValue.CONSENT:\r\n case PromptValue.LOGIN:\r\n this.logger.trace(\r\n \"initializeNativeRequest: prompt is compatible with native flow\"\r\n );\r\n return prompt;\r\n default:\r\n this.logger.trace(\r\n `initializeNativeRequest: prompt = ${prompt} is not compatible with native flow`\r\n );\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.nativePromptNotSupported\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Handles extra broker request parameters\r\n * @param request {PlatformAuthRequest}\r\n * @private\r\n */\r\n private handleExtraBrokerParams(request: PlatformAuthRequest): void {\r\n const hasExtraBrokerParams =\r\n request.extraParameters &&\r\n request.extraParameters.hasOwnProperty(\r\n AADServerParamKeys.BROKER_CLIENT_ID\r\n ) &&\r\n request.extraParameters.hasOwnProperty(\r\n AADServerParamKeys.BROKER_REDIRECT_URI\r\n ) &&\r\n request.extraParameters.hasOwnProperty(\r\n AADServerParamKeys.CLIENT_ID\r\n );\r\n\r\n if (!request.embeddedClientId && !hasExtraBrokerParams) {\r\n return;\r\n }\r\n\r\n let child_client_id: string = \"\";\r\n const child_redirect_uri = request.redirectUri;\r\n\r\n if (request.embeddedClientId) {\r\n request.redirectUri = this.config.auth.redirectUri;\r\n child_client_id = request.embeddedClientId;\r\n } else if (request.extraParameters) {\r\n request.redirectUri =\r\n request.extraParameters[AADServerParamKeys.BROKER_REDIRECT_URI];\r\n child_client_id =\r\n request.extraParameters[AADServerParamKeys.CLIENT_ID];\r\n }\r\n\r\n request.extraParameters = {\r\n child_client_id,\r\n child_redirect_uri,\r\n };\r\n\r\n this.performanceClient?.addFields(\r\n {\r\n embeddedClientId: child_client_id,\r\n embeddedRedirectUri: child_redirect_uri,\r\n },\r\n this.correlationId\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n AuthenticationScheme,\r\n Authority,\r\n AuthorizeProtocol,\r\n ClientConfigurationErrorCodes,\r\n CommonAuthorizationUrlRequest,\r\n createClientConfigurationError,\r\n invokeAsync,\r\n IPerformanceClient,\r\n Logger,\r\n PerformanceEvents,\r\n PopTokenGenerator,\r\n ProtocolMode,\r\n RequestParameterBuilder,\r\n OAuthResponseType,\r\n Constants,\r\n CommonAuthorizationCodeRequest,\r\n AuthorizationCodeClient,\r\n ProtocolUtils,\r\n ThrottlingUtils,\r\n AuthorizeResponse,\r\n ResponseHandler,\r\n TimeUtils,\r\n AuthorizationCodePayload,\r\n ServerAuthorizationTokenResponse,\r\n} from \"@azure/msal-common/browser\";\r\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\r\nimport { ApiId, BrowserConstants } from \"../utils/BrowserConstants.js\";\r\nimport { version } from \"../packageMetadata.js\";\r\nimport { CryptoOps } from \"../crypto/CryptoOps.js\";\r\nimport {\r\n BrowserAuthErrorCodes,\r\n createBrowserAuthError,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { InteractionHandler } from \"../interaction_handler/InteractionHandler.js\";\r\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\r\nimport { PlatformAuthInteractionClient } from \"../interaction_client/PlatformAuthInteractionClient.js\";\r\nimport { EventHandler } from \"../event/EventHandler.js\";\r\nimport { decryptEarResponse } from \"../crypto/BrowserCrypto.js\";\r\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\r\n\r\n/**\r\n * Returns map of parameters that are applicable to all calls to /authorize whether using PKCE or EAR\r\n * @param config\r\n * @param authority\r\n * @param request\r\n * @param logger\r\n * @param performanceClient\r\n * @returns\r\n */\r\nasync function getStandardParameters(\r\n config: BrowserConfiguration,\r\n authority: Authority,\r\n request: CommonAuthorizationUrlRequest,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient\r\n): Promise> {\r\n const parameters = AuthorizeProtocol.getStandardAuthorizeRequestParameters(\r\n { ...config.auth, authority: authority },\r\n request,\r\n logger,\r\n performanceClient\r\n );\r\n RequestParameterBuilder.addLibraryInfo(parameters, {\r\n sku: BrowserConstants.MSAL_SKU,\r\n version: version,\r\n os: \"\",\r\n cpu: \"\",\r\n });\r\n if (config.auth.protocolMode !== ProtocolMode.OIDC) {\r\n RequestParameterBuilder.addApplicationTelemetry(\r\n parameters,\r\n config.telemetry.application\r\n );\r\n }\r\n\r\n if (request.platformBroker) {\r\n // signal ests that this is a WAM call\r\n RequestParameterBuilder.addNativeBroker(parameters);\r\n\r\n // instrument JS-platform bridge specific fields\r\n performanceClient.addFields(\r\n {\r\n isPlatformAuthorizeRequest: true,\r\n },\r\n request.correlationId\r\n );\r\n\r\n // pass the req_cnf for POP\r\n if (request.authenticationScheme === AuthenticationScheme.POP) {\r\n const cryptoOps = new CryptoOps(logger, performanceClient);\r\n const popTokenGenerator = new PopTokenGenerator(cryptoOps);\r\n\r\n // req_cnf is always sent as a string for SPAs\r\n let reqCnfData;\r\n if (!request.popKid) {\r\n const generatedReqCnfData = await invokeAsync(\r\n popTokenGenerator.generateCnf.bind(popTokenGenerator),\r\n PerformanceEvents.PopTokenGenerateCnf,\r\n logger,\r\n performanceClient,\r\n request.correlationId\r\n )(request, logger);\r\n reqCnfData = generatedReqCnfData.reqCnfString;\r\n } else {\r\n reqCnfData = cryptoOps.encodeKid(request.popKid);\r\n }\r\n RequestParameterBuilder.addPopToken(parameters, reqCnfData);\r\n }\r\n }\r\n\r\n RequestParameterBuilder.instrumentBrokerParams(\r\n parameters,\r\n request.correlationId,\r\n performanceClient\r\n );\r\n\r\n return parameters;\r\n}\r\n\r\n/**\r\n * Gets the full /authorize URL with request parameters when using Auth Code + PKCE\r\n * @param config\r\n * @param authority\r\n * @param request\r\n * @param logger\r\n * @param performanceClient\r\n * @returns\r\n */\r\nexport async function getAuthCodeRequestUrl(\r\n config: BrowserConfiguration,\r\n authority: Authority,\r\n request: CommonAuthorizationUrlRequest,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient\r\n): Promise {\r\n if (!request.codeChallenge) {\r\n throw createClientConfigurationError(\r\n ClientConfigurationErrorCodes.pkceParamsMissing\r\n );\r\n }\r\n\r\n const parameters = await invokeAsync(\r\n getStandardParameters,\r\n PerformanceEvents.GetStandardParams,\r\n logger,\r\n performanceClient,\r\n request.correlationId\r\n )(config, authority, request, logger, performanceClient);\r\n RequestParameterBuilder.addResponseType(parameters, OAuthResponseType.CODE);\r\n\r\n RequestParameterBuilder.addCodeChallengeParams(\r\n parameters,\r\n request.codeChallenge,\r\n Constants.S256_CODE_CHALLENGE_METHOD\r\n );\r\n\r\n RequestParameterBuilder.addExtraQueryParameters(\r\n parameters,\r\n request.extraQueryParameters || {}\r\n );\r\n\r\n return AuthorizeProtocol.getAuthorizeUrl(\r\n authority,\r\n parameters,\r\n config.auth.encodeExtraQueryParams,\r\n request.extraQueryParameters\r\n );\r\n}\r\n\r\n/**\r\n * Gets the form that will be posted to /authorize with request parameters when using EAR\r\n */\r\nexport async function getEARForm(\r\n frame: Document,\r\n config: BrowserConfiguration,\r\n authority: Authority,\r\n request: CommonAuthorizationUrlRequest,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient\r\n): Promise {\r\n if (!request.earJwk) {\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.earJwkEmpty);\r\n }\r\n\r\n const parameters = await getStandardParameters(\r\n config,\r\n authority,\r\n request,\r\n logger,\r\n performanceClient\r\n );\r\n\r\n RequestParameterBuilder.addResponseType(\r\n parameters,\r\n OAuthResponseType.IDTOKEN_TOKEN_REFRESHTOKEN\r\n );\r\n RequestParameterBuilder.addEARParameters(parameters, request.earJwk);\r\n\r\n const queryParams = new Map();\r\n RequestParameterBuilder.addExtraQueryParameters(\r\n queryParams,\r\n request.extraQueryParameters || {}\r\n );\r\n const url = AuthorizeProtocol.getAuthorizeUrl(\r\n authority,\r\n queryParams,\r\n config.auth.encodeExtraQueryParams,\r\n request.extraQueryParameters\r\n );\r\n\r\n return createForm(frame, url, parameters);\r\n}\r\n\r\n/**\r\n * Gets the form that will be posted to /authorize with request parameters when using POST method\r\n */\r\nexport async function getCodeForm(\r\n frame: Document,\r\n config: BrowserConfiguration,\r\n authority: Authority,\r\n request: CommonAuthorizationUrlRequest,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient\r\n): Promise {\r\n const parameters = await getStandardParameters(\r\n config,\r\n authority,\r\n request,\r\n logger,\r\n performanceClient\r\n );\r\n\r\n RequestParameterBuilder.addResponseType(parameters, OAuthResponseType.CODE);\r\n\r\n RequestParameterBuilder.addCodeChallengeParams(\r\n parameters,\r\n request.codeChallenge,\r\n request.codeChallengeMethod || Constants.S256_CODE_CHALLENGE_METHOD\r\n );\r\n\r\n RequestParameterBuilder.addPostBodyParameters(\r\n parameters,\r\n request.authorizePostBodyParameters || {}\r\n );\r\n\r\n const queryParams = new Map();\r\n RequestParameterBuilder.addExtraQueryParameters(\r\n queryParams,\r\n request.extraQueryParameters || {}\r\n );\r\n\r\n const url = AuthorizeProtocol.getAuthorizeUrl(\r\n authority,\r\n queryParams,\r\n config.auth.encodeExtraQueryParams,\r\n request.extraQueryParameters\r\n );\r\n\r\n return createForm(frame, url, parameters);\r\n}\r\n\r\n/**\r\n * Creates form element in the provided document with auth parameters in the post body\r\n * @param frame\r\n * @param authorizeUrl\r\n * @param parameters\r\n * @returns\r\n */\r\nfunction createForm(\r\n frame: Document,\r\n authorizeUrl: string,\r\n parameters: Map\r\n): HTMLFormElement {\r\n const form = frame.createElement(\"form\");\r\n form.method = \"post\";\r\n form.action = authorizeUrl;\r\n\r\n parameters.forEach((value: string, key: string) => {\r\n const param = frame.createElement(\"input\");\r\n param.hidden = true;\r\n param.name = key;\r\n param.value = value;\r\n\r\n form.appendChild(param);\r\n });\r\n\r\n frame.body.appendChild(form);\r\n return form;\r\n}\r\n\r\n/**\r\n * Response handler when server returns accountId on the /authorize request\r\n * @param request\r\n * @param accountId\r\n * @param apiId\r\n * @param config\r\n * @param browserStorage\r\n * @param nativeStorage\r\n * @param eventHandler\r\n * @param logger\r\n * @param performanceClient\r\n * @param nativeMessageHandler\r\n * @returns\r\n */\r\nexport async function handleResponsePlatformBroker(\r\n request: CommonAuthorizationUrlRequest,\r\n accountId: string,\r\n apiId: ApiId,\r\n config: BrowserConfiguration,\r\n browserStorage: BrowserCacheManager,\r\n nativeStorage: BrowserCacheManager,\r\n eventHandler: EventHandler,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient,\r\n platformAuthProvider?: IPlatformAuthHandler\r\n): Promise {\r\n logger.verbose(\"Account id found, calling WAM for token\");\r\n\r\n if (!platformAuthProvider) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.nativeConnectionNotEstablished\r\n );\r\n }\r\n const browserCrypto = new CryptoOps(logger, performanceClient);\r\n const nativeInteractionClient = new PlatformAuthInteractionClient(\r\n config,\r\n browserStorage,\r\n browserCrypto,\r\n logger,\r\n eventHandler,\r\n config.system.navigationClient,\r\n apiId,\r\n performanceClient,\r\n platformAuthProvider,\r\n accountId,\r\n nativeStorage,\r\n request.correlationId\r\n );\r\n const { userRequestState } = ProtocolUtils.parseRequestState(\r\n browserCrypto,\r\n request.state\r\n );\r\n return invokeAsync(\r\n nativeInteractionClient.acquireToken.bind(nativeInteractionClient),\r\n PerformanceEvents.NativeInteractionClientAcquireToken,\r\n logger,\r\n performanceClient,\r\n request.correlationId\r\n )({\r\n ...request,\r\n state: userRequestState,\r\n prompt: undefined, // Server should handle the prompt, ideally native broker can do this part silently\r\n });\r\n}\r\n\r\n/**\r\n * Response handler when server returns code on the /authorize request\r\n * @param request\r\n * @param response\r\n * @param codeVerifier\r\n * @param authClient\r\n * @param browserStorage\r\n * @param logger\r\n * @param performanceClient\r\n * @returns\r\n */\r\nexport async function handleResponseCode(\r\n request: CommonAuthorizationUrlRequest,\r\n response: AuthorizeResponse,\r\n codeVerifier: string,\r\n apiId: ApiId,\r\n config: BrowserConfiguration,\r\n authClient: AuthorizationCodeClient,\r\n browserStorage: BrowserCacheManager,\r\n nativeStorage: BrowserCacheManager,\r\n eventHandler: EventHandler,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient,\r\n platformAuthProvider?: IPlatformAuthHandler\r\n): Promise {\r\n // Remove throttle if it exists\r\n ThrottlingUtils.removeThrottle(\r\n browserStorage,\r\n config.auth.clientId,\r\n request\r\n );\r\n if (response.accountId) {\r\n return invokeAsync(\r\n handleResponsePlatformBroker,\r\n PerformanceEvents.HandleResponsePlatformBroker,\r\n logger,\r\n performanceClient,\r\n request.correlationId\r\n )(\r\n request,\r\n response.accountId,\r\n apiId,\r\n config,\r\n browserStorage,\r\n nativeStorage,\r\n eventHandler,\r\n logger,\r\n performanceClient,\r\n platformAuthProvider\r\n );\r\n }\r\n const authCodeRequest: CommonAuthorizationCodeRequest = {\r\n ...request,\r\n code: response.code || \"\",\r\n codeVerifier: codeVerifier,\r\n };\r\n // Create popup interaction handler.\r\n const interactionHandler = new InteractionHandler(\r\n authClient,\r\n browserStorage,\r\n authCodeRequest,\r\n logger,\r\n performanceClient\r\n );\r\n // Handle response from hash string.\r\n const result = await invokeAsync(\r\n interactionHandler.handleCodeResponse.bind(interactionHandler),\r\n PerformanceEvents.HandleCodeResponse,\r\n logger,\r\n performanceClient,\r\n request.correlationId\r\n )(response, request);\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * Response handler when server returns ear_jwe on the /authorize request\r\n * @param request\r\n * @param response\r\n * @param apiId\r\n * @param config\r\n * @param authority\r\n * @param browserStorage\r\n * @param nativeStorage\r\n * @param eventHandler\r\n * @param logger\r\n * @param performanceClient\r\n * @param nativeMessageHandler\r\n * @returns\r\n */\r\nexport async function handleResponseEAR(\r\n request: CommonAuthorizationUrlRequest,\r\n response: AuthorizeResponse,\r\n apiId: ApiId,\r\n config: BrowserConfiguration,\r\n authority: Authority,\r\n browserStorage: BrowserCacheManager,\r\n nativeStorage: BrowserCacheManager,\r\n eventHandler: EventHandler,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient,\r\n platformAuthProvider?: IPlatformAuthHandler\r\n): Promise {\r\n // Remove throttle if it exists\r\n ThrottlingUtils.removeThrottle(\r\n browserStorage,\r\n config.auth.clientId,\r\n request\r\n );\r\n\r\n // Validate state & check response for errors\r\n AuthorizeProtocol.validateAuthorizationResponse(response, request.state);\r\n\r\n if (!response.ear_jwe) {\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.earJweEmpty);\r\n }\r\n\r\n if (!request.earJwk) {\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.earJwkEmpty);\r\n }\r\n\r\n const decryptedData = JSON.parse(\r\n await invokeAsync(\r\n decryptEarResponse,\r\n PerformanceEvents.DecryptEarResponse,\r\n logger,\r\n performanceClient,\r\n request.correlationId\r\n )(request.earJwk, response.ear_jwe)\r\n ) as AuthorizeResponse & ServerAuthorizationTokenResponse;\r\n\r\n if (decryptedData.accountId) {\r\n return invokeAsync(\r\n handleResponsePlatformBroker,\r\n PerformanceEvents.HandleResponsePlatformBroker,\r\n logger,\r\n performanceClient,\r\n request.correlationId\r\n )(\r\n request,\r\n decryptedData.accountId,\r\n apiId,\r\n config,\r\n browserStorage,\r\n nativeStorage,\r\n eventHandler,\r\n logger,\r\n performanceClient,\r\n platformAuthProvider\r\n );\r\n }\r\n\r\n const responseHandler = new ResponseHandler(\r\n config.auth.clientId,\r\n browserStorage,\r\n new CryptoOps(logger, performanceClient),\r\n logger,\r\n null,\r\n null,\r\n performanceClient\r\n );\r\n\r\n // Validate response. This function throws a server error if an error is returned by the server.\r\n responseHandler.validateTokenResponse(decryptedData);\r\n\r\n // Temporary until response handler is refactored to be more flow agnostic.\r\n const additionalData: AuthorizationCodePayload = {\r\n code: \"\",\r\n state: request.state,\r\n nonce: request.nonce,\r\n client_info: decryptedData.client_info,\r\n cloud_graph_host_name: decryptedData.cloud_graph_host_name,\r\n cloud_instance_host_name: decryptedData.cloud_instance_host_name,\r\n cloud_instance_name: decryptedData.cloud_instance_name,\r\n msgraph_host: decryptedData.msgraph_host,\r\n };\r\n\r\n return (await invokeAsync(\r\n responseHandler.handleServerTokenResponse.bind(responseHandler),\r\n PerformanceEvents.HandleServerTokenResponse,\r\n logger,\r\n performanceClient,\r\n request.correlationId\r\n )(\r\n decryptedData,\r\n authority,\r\n TimeUtils.nowSeconds(),\r\n request,\r\n additionalData,\r\n undefined,\r\n undefined,\r\n undefined,\r\n undefined\r\n )) as AuthenticationResult;\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n IPerformanceClient,\r\n Logger,\r\n PerformanceEvents,\r\n PkceCodes,\r\n invoke,\r\n invokeAsync,\r\n} from \"@azure/msal-common/browser\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { urlEncodeArr } from \"../encode/Base64Encode.js\";\r\nimport { getRandomValues, sha256Digest } from \"./BrowserCrypto.js\";\r\n\r\n// Constant byte array length\r\nconst RANDOM_BYTE_ARR_LENGTH = 32;\r\n\r\n/**\r\n * This file defines APIs to generate PKCE codes and code verifiers.\r\n */\r\n\r\n/**\r\n * Generates PKCE Codes. See the RFC for more information: https://tools.ietf.org/html/rfc7636\r\n */\r\nexport async function generatePkceCodes(\r\n performanceClient: IPerformanceClient,\r\n logger: Logger,\r\n correlationId: string\r\n): Promise {\r\n performanceClient.addQueueMeasurement(\r\n PerformanceEvents.GeneratePkceCodes,\r\n correlationId\r\n );\r\n const codeVerifier = invoke(\r\n generateCodeVerifier,\r\n PerformanceEvents.GenerateCodeVerifier,\r\n logger,\r\n performanceClient,\r\n correlationId\r\n )(performanceClient, logger, correlationId);\r\n const codeChallenge = await invokeAsync(\r\n generateCodeChallengeFromVerifier,\r\n PerformanceEvents.GenerateCodeChallengeFromVerifier,\r\n logger,\r\n performanceClient,\r\n correlationId\r\n )(codeVerifier, performanceClient, logger, correlationId);\r\n return {\r\n verifier: codeVerifier,\r\n challenge: codeChallenge,\r\n };\r\n}\r\n\r\n/**\r\n * Generates a random 32 byte buffer and returns the base64\r\n * encoded string to be used as a PKCE Code Verifier\r\n */\r\nfunction generateCodeVerifier(\r\n performanceClient: IPerformanceClient,\r\n logger: Logger,\r\n correlationId: string\r\n): string {\r\n try {\r\n // Generate random values as utf-8\r\n const buffer: Uint8Array = new Uint8Array(RANDOM_BYTE_ARR_LENGTH);\r\n invoke(\r\n getRandomValues,\r\n PerformanceEvents.GetRandomValues,\r\n logger,\r\n performanceClient,\r\n correlationId\r\n )(buffer);\r\n // encode verifier as base64\r\n const pkceCodeVerifierB64: string = urlEncodeArr(buffer);\r\n return pkceCodeVerifierB64;\r\n } catch (e) {\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.pkceNotCreated);\r\n }\r\n}\r\n\r\n/**\r\n * Creates a base64 encoded PKCE Code Challenge string from the\r\n * hash created from the PKCE Code Verifier supplied\r\n */\r\nasync function generateCodeChallengeFromVerifier(\r\n pkceCodeVerifier: string,\r\n performanceClient: IPerformanceClient,\r\n logger: Logger,\r\n correlationId: string\r\n): Promise {\r\n performanceClient.addQueueMeasurement(\r\n PerformanceEvents.GenerateCodeChallengeFromVerifier,\r\n correlationId\r\n );\r\n try {\r\n // hashed verifier\r\n const pkceHashedCodeVerifier = await invokeAsync(\r\n sha256Digest,\r\n PerformanceEvents.Sha256Digest,\r\n logger,\r\n performanceClient,\r\n correlationId\r\n )(pkceCodeVerifier, performanceClient, correlationId);\r\n // encode hash as base64\r\n return urlEncodeArr(new Uint8Array(pkceHashedCodeVerifier));\r\n } catch (e) {\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.pkceNotCreated);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n PlatformAuthConstants,\r\n NativeExtensionMethod,\r\n} from \"../../utils/BrowserConstants.js\";\r\nimport {\r\n Logger,\r\n AuthError,\r\n createAuthError,\r\n AuthErrorCodes,\r\n InProgressPerformanceEvent,\r\n PerformanceEvents,\r\n IPerformanceClient,\r\n} from \"@azure/msal-common/browser\";\r\nimport {\r\n NativeExtensionRequest,\r\n NativeExtensionRequestBody,\r\n PlatformAuthRequest,\r\n} from \"./PlatformAuthRequest.js\";\r\nimport { createNativeAuthError } from \"../../error/NativeAuthError.js\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../../error/BrowserAuthError.js\";\r\nimport { createNewGuid } from \"../../crypto/BrowserCrypto.js\";\r\nimport { PlatformAuthResponse } from \"./PlatformAuthResponse.js\";\r\nimport { IPlatformAuthHandler } from \"./IPlatformAuthHandler.js\";\r\n\r\ntype ResponseResolvers = {\r\n resolve: (value: T | PromiseLike) => void;\r\n reject: (\r\n value: AuthError | Error | PromiseLike | PromiseLike\r\n ) => void;\r\n};\r\n\r\nexport class PlatformAuthExtensionHandler implements IPlatformAuthHandler {\r\n private extensionId: string | undefined;\r\n private extensionVersion: string | undefined;\r\n private logger: Logger;\r\n private readonly handshakeTimeoutMs: number;\r\n private timeoutId: number | undefined;\r\n private resolvers: Map>;\r\n private handshakeResolvers: Map>;\r\n private messageChannel: MessageChannel;\r\n private readonly windowListener: (event: MessageEvent) => void;\r\n private readonly performanceClient: IPerformanceClient;\r\n private readonly handshakeEvent: InProgressPerformanceEvent;\r\n platformAuthType: string;\r\n\r\n constructor(\r\n logger: Logger,\r\n handshakeTimeoutMs: number,\r\n performanceClient: IPerformanceClient,\r\n extensionId?: string\r\n ) {\r\n this.logger = logger;\r\n this.handshakeTimeoutMs = handshakeTimeoutMs;\r\n this.extensionId = extensionId;\r\n this.resolvers = new Map(); // Used for non-handshake messages\r\n this.handshakeResolvers = new Map(); // Used for handshake messages\r\n this.messageChannel = new MessageChannel();\r\n this.windowListener = this.onWindowMessage.bind(this); // Window event callback doesn't have access to 'this' unless it's bound\r\n this.performanceClient = performanceClient;\r\n this.handshakeEvent = performanceClient.startMeasurement(\r\n PerformanceEvents.NativeMessageHandlerHandshake\r\n );\r\n this.platformAuthType =\r\n PlatformAuthConstants.PLATFORM_EXTENSION_PROVIDER;\r\n }\r\n\r\n /**\r\n * Sends a given message to the extension and resolves with the extension response\r\n * @param request\r\n */\r\n async sendMessage(\r\n request: PlatformAuthRequest\r\n ): Promise {\r\n this.logger.trace(this.platformAuthType + \" - sendMessage called.\");\r\n\r\n // fall back to native calls\r\n const messageBody: NativeExtensionRequestBody = {\r\n method: NativeExtensionMethod.GetToken,\r\n request: request,\r\n };\r\n\r\n const req: NativeExtensionRequest = {\r\n channel: PlatformAuthConstants.CHANNEL_ID,\r\n extensionId: this.extensionId,\r\n responseId: createNewGuid(),\r\n body: messageBody,\r\n };\r\n\r\n this.logger.trace(\r\n this.platformAuthType + \" - Sending request to browser extension\"\r\n );\r\n this.logger.tracePii(\r\n this.platformAuthType +\r\n ` - Sending request to browser extension: ${JSON.stringify(\r\n req\r\n )}`\r\n );\r\n this.messageChannel.port1.postMessage(req);\r\n\r\n const response: object = await new Promise((resolve, reject) => {\r\n this.resolvers.set(req.responseId, { resolve, reject });\r\n });\r\n\r\n const validatedResponse: PlatformAuthResponse =\r\n this.validatePlatformBrokerResponse(response);\r\n\r\n return validatedResponse;\r\n }\r\n\r\n /**\r\n * Returns an instance of the MessageHandler that has successfully established a connection with an extension\r\n * @param {Logger} logger\r\n * @param {number} handshakeTimeoutMs\r\n * @param {IPerformanceClient} performanceClient\r\n * @param {ICrypto} crypto\r\n */\r\n static async createProvider(\r\n logger: Logger,\r\n handshakeTimeoutMs: number,\r\n performanceClient: IPerformanceClient\r\n ): Promise {\r\n logger.trace(\"PlatformAuthExtensionHandler - createProvider called.\");\r\n\r\n try {\r\n const preferredProvider = new PlatformAuthExtensionHandler(\r\n logger,\r\n handshakeTimeoutMs,\r\n performanceClient,\r\n PlatformAuthConstants.PREFERRED_EXTENSION_ID\r\n );\r\n await preferredProvider.sendHandshakeRequest();\r\n return preferredProvider;\r\n } catch (e) {\r\n // If preferred extension fails for whatever reason, fallback to using any installed extension\r\n const backupProvider = new PlatformAuthExtensionHandler(\r\n logger,\r\n handshakeTimeoutMs,\r\n performanceClient\r\n );\r\n await backupProvider.sendHandshakeRequest();\r\n return backupProvider;\r\n }\r\n }\r\n\r\n /**\r\n * Send handshake request helper.\r\n */\r\n private async sendHandshakeRequest(): Promise {\r\n this.logger.trace(\r\n this.platformAuthType + \" - sendHandshakeRequest called.\"\r\n );\r\n // Register this event listener before sending handshake\r\n window.addEventListener(\"message\", this.windowListener, false); // false is important, because content script message processing should work first\r\n\r\n const req: NativeExtensionRequest = {\r\n channel: PlatformAuthConstants.CHANNEL_ID,\r\n extensionId: this.extensionId,\r\n responseId: createNewGuid(),\r\n body: {\r\n method: NativeExtensionMethod.HandshakeRequest,\r\n },\r\n };\r\n this.handshakeEvent.add({\r\n extensionId: this.extensionId,\r\n extensionHandshakeTimeoutMs: this.handshakeTimeoutMs,\r\n });\r\n\r\n this.messageChannel.port1.onmessage = (event) => {\r\n this.onChannelMessage(event);\r\n };\r\n\r\n window.postMessage(req, window.origin, [this.messageChannel.port2]);\r\n\r\n return new Promise((resolve, reject) => {\r\n this.handshakeResolvers.set(req.responseId, { resolve, reject });\r\n this.timeoutId = window.setTimeout(() => {\r\n /*\r\n * Throw an error if neither HandshakeResponse nor original Handshake request are received in a reasonable timeframe.\r\n * This typically suggests an event handler stopped propagation of the Handshake request but did not respond to it on the MessageChannel port\r\n */\r\n window.removeEventListener(\r\n \"message\",\r\n this.windowListener,\r\n false\r\n );\r\n this.messageChannel.port1.close();\r\n this.messageChannel.port2.close();\r\n this.handshakeEvent.end({\r\n extensionHandshakeTimedOut: true,\r\n success: false,\r\n });\r\n reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.nativeHandshakeTimeout\r\n )\r\n );\r\n this.handshakeResolvers.delete(req.responseId);\r\n }, this.handshakeTimeoutMs); // Use a reasonable timeout in milliseconds here\r\n });\r\n }\r\n\r\n /**\r\n * Invoked when a message is posted to the window. If a handshake request is received it means the extension is not installed.\r\n * @param event\r\n */\r\n private onWindowMessage(event: MessageEvent): void {\r\n this.logger.trace(this.platformAuthType + \" - onWindowMessage called\");\r\n // We only accept messages from ourselves\r\n if (event.source !== window) {\r\n return;\r\n }\r\n\r\n const request = event.data;\r\n\r\n if (\r\n !request.channel ||\r\n request.channel !== PlatformAuthConstants.CHANNEL_ID\r\n ) {\r\n return;\r\n }\r\n\r\n if (request.extensionId && request.extensionId !== this.extensionId) {\r\n return;\r\n }\r\n\r\n if (request.body.method === NativeExtensionMethod.HandshakeRequest) {\r\n const handshakeResolver = this.handshakeResolvers.get(\r\n request.responseId\r\n );\r\n /*\r\n * Filter out responses with no matched resolvers sooner to keep channel ports open while waiting for\r\n * the proper response.\r\n */\r\n if (!handshakeResolver) {\r\n this.logger.trace(\r\n this.platformAuthType +\r\n `.onWindowMessage - resolver can't be found for request ${request.responseId}`\r\n );\r\n return;\r\n }\r\n\r\n // If we receive this message back it means no extension intercepted the request, meaning no extension supporting handshake protocol is installed\r\n this.logger.verbose(\r\n request.extensionId\r\n ? `Extension with id: ${request.extensionId} not installed`\r\n : \"No extension installed\"\r\n );\r\n clearTimeout(this.timeoutId);\r\n this.messageChannel.port1.close();\r\n this.messageChannel.port2.close();\r\n window.removeEventListener(\"message\", this.windowListener, false);\r\n this.handshakeEvent.end({\r\n success: false,\r\n extensionInstalled: false,\r\n });\r\n handshakeResolver.reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.nativeExtensionNotInstalled\r\n )\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Invoked when a message is received from the extension on the MessageChannel port\r\n * @param event\r\n */\r\n private onChannelMessage(event: MessageEvent): void {\r\n this.logger.trace(\r\n this.platformAuthType + \" - onChannelMessage called.\"\r\n );\r\n const request = event.data;\r\n\r\n const resolver = this.resolvers.get(request.responseId);\r\n const handshakeResolver = this.handshakeResolvers.get(\r\n request.responseId\r\n );\r\n\r\n try {\r\n const method = request.body.method;\r\n\r\n if (method === NativeExtensionMethod.Response) {\r\n if (!resolver) {\r\n return;\r\n }\r\n const response = request.body.response;\r\n this.logger.trace(\r\n this.platformAuthType +\r\n \" - Received response from browser extension\"\r\n );\r\n this.logger.tracePii(\r\n this.platformAuthType +\r\n ` - Received response from browser extension: ${JSON.stringify(\r\n response\r\n )}`\r\n );\r\n if (response.status !== \"Success\") {\r\n resolver.reject(\r\n createNativeAuthError(\r\n response.code,\r\n response.description,\r\n response.ext\r\n )\r\n );\r\n } else if (response.result) {\r\n if (\r\n response.result[\"code\"] &&\r\n response.result[\"description\"]\r\n ) {\r\n resolver.reject(\r\n createNativeAuthError(\r\n response.result[\"code\"],\r\n response.result[\"description\"],\r\n response.result[\"ext\"]\r\n )\r\n );\r\n } else {\r\n resolver.resolve(response.result);\r\n }\r\n } else {\r\n throw createAuthError(\r\n AuthErrorCodes.unexpectedError,\r\n \"Event does not contain result.\"\r\n );\r\n }\r\n this.resolvers.delete(request.responseId);\r\n } else if (method === NativeExtensionMethod.HandshakeResponse) {\r\n if (!handshakeResolver) {\r\n this.logger.trace(\r\n this.platformAuthType +\r\n `.onChannelMessage - resolver can't be found for request ${request.responseId}`\r\n );\r\n return;\r\n }\r\n clearTimeout(this.timeoutId); // Clear setTimeout\r\n window.removeEventListener(\r\n \"message\",\r\n this.windowListener,\r\n false\r\n ); // Remove 'No extension' listener\r\n this.extensionId = request.extensionId;\r\n this.extensionVersion = request.body.version;\r\n this.logger.verbose(\r\n this.platformAuthType +\r\n ` - Received HandshakeResponse from extension: ${this.extensionId}`\r\n );\r\n this.handshakeEvent.end({\r\n extensionInstalled: true,\r\n success: true,\r\n });\r\n\r\n handshakeResolver.resolve();\r\n this.handshakeResolvers.delete(request.responseId);\r\n }\r\n // Do nothing if method is not Response or HandshakeResponse\r\n } catch (err) {\r\n this.logger.error(\"Error parsing response from WAM Extension\");\r\n this.logger.errorPii(\r\n `Error parsing response from WAM Extension: ${err as string}`\r\n );\r\n this.logger.errorPii(`Unable to parse ${event}`);\r\n\r\n if (resolver) {\r\n resolver.reject(err as AuthError);\r\n } else if (handshakeResolver) {\r\n handshakeResolver.reject(err as AuthError);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Validates native platform response before processing\r\n * @param response\r\n */\r\n private validatePlatformBrokerResponse(\r\n response: object\r\n ): PlatformAuthResponse {\r\n if (\r\n response.hasOwnProperty(\"access_token\") &&\r\n response.hasOwnProperty(\"id_token\") &&\r\n response.hasOwnProperty(\"client_info\") &&\r\n response.hasOwnProperty(\"account\") &&\r\n response.hasOwnProperty(\"scope\") &&\r\n response.hasOwnProperty(\"expires_in\")\r\n ) {\r\n return response as PlatformAuthResponse;\r\n } else {\r\n throw createAuthError(\r\n AuthErrorCodes.unexpectedError,\r\n \"Response missing expected properties.\"\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Returns the Id for the browser extension this handler is communicating with\r\n * @returns\r\n */\r\n getExtensionId(): string | undefined {\r\n return this.extensionId;\r\n }\r\n\r\n /**\r\n * Returns the version for the browser extension this handler is communicating with\r\n * @returns\r\n */\r\n getExtensionVersion(): string | undefined {\r\n return this.extensionVersion;\r\n }\r\n\r\n getExtensionName(): string | undefined {\r\n return this.getExtensionId() ===\r\n PlatformAuthConstants.PREFERRED_EXTENSION_ID\r\n ? \"chrome\"\r\n : this.getExtensionId()?.length\r\n ? \"unknown\"\r\n : undefined;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n Logger,\r\n createAuthError,\r\n AuthErrorCodes,\r\n IPerformanceClient,\r\n StringDict,\r\n} from \"@azure/msal-common/browser\";\r\nimport {\r\n DOMExtraParameters,\r\n PlatformAuthRequest,\r\n PlatformDOMTokenRequest,\r\n} from \"./PlatformAuthRequest.js\";\r\nimport { PlatformAuthConstants } from \"../../utils/BrowserConstants.js\";\r\nimport {\r\n PlatformAuthResponse,\r\n PlatformDOMTokenResponse,\r\n} from \"./PlatformAuthResponse.js\";\r\nimport { createNativeAuthError } from \"../../error/NativeAuthError.js\";\r\nimport { IPlatformAuthHandler } from \"./IPlatformAuthHandler.js\";\r\n\r\nexport class PlatformAuthDOMHandler implements IPlatformAuthHandler {\r\n protected logger: Logger;\r\n protected performanceClient: IPerformanceClient;\r\n protected correlationId: string;\r\n platformAuthType: string;\r\n\r\n constructor(\r\n logger: Logger,\r\n performanceClient: IPerformanceClient,\r\n correlationId: string\r\n ) {\r\n this.logger = logger;\r\n this.performanceClient = performanceClient;\r\n this.correlationId = correlationId;\r\n this.platformAuthType = PlatformAuthConstants.PLATFORM_DOM_PROVIDER;\r\n }\r\n\r\n static async createProvider(\r\n logger: Logger,\r\n performanceClient: IPerformanceClient,\r\n correlationId: string\r\n ): Promise {\r\n logger.trace(\"PlatformAuthDOMHandler: createProvider called\");\r\n\r\n // @ts-ignore\r\n if (window.navigator?.platformAuthentication) {\r\n const supportedContracts =\r\n // @ts-ignore\r\n await window.navigator.platformAuthentication.getSupportedContracts(\r\n PlatformAuthConstants.MICROSOFT_ENTRA_BROKERID\r\n );\r\n if (\r\n supportedContracts?.includes(\r\n PlatformAuthConstants.PLATFORM_DOM_APIS\r\n )\r\n ) {\r\n logger.trace(\"Platform auth api available in DOM\");\r\n return new PlatformAuthDOMHandler(\r\n logger,\r\n performanceClient,\r\n correlationId\r\n );\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n /**\r\n * Returns the Id for the broker extension this handler is communicating with\r\n * @returns\r\n */\r\n getExtensionId(): string {\r\n return PlatformAuthConstants.MICROSOFT_ENTRA_BROKERID;\r\n }\r\n\r\n getExtensionVersion(): string | undefined {\r\n return \"\";\r\n }\r\n\r\n getExtensionName(): string | undefined {\r\n return PlatformAuthConstants.DOM_API_NAME;\r\n }\r\n\r\n /**\r\n * Send token request to platform broker via browser DOM API\r\n * @param request\r\n * @returns\r\n */\r\n async sendMessage(\r\n request: PlatformAuthRequest\r\n ): Promise {\r\n this.logger.trace(\r\n this.platformAuthType + \" - Sending request to browser DOM API\"\r\n );\r\n\r\n try {\r\n const platformDOMRequest: PlatformDOMTokenRequest =\r\n this.initializePlatformDOMRequest(request);\r\n const response: object =\r\n // @ts-ignore\r\n await window.navigator.platformAuthentication.executeGetToken(\r\n platformDOMRequest\r\n );\r\n return this.validatePlatformBrokerResponse(response);\r\n } catch (e) {\r\n this.logger.error(\r\n this.platformAuthType + \" - executeGetToken DOM API error\"\r\n );\r\n throw e;\r\n }\r\n }\r\n\r\n private initializePlatformDOMRequest(\r\n request: PlatformAuthRequest\r\n ): PlatformDOMTokenRequest {\r\n this.logger.trace(\r\n this.platformAuthType + \" - initializeNativeDOMRequest called\"\r\n );\r\n\r\n const {\r\n accountId,\r\n clientId,\r\n authority,\r\n scope,\r\n redirectUri,\r\n correlationId,\r\n state,\r\n storeInCache,\r\n embeddedClientId,\r\n extraParameters,\r\n ...remainingProperties\r\n } = request;\r\n\r\n const validExtraParameters: DOMExtraParameters =\r\n this.getDOMExtraParams(remainingProperties);\r\n\r\n const platformDOMRequest: PlatformDOMTokenRequest = {\r\n accountId: accountId,\r\n brokerId: this.getExtensionId(),\r\n authority: authority,\r\n clientId: clientId,\r\n correlationId: correlationId || this.correlationId,\r\n extraParameters: { ...extraParameters, ...validExtraParameters },\r\n isSecurityTokenService: false,\r\n redirectUri: redirectUri,\r\n scope: scope,\r\n state: state,\r\n storeInCache: storeInCache,\r\n embeddedClientId: embeddedClientId,\r\n };\r\n\r\n return platformDOMRequest;\r\n }\r\n\r\n private validatePlatformBrokerResponse(\r\n response: object\r\n ): PlatformAuthResponse {\r\n if (response.hasOwnProperty(\"isSuccess\")) {\r\n if (\r\n response.hasOwnProperty(\"accessToken\") &&\r\n response.hasOwnProperty(\"idToken\") &&\r\n response.hasOwnProperty(\"clientInfo\") &&\r\n response.hasOwnProperty(\"account\") &&\r\n response.hasOwnProperty(\"scopes\") &&\r\n response.hasOwnProperty(\"expiresIn\")\r\n ) {\r\n this.logger.trace(\r\n this.platformAuthType +\r\n \" - platform broker returned successful and valid response\"\r\n );\r\n return this.convertToPlatformBrokerResponse(\r\n response as PlatformDOMTokenResponse\r\n );\r\n } else if (response.hasOwnProperty(\"error\")) {\r\n const errorResponse = response as PlatformDOMTokenResponse;\r\n if (\r\n errorResponse.isSuccess === false &&\r\n errorResponse.error &&\r\n errorResponse.error.code\r\n ) {\r\n this.logger.trace(\r\n this.platformAuthType +\r\n \" - platform broker returned error response\"\r\n );\r\n throw createNativeAuthError(\r\n errorResponse.error.code,\r\n errorResponse.error.description,\r\n {\r\n error: parseInt(errorResponse.error.errorCode),\r\n protocol_error: errorResponse.error.protocolError,\r\n status: errorResponse.error.status,\r\n properties: errorResponse.error.properties,\r\n }\r\n );\r\n }\r\n }\r\n }\r\n throw createAuthError(\r\n AuthErrorCodes.unexpectedError,\r\n \"Response missing expected properties.\"\r\n );\r\n }\r\n\r\n private convertToPlatformBrokerResponse(\r\n response: PlatformDOMTokenResponse\r\n ): PlatformAuthResponse {\r\n this.logger.trace(\r\n this.platformAuthType + \" - convertToNativeResponse called\"\r\n );\r\n const nativeResponse: PlatformAuthResponse = {\r\n access_token: response.accessToken,\r\n id_token: response.idToken,\r\n client_info: response.clientInfo,\r\n account: response.account,\r\n expires_in: response.expiresIn,\r\n scope: response.scopes,\r\n state: response.state || \"\",\r\n properties: response.properties || {},\r\n extendedLifetimeToken: response.extendedLifetimeToken ?? false,\r\n shr: response.proofOfPossessionPayload,\r\n };\r\n\r\n return nativeResponse;\r\n }\r\n\r\n private getDOMExtraParams(\r\n extraParameters: Record\r\n ): DOMExtraParameters {\r\n const stringifiedParams = Object.entries(extraParameters).reduce(\r\n (record, [key, value]) => {\r\n record[key] = String(value);\r\n return record;\r\n },\r\n {} as StringDict\r\n );\r\n\r\n const validExtraParams: DOMExtraParameters = {\r\n ...stringifiedParams,\r\n };\r\n\r\n return validExtraParams;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n LoggerOptions,\r\n IPerformanceClient,\r\n Logger,\r\n AuthenticationScheme,\r\n StubPerformanceClient,\r\n} from \"@azure/msal-common/browser\";\r\nimport { name, version } from \"../../packageMetadata.js\";\r\nimport {\r\n BrowserConfiguration,\r\n DEFAULT_NATIVE_BROKER_HANDSHAKE_TIMEOUT_MS,\r\n} from \"../../config/Configuration.js\";\r\nimport { PlatformAuthExtensionHandler } from \"./PlatformAuthExtensionHandler.js\";\r\nimport { IPlatformAuthHandler } from \"./IPlatformAuthHandler.js\";\r\nimport { PlatformAuthDOMHandler } from \"./PlatformAuthDOMHandler.js\";\r\nimport { createNewGuid } from \"../../crypto/BrowserCrypto.js\";\r\nimport { BrowserCacheLocation } from \"../../utils/BrowserConstants.js\";\r\nimport { PLATFORM_AUTH_DOM_SUPPORT } from \"../../cache/CacheKeys.js\";\r\n\r\n/**\r\n * Checks if the platform broker is available in the current environment.\r\n * @param loggerOptions\r\n * @param perfClient\r\n * @returns\r\n */\r\nexport async function isPlatformBrokerAvailable(\r\n loggerOptions?: LoggerOptions,\r\n perfClient?: IPerformanceClient,\r\n correlationId?: string\r\n): Promise {\r\n const logger = new Logger(loggerOptions || {}, name, version);\r\n\r\n logger.trace(\"isPlatformBrokerAvailable called\");\r\n\r\n const performanceClient = perfClient || new StubPerformanceClient();\r\n\r\n if (typeof window === \"undefined\") {\r\n logger.trace(\"Non-browser environment detected, returning false\");\r\n return false;\r\n }\r\n\r\n return !!(await getPlatformAuthProvider(\r\n logger,\r\n performanceClient,\r\n correlationId || createNewGuid()\r\n ));\r\n}\r\n\r\nexport async function getPlatformAuthProvider(\r\n logger: Logger,\r\n performanceClient: IPerformanceClient,\r\n correlationId: string,\r\n nativeBrokerHandshakeTimeout?: number\r\n): Promise {\r\n logger.trace(\"getPlatformAuthProvider called\", correlationId);\r\n\r\n const enablePlatformBrokerDOMSupport = isDomEnabledForPlatformAuth();\r\n\r\n logger.trace(\r\n \"Has client allowed platform auth via DOM API: \" +\r\n enablePlatformBrokerDOMSupport\r\n );\r\n let platformAuthProvider: IPlatformAuthHandler | undefined;\r\n try {\r\n if (enablePlatformBrokerDOMSupport) {\r\n // Check if DOM platform API is supported first\r\n platformAuthProvider = await PlatformAuthDOMHandler.createProvider(\r\n logger,\r\n performanceClient,\r\n correlationId\r\n );\r\n }\r\n if (!platformAuthProvider) {\r\n logger.trace(\r\n \"Platform auth via DOM API not available, checking for extension\"\r\n );\r\n /*\r\n * If DOM APIs are not available, check if browser extension is available.\r\n * Platform authentication via DOM APIs is preferred over extension APIs.\r\n */\r\n platformAuthProvider =\r\n await PlatformAuthExtensionHandler.createProvider(\r\n logger,\r\n nativeBrokerHandshakeTimeout ||\r\n DEFAULT_NATIVE_BROKER_HANDSHAKE_TIMEOUT_MS,\r\n performanceClient\r\n );\r\n }\r\n } catch (e) {\r\n logger.trace(\"Platform auth not available\", e as string);\r\n }\r\n return platformAuthProvider;\r\n}\r\n\r\n/**\r\n * Returns true if the DOM API support for platform auth is enabled in session storage\r\n * @returns boolean\r\n * @deprecated\r\n */\r\nexport function isDomEnabledForPlatformAuth(): boolean {\r\n let sessionStorage: Storage | undefined;\r\n try {\r\n sessionStorage = window[BrowserCacheLocation.SessionStorage];\r\n // Mute errors if it's a non-browser environment or cookies are blocked.\r\n return sessionStorage?.getItem(PLATFORM_AUTH_DOM_SUPPORT) === \"true\";\r\n } catch (e) {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Returns boolean indicating whether or not the request should attempt to use native broker\r\n * @param logger\r\n * @param config\r\n * @param platformAuthProvider\r\n * @param authenticationScheme\r\n */\r\nexport function isPlatformAuthAllowed(\r\n config: BrowserConfiguration,\r\n logger: Logger,\r\n platformAuthProvider?: IPlatformAuthHandler,\r\n authenticationScheme?: AuthenticationScheme\r\n): boolean {\r\n logger.trace(\"isPlatformAuthAllowed called\");\r\n if (!config.system.allowPlatformBroker) {\r\n logger.trace(\r\n \"isPlatformAuthAllowed: allowPlatformBroker is not enabled, returning false\"\r\n );\r\n // Developer disabled WAM\r\n return false;\r\n }\r\n\r\n if (!platformAuthProvider) {\r\n logger.trace(\r\n \"isPlatformAuthAllowed: Platform auth provider is not initialized, returning false\"\r\n );\r\n // Platform broker auth providers are not available\r\n return false;\r\n }\r\n\r\n if (authenticationScheme) {\r\n switch (authenticationScheme) {\r\n case AuthenticationScheme.BEARER:\r\n case AuthenticationScheme.POP:\r\n logger.trace(\r\n \"isPlatformAuthAllowed: authenticationScheme is supported, returning true\"\r\n );\r\n return true;\r\n default:\r\n logger.trace(\r\n \"isPlatformAuthAllowed: authenticationScheme is not supported, returning false\"\r\n );\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n AuthorizationCodeClient,\r\n CommonEndSessionRequest,\r\n UrlString,\r\n AuthError,\r\n OIDC_DEFAULT_SCOPES,\r\n PerformanceEvents,\r\n IPerformanceClient,\r\n Logger,\r\n ICrypto,\r\n ProtocolMode,\r\n ServerResponseType,\r\n invokeAsync,\r\n invoke,\r\n PkceCodes,\r\n CommonAuthorizationUrlRequest,\r\n HttpMethod,\r\n} from \"@azure/msal-common/browser\";\r\nimport { StandardInteractionClient } from \"./StandardInteractionClient.js\";\r\nimport { EventType } from \"../event/EventType.js\";\r\nimport {\r\n InteractionType,\r\n ApiId,\r\n BrowserConstants,\r\n} from \"../utils/BrowserConstants.js\";\r\nimport { EndSessionPopupRequest } from \"../request/EndSessionPopupRequest.js\";\r\nimport { NavigationOptions } from \"../navigation/NavigationOptions.js\";\r\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\r\nimport { PopupRequest } from \"../request/PopupRequest.js\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\r\nimport { EventHandler } from \"../event/EventHandler.js\";\r\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\r\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\r\nimport { PopupWindowAttributes } from \"../request/PopupWindowAttributes.js\";\r\nimport { EventError } from \"../event/EventMessage.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport * as ResponseHandler from \"../response/ResponseHandler.js\";\r\nimport * as Authorize from \"../protocol/Authorize.js\";\r\nimport { generatePkceCodes } from \"../crypto/PkceGenerator.js\";\r\nimport { isPlatformAuthAllowed } from \"../broker/nativeBroker/PlatformAuthProvider.js\";\r\nimport { generateEarKey } from \"../crypto/BrowserCrypto.js\";\r\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\r\nimport { validateRequestMethod } from \"../request/RequestHelpers.js\";\r\n\r\nexport type PopupParams = {\r\n popup?: Window | null;\r\n popupName: string;\r\n popupWindowAttributes: PopupWindowAttributes;\r\n popupWindowParent: Window;\r\n};\r\n\r\nexport class PopupClient extends StandardInteractionClient {\r\n private currentWindow: Window | undefined;\r\n protected nativeStorage: BrowserCacheManager;\r\n\r\n constructor(\r\n config: BrowserConfiguration,\r\n storageImpl: BrowserCacheManager,\r\n browserCrypto: ICrypto,\r\n logger: Logger,\r\n eventHandler: EventHandler,\r\n navigationClient: INavigationClient,\r\n performanceClient: IPerformanceClient,\r\n nativeStorageImpl: BrowserCacheManager,\r\n platformAuthHandler?: IPlatformAuthHandler,\r\n correlationId?: string\r\n ) {\r\n super(\r\n config,\r\n storageImpl,\r\n browserCrypto,\r\n logger,\r\n eventHandler,\r\n navigationClient,\r\n performanceClient,\r\n platformAuthHandler,\r\n correlationId\r\n );\r\n // Properly sets this reference for the unload event.\r\n this.unloadWindow = this.unloadWindow.bind(this);\r\n this.nativeStorage = nativeStorageImpl;\r\n this.eventHandler = eventHandler;\r\n }\r\n\r\n /**\r\n * Acquires tokens by opening a popup window to the /authorize endpoint of the authority\r\n * @param request\r\n * @param pkceCodes\r\n */\r\n acquireToken(\r\n request: PopupRequest,\r\n pkceCodes?: PkceCodes\r\n ): Promise {\r\n let popupParams: PopupParams | undefined = undefined;\r\n try {\r\n const popupName = this.generatePopupName(\r\n request.scopes || OIDC_DEFAULT_SCOPES,\r\n request.authority || this.config.auth.authority\r\n );\r\n popupParams = {\r\n popupName,\r\n popupWindowAttributes: request.popupWindowAttributes || {},\r\n popupWindowParent: request.popupWindowParent ?? window,\r\n };\r\n\r\n this.performanceClient.addFields(\r\n { isAsyncPopup: this.config.system.asyncPopups },\r\n this.correlationId\r\n );\r\n\r\n // asyncPopups flag is true. Acquires token without first opening popup. Popup will be opened later asynchronously.\r\n if (this.config.system.asyncPopups) {\r\n this.logger.verbose(\"asyncPopups set to true, acquiring token\");\r\n // Passes on popup position and dimensions if in request\r\n return this.acquireTokenPopupAsync(\r\n request,\r\n popupParams,\r\n pkceCodes\r\n );\r\n } else {\r\n // Pre-validate request method to avoid opening popup if the request is invalid\r\n const validatedRequest: PopupRequest = {\r\n ...request,\r\n httpMethod: validateRequestMethod(\r\n request,\r\n this.config.auth.protocolMode\r\n ),\r\n };\r\n // asyncPopups flag is set to false. Opens popup before acquiring token.\r\n this.logger.verbose(\r\n \"asyncPopup set to false, opening popup before acquiring token\"\r\n );\r\n popupParams.popup = this.openSizedPopup(\r\n \"about:blank\",\r\n popupParams\r\n );\r\n return this.acquireTokenPopupAsync(\r\n validatedRequest,\r\n popupParams,\r\n pkceCodes\r\n );\r\n }\r\n } catch (e) {\r\n return Promise.reject(e);\r\n }\r\n }\r\n\r\n /**\r\n * Clears local cache for the current user then opens a popup window prompting the user to sign-out of the server\r\n * @param logoutRequest\r\n */\r\n logout(logoutRequest?: EndSessionPopupRequest): Promise {\r\n try {\r\n this.logger.verbose(\"logoutPopup called\");\r\n const validLogoutRequest =\r\n this.initializeLogoutRequest(logoutRequest);\r\n const popupParams: PopupParams = {\r\n popupName: this.generateLogoutPopupName(validLogoutRequest),\r\n popupWindowAttributes:\r\n logoutRequest?.popupWindowAttributes || {},\r\n popupWindowParent: logoutRequest?.popupWindowParent ?? window,\r\n };\r\n const authority = logoutRequest && logoutRequest.authority;\r\n const mainWindowRedirectUri =\r\n logoutRequest && logoutRequest.mainWindowRedirectUri;\r\n\r\n // asyncPopups flag is true. Acquires token without first opening popup. Popup will be opened later asynchronously.\r\n if (this.config.system.asyncPopups) {\r\n this.logger.verbose(\"asyncPopups set to true\");\r\n // Passes on popup position and dimensions if in request\r\n return this.logoutPopupAsync(\r\n validLogoutRequest,\r\n popupParams,\r\n authority,\r\n mainWindowRedirectUri\r\n );\r\n } else {\r\n // asyncPopups flag is set to false. Opens popup before logging out.\r\n this.logger.verbose(\"asyncPopup set to false, opening popup\");\r\n popupParams.popup = this.openSizedPopup(\r\n \"about:blank\",\r\n popupParams\r\n );\r\n return this.logoutPopupAsync(\r\n validLogoutRequest,\r\n popupParams,\r\n authority,\r\n mainWindowRedirectUri\r\n );\r\n }\r\n } catch (e) {\r\n // Since this function is synchronous we need to reject\r\n return Promise.reject(e);\r\n }\r\n }\r\n\r\n /**\r\n * Helper which obtains an access_token for your API via opening a popup window in the user's browser\r\n * @param request\r\n * @param popupParams\r\n * @param pkceCodes\r\n *\r\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\r\n */\r\n protected async acquireTokenPopupAsync(\r\n request: PopupRequest,\r\n popupParams: PopupParams,\r\n pkceCodes?: PkceCodes\r\n ): Promise {\r\n this.logger.verbose(\"acquireTokenPopupAsync called\");\r\n\r\n const validRequest = await invokeAsync(\r\n this.initializeAuthorizationRequest.bind(this),\r\n PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(request, InteractionType.Popup);\r\n\r\n /*\r\n * Skip pre-connect for async popups to reduce time between user interaction and popup window creation to avoid\r\n * popup from being blocked by browsers with shorter popup timers\r\n */\r\n if (popupParams.popup) {\r\n BrowserUtils.preconnect(validRequest.authority);\r\n }\r\n\r\n const isPlatformBroker = isPlatformAuthAllowed(\r\n this.config,\r\n this.logger,\r\n this.platformAuthProvider,\r\n request.authenticationScheme\r\n );\r\n validRequest.platformBroker = isPlatformBroker;\r\n\r\n if (this.config.auth.protocolMode === ProtocolMode.EAR) {\r\n return this.executeEarFlow(validRequest, popupParams);\r\n } else {\r\n return this.executeCodeFlow(validRequest, popupParams, pkceCodes);\r\n }\r\n }\r\n\r\n /**\r\n * Executes auth code + PKCE flow\r\n * @param request\r\n * @param popupParams\r\n * @param pkceCodes\r\n * @returns\r\n */\r\n async executeCodeFlow(\r\n request: CommonAuthorizationUrlRequest,\r\n popupParams: PopupParams,\r\n pkceCodes?: PkceCodes\r\n ): Promise {\r\n const correlationId = request.correlationId;\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(\r\n ApiId.acquireTokenPopup\r\n );\r\n\r\n const pkce =\r\n pkceCodes ||\r\n (await invokeAsync(\r\n generatePkceCodes,\r\n PerformanceEvents.GeneratePkceCodes,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(this.performanceClient, this.logger, correlationId));\r\n\r\n const popupRequest = {\r\n ...request,\r\n codeChallenge: pkce.challenge,\r\n };\r\n\r\n try {\r\n // Initialize the client\r\n const authClient: AuthorizationCodeClient = await invokeAsync(\r\n this.createAuthCodeClient.bind(this),\r\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )({\r\n serverTelemetryManager,\r\n requestAuthority: popupRequest.authority,\r\n requestAzureCloudOptions: popupRequest.azureCloudOptions,\r\n requestExtraQueryParameters: popupRequest.extraQueryParameters,\r\n account: popupRequest.account,\r\n });\r\n\r\n if (popupRequest.httpMethod === HttpMethod.POST) {\r\n return await this.executeCodeFlowWithPost(\r\n popupRequest,\r\n popupParams,\r\n authClient,\r\n pkce.verifier\r\n );\r\n } else {\r\n // Create acquire token url.\r\n const navigateUrl = await invokeAsync(\r\n Authorize.getAuthCodeRequestUrl,\r\n PerformanceEvents.GetAuthCodeUrl,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n this.config,\r\n authClient.authority,\r\n popupRequest,\r\n this.logger,\r\n this.performanceClient\r\n );\r\n\r\n // Show the UI once the url has been created. Get the window handle for the popup.\r\n const popupWindow: Window = this.initiateAuthRequest(\r\n navigateUrl,\r\n popupParams\r\n );\r\n this.eventHandler.emitEvent(\r\n EventType.POPUP_OPENED,\r\n InteractionType.Popup,\r\n { popupWindow },\r\n null\r\n );\r\n\r\n // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.\r\n const responseString = await this.monitorPopupForHash(\r\n popupWindow,\r\n popupParams.popupWindowParent\r\n );\r\n\r\n const serverParams = invoke(\r\n ResponseHandler.deserializeResponse,\r\n PerformanceEvents.DeserializeResponse,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(\r\n responseString,\r\n this.config.auth.OIDCOptions.serverResponseType,\r\n this.logger\r\n );\r\n\r\n return await invokeAsync(\r\n Authorize.handleResponseCode,\r\n PerformanceEvents.HandleResponseCode,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n request,\r\n serverParams,\r\n pkce.verifier,\r\n ApiId.acquireTokenPopup,\r\n this.config,\r\n authClient,\r\n this.browserStorage,\r\n this.nativeStorage,\r\n this.eventHandler,\r\n this.logger,\r\n this.performanceClient,\r\n this.platformAuthProvider\r\n );\r\n }\r\n } catch (e) {\r\n // Close the synchronous popup if an error is thrown before the window unload event is registered\r\n popupParams.popup?.close();\r\n\r\n if (e instanceof AuthError) {\r\n (e as AuthError).setCorrelationId(this.correlationId);\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n }\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Executes EAR flow\r\n * @param request\r\n */\r\n async executeEarFlow(\r\n request: CommonAuthorizationUrlRequest,\r\n popupParams: PopupParams\r\n ): Promise {\r\n const correlationId = request.correlationId;\r\n // Get the frame handle for the silent request\r\n const discoveredAuthority = await invokeAsync(\r\n this.getDiscoveredAuthority.bind(this),\r\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )({\r\n requestAuthority: request.authority,\r\n requestAzureCloudOptions: request.azureCloudOptions,\r\n requestExtraQueryParameters: request.extraQueryParameters,\r\n account: request.account,\r\n });\r\n\r\n const earJwk = await invokeAsync(\r\n generateEarKey,\r\n PerformanceEvents.GenerateEarKey,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )();\r\n const popupRequest = {\r\n ...request,\r\n earJwk: earJwk,\r\n };\r\n const popupWindow =\r\n popupParams.popup || this.openPopup(\"about:blank\", popupParams);\r\n\r\n const form = await Authorize.getEARForm(\r\n popupWindow.document,\r\n this.config,\r\n discoveredAuthority,\r\n popupRequest,\r\n this.logger,\r\n this.performanceClient\r\n );\r\n form.submit();\r\n\r\n // Monitor the popup for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.\r\n const responseString = await invokeAsync(\r\n this.monitorPopupForHash.bind(this),\r\n PerformanceEvents.SilentHandlerMonitorIframeForHash,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(popupWindow, popupParams.popupWindowParent);\r\n\r\n const serverParams = invoke(\r\n ResponseHandler.deserializeResponse,\r\n PerformanceEvents.DeserializeResponse,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(\r\n responseString,\r\n this.config.auth.OIDCOptions.serverResponseType,\r\n this.logger\r\n );\r\n\r\n return invokeAsync(\r\n Authorize.handleResponseEAR,\r\n PerformanceEvents.HandleResponseEar,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n popupRequest,\r\n serverParams,\r\n ApiId.acquireTokenPopup,\r\n this.config,\r\n discoveredAuthority,\r\n this.browserStorage,\r\n this.nativeStorage,\r\n this.eventHandler,\r\n this.logger,\r\n this.performanceClient,\r\n this.platformAuthProvider\r\n );\r\n }\r\n\r\n async executeCodeFlowWithPost(\r\n request: CommonAuthorizationUrlRequest,\r\n popupParams: PopupParams,\r\n authClient: AuthorizationCodeClient,\r\n pkceVerifier: string\r\n ): Promise {\r\n const correlationId = request.correlationId;\r\n // Get the frame handle for the silent request\r\n const discoveredAuthority = await invokeAsync(\r\n this.getDiscoveredAuthority.bind(this),\r\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )({\r\n requestAuthority: request.authority,\r\n requestAzureCloudOptions: request.azureCloudOptions,\r\n requestExtraQueryParameters: request.extraQueryParameters,\r\n account: request.account,\r\n });\r\n\r\n const popupWindow =\r\n popupParams.popup || this.openPopup(\"about:blank\", popupParams);\r\n\r\n const form = await Authorize.getCodeForm(\r\n popupWindow.document,\r\n this.config,\r\n discoveredAuthority,\r\n request,\r\n this.logger,\r\n this.performanceClient\r\n );\r\n\r\n form.submit();\r\n\r\n // Monitor the popup for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.\r\n const responseString = await invokeAsync(\r\n this.monitorPopupForHash.bind(this),\r\n PerformanceEvents.SilentHandlerMonitorIframeForHash,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(popupWindow, popupParams.popupWindowParent);\r\n\r\n const serverParams = invoke(\r\n ResponseHandler.deserializeResponse,\r\n PerformanceEvents.DeserializeResponse,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(\r\n responseString,\r\n this.config.auth.OIDCOptions.serverResponseType,\r\n this.logger\r\n );\r\n\r\n return invokeAsync(\r\n Authorize.handleResponseCode,\r\n PerformanceEvents.HandleResponseCode,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n request,\r\n serverParams,\r\n pkceVerifier,\r\n ApiId.acquireTokenPopup,\r\n this.config,\r\n authClient,\r\n this.browserStorage,\r\n this.nativeStorage,\r\n this.eventHandler,\r\n this.logger,\r\n this.performanceClient,\r\n this.platformAuthProvider\r\n );\r\n }\r\n\r\n /**\r\n *\r\n * @param validRequest\r\n * @param popupName\r\n * @param requestAuthority\r\n * @param popup\r\n * @param mainWindowRedirectUri\r\n * @param popupWindowAttributes\r\n */\r\n protected async logoutPopupAsync(\r\n validRequest: CommonEndSessionRequest,\r\n popupParams: PopupParams,\r\n requestAuthority?: string,\r\n mainWindowRedirectUri?: string\r\n ): Promise {\r\n this.logger.verbose(\"logoutPopupAsync called\");\r\n this.eventHandler.emitEvent(\r\n EventType.LOGOUT_START,\r\n InteractionType.Popup,\r\n validRequest\r\n );\r\n\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(\r\n ApiId.logoutPopup\r\n );\r\n\r\n try {\r\n // Clear cache on logout\r\n await this.clearCacheOnLogout(\r\n this.correlationId,\r\n validRequest.account\r\n );\r\n\r\n // Initialize the client\r\n const authClient = await invokeAsync(\r\n this.createAuthCodeClient.bind(this),\r\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )({\r\n serverTelemetryManager,\r\n requestAuthority: requestAuthority,\r\n account: validRequest.account || undefined,\r\n });\r\n\r\n try {\r\n authClient.authority.endSessionEndpoint;\r\n } catch {\r\n if (\r\n validRequest.account?.homeAccountId &&\r\n validRequest.postLogoutRedirectUri &&\r\n authClient.authority.protocolMode === ProtocolMode.OIDC\r\n ) {\r\n this.eventHandler.emitEvent(\r\n EventType.LOGOUT_SUCCESS,\r\n InteractionType.Popup,\r\n validRequest\r\n );\r\n\r\n if (mainWindowRedirectUri) {\r\n const navigationOptions: NavigationOptions = {\r\n apiId: ApiId.logoutPopup,\r\n timeout:\r\n this.config.system.redirectNavigationTimeout,\r\n noHistory: false,\r\n };\r\n const absoluteUrl = UrlString.getAbsoluteUrl(\r\n mainWindowRedirectUri,\r\n BrowserUtils.getCurrentUri()\r\n );\r\n await this.navigationClient.navigateInternal(\r\n absoluteUrl,\r\n navigationOptions\r\n );\r\n }\r\n\r\n popupParams.popup?.close();\r\n\r\n return;\r\n }\r\n }\r\n\r\n // Create logout string and navigate user window to logout.\r\n const logoutUri: string = authClient.getLogoutUri(validRequest);\r\n\r\n this.eventHandler.emitEvent(\r\n EventType.LOGOUT_SUCCESS,\r\n InteractionType.Popup,\r\n validRequest\r\n );\r\n\r\n // Open the popup window to requestUrl.\r\n const popupWindow = this.openPopup(logoutUri, popupParams);\r\n this.eventHandler.emitEvent(\r\n EventType.POPUP_OPENED,\r\n InteractionType.Popup,\r\n { popupWindow },\r\n null\r\n );\r\n\r\n await this.monitorPopupForHash(\r\n popupWindow,\r\n popupParams.popupWindowParent\r\n ).catch(() => {\r\n // Swallow any errors related to monitoring the window. Server logout is best effort\r\n });\r\n\r\n if (mainWindowRedirectUri) {\r\n const navigationOptions: NavigationOptions = {\r\n apiId: ApiId.logoutPopup,\r\n timeout: this.config.system.redirectNavigationTimeout,\r\n noHistory: false,\r\n };\r\n const absoluteUrl = UrlString.getAbsoluteUrl(\r\n mainWindowRedirectUri,\r\n BrowserUtils.getCurrentUri()\r\n );\r\n\r\n this.logger.verbose(\r\n \"Redirecting main window to url specified in the request\"\r\n );\r\n this.logger.verbosePii(\r\n `Redirecting main window to: ${absoluteUrl}`\r\n );\r\n await this.navigationClient.navigateInternal(\r\n absoluteUrl,\r\n navigationOptions\r\n );\r\n } else {\r\n this.logger.verbose(\"No main window navigation requested\");\r\n }\r\n } catch (e) {\r\n // Close the synchronous popup if an error is thrown before the window unload event is registered\r\n popupParams.popup?.close();\r\n\r\n if (e instanceof AuthError) {\r\n (e as AuthError).setCorrelationId(this.correlationId);\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n }\r\n this.eventHandler.emitEvent(\r\n EventType.LOGOUT_FAILURE,\r\n InteractionType.Popup,\r\n null,\r\n e as EventError\r\n );\r\n this.eventHandler.emitEvent(\r\n EventType.LOGOUT_END,\r\n InteractionType.Popup\r\n );\r\n throw e;\r\n }\r\n\r\n this.eventHandler.emitEvent(\r\n EventType.LOGOUT_END,\r\n InteractionType.Popup\r\n );\r\n }\r\n\r\n /**\r\n * Opens a popup window with given request Url.\r\n * @param requestUrl\r\n */\r\n initiateAuthRequest(requestUrl: string, params: PopupParams): Window {\r\n // Check that request url is not empty.\r\n if (requestUrl) {\r\n this.logger.infoPii(`Navigate to: ${requestUrl}`);\r\n // Open the popup window to requestUrl.\r\n return this.openPopup(requestUrl, params);\r\n } else {\r\n // Throw error if request URL is empty.\r\n this.logger.error(\"Navigate url is empty\");\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.emptyNavigateUri\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Monitors a window until it loads a url with the same origin.\r\n * @param popupWindow - window that is being monitored\r\n * @param timeout - timeout for processing hash once popup is redirected back to application\r\n */\r\n monitorPopupForHash(\r\n popupWindow: Window,\r\n popupWindowParent: Window\r\n ): Promise {\r\n return new Promise((resolve, reject) => {\r\n this.logger.verbose(\r\n \"PopupHandler.monitorPopupForHash - polling started\"\r\n );\r\n\r\n const intervalId = setInterval(() => {\r\n // Window is closed\r\n if (popupWindow.closed) {\r\n this.logger.error(\r\n \"PopupHandler.monitorPopupForHash - window closed\"\r\n );\r\n clearInterval(intervalId);\r\n reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.userCancelled\r\n )\r\n );\r\n return;\r\n }\r\n\r\n let href = \"\";\r\n try {\r\n /*\r\n * Will throw if cross origin,\r\n * which should be caught and ignored\r\n * since we need the interval to keep running while on STS UI.\r\n */\r\n href = popupWindow.location.href;\r\n } catch (e) {}\r\n\r\n // Don't process blank pages or cross domain\r\n if (!href || href === \"about:blank\") {\r\n return;\r\n }\r\n clearInterval(intervalId);\r\n\r\n let responseString = \"\";\r\n const responseType =\r\n this.config.auth.OIDCOptions.serverResponseType;\r\n if (popupWindow) {\r\n if (responseType === ServerResponseType.QUERY) {\r\n responseString = popupWindow.location.search;\r\n } else {\r\n responseString = popupWindow.location.hash;\r\n }\r\n }\r\n\r\n this.logger.verbose(\r\n \"PopupHandler.monitorPopupForHash - popup window is on same origin as caller\"\r\n );\r\n\r\n resolve(responseString);\r\n }, this.config.system.pollIntervalMilliseconds);\r\n }).finally(() => {\r\n this.cleanPopup(popupWindow, popupWindowParent);\r\n });\r\n }\r\n\r\n /**\r\n * @hidden\r\n *\r\n * Configures popup window for login.\r\n *\r\n * @param urlNavigate\r\n * @param title\r\n * @param popUpWidth\r\n * @param popUpHeight\r\n * @param popupWindowAttributes\r\n * @ignore\r\n * @hidden\r\n */\r\n openPopup(urlNavigate: string, popupParams: PopupParams): Window {\r\n try {\r\n let popupWindow;\r\n // Popup window passed in, setting url to navigate to\r\n if (popupParams.popup) {\r\n popupWindow = popupParams.popup;\r\n this.logger.verbosePii(\r\n `Navigating popup window to: ${urlNavigate}`\r\n );\r\n popupWindow.location.assign(urlNavigate);\r\n } else if (typeof popupParams.popup === \"undefined\") {\r\n // Popup will be undefined if it was not passed in\r\n this.logger.verbosePii(\r\n `Opening popup window to: ${urlNavigate}`\r\n );\r\n popupWindow = this.openSizedPopup(urlNavigate, popupParams);\r\n }\r\n\r\n // Popup will be null if popups are blocked\r\n if (!popupWindow) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.emptyWindowError\r\n );\r\n }\r\n if (popupWindow.focus) {\r\n popupWindow.focus();\r\n }\r\n this.currentWindow = popupWindow;\r\n popupParams.popupWindowParent.addEventListener(\r\n \"beforeunload\",\r\n this.unloadWindow\r\n );\r\n\r\n return popupWindow;\r\n } catch (e) {\r\n this.logger.error(\r\n \"error opening popup \" + (e as AuthError).message\r\n );\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.popupWindowError\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Helper function to set popup window dimensions and position\r\n * @param urlNavigate\r\n * @param popupName\r\n * @param popupWindowAttributes\r\n * @returns\r\n */\r\n openSizedPopup(\r\n urlNavigate: string,\r\n { popupName, popupWindowAttributes, popupWindowParent }: PopupParams\r\n ): Window | null {\r\n /**\r\n * adding winLeft and winTop to account for dual monitor\r\n * using screenLeft and screenTop for IE8 and earlier\r\n */\r\n const winLeft = popupWindowParent.screenLeft\r\n ? popupWindowParent.screenLeft\r\n : popupWindowParent.screenX;\r\n const winTop = popupWindowParent.screenTop\r\n ? popupWindowParent.screenTop\r\n : popupWindowParent.screenY;\r\n /**\r\n * window.innerWidth displays browser window\"s height and width excluding toolbars\r\n * using document.documentElement.clientWidth for IE8 and earlier\r\n */\r\n const winWidth =\r\n popupWindowParent.innerWidth ||\r\n document.documentElement.clientWidth ||\r\n document.body.clientWidth;\r\n const winHeight =\r\n popupWindowParent.innerHeight ||\r\n document.documentElement.clientHeight ||\r\n document.body.clientHeight;\r\n\r\n let width = popupWindowAttributes.popupSize?.width;\r\n let height = popupWindowAttributes.popupSize?.height;\r\n let top = popupWindowAttributes.popupPosition?.top;\r\n let left = popupWindowAttributes.popupPosition?.left;\r\n\r\n if (!width || width < 0 || width > winWidth) {\r\n this.logger.verbose(\r\n \"Default popup window width used. Window width not configured or invalid.\"\r\n );\r\n width = BrowserConstants.POPUP_WIDTH;\r\n }\r\n\r\n if (!height || height < 0 || height > winHeight) {\r\n this.logger.verbose(\r\n \"Default popup window height used. Window height not configured or invalid.\"\r\n );\r\n height = BrowserConstants.POPUP_HEIGHT;\r\n }\r\n\r\n if (!top || top < 0 || top > winHeight) {\r\n this.logger.verbose(\r\n \"Default popup window top position used. Window top not configured or invalid.\"\r\n );\r\n top = Math.max(\r\n 0,\r\n winHeight / 2 - BrowserConstants.POPUP_HEIGHT / 2 + winTop\r\n );\r\n }\r\n\r\n if (!left || left < 0 || left > winWidth) {\r\n this.logger.verbose(\r\n \"Default popup window left position used. Window left not configured or invalid.\"\r\n );\r\n left = Math.max(\r\n 0,\r\n winWidth / 2 - BrowserConstants.POPUP_WIDTH / 2 + winLeft\r\n );\r\n }\r\n\r\n return popupWindowParent.open(\r\n urlNavigate,\r\n popupName,\r\n `width=${width}, height=${height}, top=${top}, left=${left}, scrollbars=yes`\r\n );\r\n }\r\n\r\n /**\r\n * Event callback to unload main window.\r\n */\r\n unloadWindow(e: Event): void {\r\n if (this.currentWindow) {\r\n this.currentWindow.close();\r\n }\r\n // Guarantees browser unload will happen, so no other errors will be thrown.\r\n e.preventDefault();\r\n }\r\n\r\n /**\r\n * Closes popup, removes any state vars created during popup calls.\r\n * @param popupWindow\r\n */\r\n cleanPopup(popupWindow: Window, popupWindowParent: Window): void {\r\n // Close window.\r\n popupWindow.close();\r\n\r\n // Remove window unload function\r\n popupWindowParent.removeEventListener(\r\n \"beforeunload\",\r\n this.unloadWindow\r\n );\r\n }\r\n\r\n /**\r\n * Generates the name for the popup based on the client id and request\r\n * @param clientId\r\n * @param request\r\n */\r\n generatePopupName(scopes: Array, authority: string): string {\r\n return `${BrowserConstants.POPUP_NAME_PREFIX}.${\r\n this.config.auth.clientId\r\n }.${scopes.join(\"-\")}.${authority}.${this.correlationId}`;\r\n }\r\n\r\n /**\r\n * Generates the name for the popup based on the client id and request for logouts\r\n * @param clientId\r\n * @param request\r\n */\r\n generateLogoutPopupName(request: CommonEndSessionRequest): string {\r\n const homeAccountId = request.account && request.account.homeAccountId;\r\n return `${BrowserConstants.POPUP_NAME_PREFIX}.${this.config.auth.clientId}.${homeAccountId}.${this.correlationId}`;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n AuthorizationCodeClient,\r\n UrlString,\r\n AuthError,\r\n ServerTelemetryManager,\r\n Constants,\r\n AuthorizeResponse,\r\n ICrypto,\r\n Logger,\r\n IPerformanceClient,\r\n PerformanceEvents,\r\n ProtocolMode,\r\n invokeAsync,\r\n ServerResponseType,\r\n UrlUtils,\r\n InProgressPerformanceEvent,\r\n CommonAuthorizationUrlRequest,\r\n HttpMethod,\r\n} from \"@azure/msal-common/browser\";\r\nimport { StandardInteractionClient } from \"./StandardInteractionClient.js\";\r\nimport {\r\n ApiId,\r\n INTERACTION_TYPE,\r\n InteractionType,\r\n TemporaryCacheKeys,\r\n} from \"../utils/BrowserConstants.js\";\r\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\r\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\r\nimport { EventType } from \"../event/EventType.js\";\r\nimport { NavigationOptions } from \"../navigation/NavigationOptions.js\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\r\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\r\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\r\nimport { EventHandler } from \"../event/EventHandler.js\";\r\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\r\nimport { EventError } from \"../event/EventMessage.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport * as ResponseHandler from \"../response/ResponseHandler.js\";\r\nimport * as Authorize from \"../protocol/Authorize.js\";\r\nimport { generatePkceCodes } from \"../crypto/PkceGenerator.js\";\r\nimport { isPlatformAuthAllowed } from \"../broker/nativeBroker/PlatformAuthProvider.js\";\r\nimport { generateEarKey } from \"../crypto/BrowserCrypto.js\";\r\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\r\n\r\nfunction getNavigationType(): NavigationTimingType | undefined {\r\n if (\r\n typeof window === \"undefined\" ||\r\n typeof window.performance === \"undefined\" ||\r\n typeof window.performance.getEntriesByType !== \"function\"\r\n ) {\r\n return undefined;\r\n }\r\n\r\n const navigationEntries = window.performance.getEntriesByType(\"navigation\");\r\n const navigation = navigationEntries.length\r\n ? (navigationEntries[0] as PerformanceNavigationTiming)\r\n : undefined;\r\n return navigation?.type;\r\n}\r\n\r\nexport class RedirectClient extends StandardInteractionClient {\r\n protected nativeStorage: BrowserCacheManager;\r\n\r\n constructor(\r\n config: BrowserConfiguration,\r\n storageImpl: BrowserCacheManager,\r\n browserCrypto: ICrypto,\r\n logger: Logger,\r\n eventHandler: EventHandler,\r\n navigationClient: INavigationClient,\r\n performanceClient: IPerformanceClient,\r\n nativeStorageImpl: BrowserCacheManager,\r\n platformAuthHandler?: IPlatformAuthHandler,\r\n correlationId?: string\r\n ) {\r\n super(\r\n config,\r\n storageImpl,\r\n browserCrypto,\r\n logger,\r\n eventHandler,\r\n navigationClient,\r\n performanceClient,\r\n platformAuthHandler,\r\n correlationId\r\n );\r\n this.nativeStorage = nativeStorageImpl;\r\n }\r\n\r\n /**\r\n * Redirects the page to the /authorize endpoint of the IDP\r\n * @param request\r\n */\r\n async acquireToken(request: RedirectRequest): Promise {\r\n const validRequest = await invokeAsync(\r\n this.initializeAuthorizationRequest.bind(this),\r\n PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(request, InteractionType.Redirect);\r\n\r\n validRequest.platformBroker = isPlatformAuthAllowed(\r\n this.config,\r\n this.logger,\r\n this.platformAuthProvider,\r\n request.authenticationScheme\r\n );\r\n\r\n const handleBackButton = (event: PageTransitionEvent) => {\r\n // Clear temporary cache if the back button is clicked during the redirect flow.\r\n if (event.persisted) {\r\n this.logger.verbose(\r\n \"Page was restored from back/forward cache. Clearing temporary cache.\"\r\n );\r\n this.browserStorage.resetRequestCache();\r\n this.eventHandler.emitEvent(\r\n EventType.RESTORE_FROM_BFCACHE,\r\n InteractionType.Redirect\r\n );\r\n }\r\n };\r\n\r\n const redirectStartPage = this.getRedirectStartPage(\r\n request.redirectStartPage\r\n );\r\n this.logger.verbosePii(`Redirect start page: ${redirectStartPage}`);\r\n // Cache start page, returns to this page after redirectUri if navigateToLoginRequestUrl is true\r\n this.browserStorage.setTemporaryCache(\r\n TemporaryCacheKeys.ORIGIN_URI,\r\n redirectStartPage,\r\n true\r\n );\r\n\r\n // Clear temporary cache if the back button is clicked during the redirect flow.\r\n window.addEventListener(\"pageshow\", handleBackButton);\r\n\r\n try {\r\n if (this.config.auth.protocolMode === ProtocolMode.EAR) {\r\n await this.executeEarFlow(validRequest);\r\n } else {\r\n await this.executeCodeFlow(\r\n validRequest,\r\n request.onRedirectNavigate\r\n );\r\n }\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n e.setCorrelationId(this.correlationId);\r\n }\r\n window.removeEventListener(\"pageshow\", handleBackButton);\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Executes auth code + PKCE flow\r\n * @param request\r\n * @returns\r\n */\r\n async executeCodeFlow(\r\n request: CommonAuthorizationUrlRequest,\r\n onRedirectNavigate?: (url: string) => boolean | void\r\n ): Promise {\r\n const correlationId = request.correlationId;\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(\r\n ApiId.acquireTokenRedirect\r\n );\r\n\r\n const pkceCodes = await invokeAsync(\r\n generatePkceCodes,\r\n PerformanceEvents.GeneratePkceCodes,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(this.performanceClient, this.logger, correlationId);\r\n\r\n const redirectRequest = {\r\n ...request,\r\n codeChallenge: pkceCodes.challenge,\r\n };\r\n\r\n this.browserStorage.cacheAuthorizeRequest(\r\n redirectRequest,\r\n pkceCodes.verifier\r\n );\r\n\r\n try {\r\n if (redirectRequest.httpMethod === HttpMethod.POST) {\r\n return await this.executeCodeFlowWithPost(redirectRequest);\r\n } else {\r\n // Initialize the client\r\n const authClient: AuthorizationCodeClient = await invokeAsync(\r\n this.createAuthCodeClient.bind(this),\r\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )({\r\n serverTelemetryManager,\r\n requestAuthority: redirectRequest.authority,\r\n requestAzureCloudOptions: redirectRequest.azureCloudOptions,\r\n requestExtraQueryParameters:\r\n redirectRequest.extraQueryParameters,\r\n account: redirectRequest.account,\r\n });\r\n\r\n // Create acquire token url.\r\n const navigateUrl = await invokeAsync(\r\n Authorize.getAuthCodeRequestUrl,\r\n PerformanceEvents.GetAuthCodeUrl,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(\r\n this.config,\r\n authClient.authority,\r\n redirectRequest,\r\n this.logger,\r\n this.performanceClient\r\n );\r\n // Show the UI once the url has been created. Response will come back in the hash, which will be handled in the handleRedirectCallback function.\r\n return await this.initiateAuthRequest(\r\n navigateUrl,\r\n onRedirectNavigate\r\n );\r\n }\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n e.setCorrelationId(this.correlationId);\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n }\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Executes EAR flow\r\n * @param request\r\n */\r\n async executeEarFlow(\r\n request: CommonAuthorizationUrlRequest\r\n ): Promise {\r\n const correlationId = request.correlationId;\r\n // Get the frame handle for the silent request\r\n const discoveredAuthority = await invokeAsync(\r\n this.getDiscoveredAuthority.bind(this),\r\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )({\r\n requestAuthority: request.authority,\r\n requestAzureCloudOptions: request.azureCloudOptions,\r\n requestExtraQueryParameters: request.extraQueryParameters,\r\n account: request.account,\r\n });\r\n\r\n const earJwk = await invokeAsync(\r\n generateEarKey,\r\n PerformanceEvents.GenerateEarKey,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )();\r\n const redirectRequest = {\r\n ...request,\r\n earJwk: earJwk,\r\n };\r\n this.browserStorage.cacheAuthorizeRequest(redirectRequest);\r\n\r\n const form = await Authorize.getEARForm(\r\n document,\r\n this.config,\r\n discoveredAuthority,\r\n redirectRequest,\r\n this.logger,\r\n this.performanceClient\r\n );\r\n form.submit();\r\n return new Promise((resolve, reject) => {\r\n setTimeout(() => {\r\n reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.timedOut,\r\n \"failed_to_redirect\"\r\n )\r\n );\r\n }, this.config.system.redirectNavigationTimeout);\r\n });\r\n }\r\n\r\n /**\r\n * Executes classic Authorization Code flow with a POST request.\r\n * @param request\r\n */\r\n async executeCodeFlowWithPost(\r\n request: CommonAuthorizationUrlRequest\r\n ): Promise {\r\n const correlationId = request.correlationId;\r\n // Get the frame handle for the silent request\r\n const discoveredAuthority = await invokeAsync(\r\n this.getDiscoveredAuthority.bind(this),\r\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )({\r\n requestAuthority: request.authority,\r\n requestAzureCloudOptions: request.azureCloudOptions,\r\n requestExtraQueryParameters: request.extraQueryParameters,\r\n account: request.account,\r\n });\r\n\r\n this.browserStorage.cacheAuthorizeRequest(request);\r\n\r\n const form = await Authorize.getCodeForm(\r\n document,\r\n this.config,\r\n discoveredAuthority,\r\n request,\r\n this.logger,\r\n this.performanceClient\r\n );\r\n\r\n form.submit();\r\n return new Promise((resolve, reject) => {\r\n setTimeout(() => {\r\n reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.timedOut,\r\n \"failed_to_redirect\"\r\n )\r\n );\r\n }, this.config.system.redirectNavigationTimeout);\r\n });\r\n }\r\n\r\n /**\r\n * Checks if navigateToLoginRequestUrl is set, and:\r\n * - if true, performs logic to cache and navigate\r\n * - if false, handles hash string and parses response\r\n * @param hash {string} url hash\r\n * @param parentMeasurement {InProgressPerformanceEvent} parent measurement\r\n */\r\n async handleRedirectPromise(\r\n hash: string = \"\",\r\n request: CommonAuthorizationUrlRequest,\r\n pkceVerifier: string,\r\n parentMeasurement: InProgressPerformanceEvent\r\n ): Promise {\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(\r\n ApiId.handleRedirectPromise\r\n );\r\n\r\n try {\r\n const [serverParams, responseString] = this.getRedirectResponse(\r\n hash || \"\"\r\n );\r\n if (!serverParams) {\r\n // Not a recognized server response hash or hash not associated with a redirect request\r\n this.logger.info(\r\n \"handleRedirectPromise did not detect a response as a result of a redirect. Cleaning temporary cache.\"\r\n );\r\n this.browserStorage.resetRequestCache();\r\n\r\n // Do not instrument \"no_server_response\" if user clicked back button\r\n if (getNavigationType() !== \"back_forward\") {\r\n parentMeasurement.event.errorCode = \"no_server_response\";\r\n } else {\r\n this.logger.verbose(\r\n \"Back navigation event detected. Muting no_server_response error\"\r\n );\r\n }\r\n return null;\r\n }\r\n\r\n // If navigateToLoginRequestUrl is true, get the url where the redirect request was initiated\r\n const loginRequestUrl =\r\n this.browserStorage.getTemporaryCache(\r\n TemporaryCacheKeys.ORIGIN_URI,\r\n true\r\n ) || Constants.EMPTY_STRING;\r\n const loginRequestUrlNormalized =\r\n UrlUtils.normalizeUrlForComparison(loginRequestUrl);\r\n const currentUrlNormalized = UrlUtils.normalizeUrlForComparison(\r\n window.location.href\r\n );\r\n\r\n if (\r\n loginRequestUrlNormalized === currentUrlNormalized &&\r\n this.config.auth.navigateToLoginRequestUrl\r\n ) {\r\n // We are on the page we need to navigate to - handle hash\r\n this.logger.verbose(\r\n \"Current page is loginRequestUrl, handling response\"\r\n );\r\n\r\n if (loginRequestUrl.indexOf(\"#\") > -1) {\r\n // Replace current hash with non-msal hash, if present\r\n BrowserUtils.replaceHash(loginRequestUrl);\r\n }\r\n\r\n const handleHashResult = await this.handleResponse(\r\n serverParams,\r\n request,\r\n pkceVerifier,\r\n serverTelemetryManager\r\n );\r\n\r\n return handleHashResult;\r\n } else if (!this.config.auth.navigateToLoginRequestUrl) {\r\n this.logger.verbose(\r\n \"NavigateToLoginRequestUrl set to false, handling response\"\r\n );\r\n return await this.handleResponse(\r\n serverParams,\r\n request,\r\n pkceVerifier,\r\n serverTelemetryManager\r\n );\r\n } else if (\r\n !BrowserUtils.isInIframe() ||\r\n this.config.system.allowRedirectInIframe\r\n ) {\r\n /*\r\n * Returned from authority using redirect - need to perform navigation before processing response\r\n * Cache the hash to be retrieved after the next redirect\r\n */\r\n this.browserStorage.setTemporaryCache(\r\n TemporaryCacheKeys.URL_HASH,\r\n responseString,\r\n true\r\n );\r\n const navigationOptions: NavigationOptions = {\r\n apiId: ApiId.handleRedirectPromise,\r\n timeout: this.config.system.redirectNavigationTimeout,\r\n noHistory: true,\r\n };\r\n\r\n /**\r\n * Default behavior is to redirect to the start page and not process the hash now.\r\n * The start page is expected to also call handleRedirectPromise which will process the hash in one of the checks above.\r\n */\r\n let processHashOnRedirect: boolean = true;\r\n if (!loginRequestUrl || loginRequestUrl === \"null\") {\r\n // Redirect to home page if login request url is null (real null or the string null)\r\n const homepage = BrowserUtils.getHomepage();\r\n // Cache the homepage under ORIGIN_URI to ensure cached hash is processed on homepage\r\n this.browserStorage.setTemporaryCache(\r\n TemporaryCacheKeys.ORIGIN_URI,\r\n homepage,\r\n true\r\n );\r\n this.logger.warning(\r\n \"Unable to get valid login request url from cache, redirecting to home page\"\r\n );\r\n processHashOnRedirect =\r\n await this.navigationClient.navigateInternal(\r\n homepage,\r\n navigationOptions\r\n );\r\n } else {\r\n // Navigate to page that initiated the redirect request\r\n this.logger.verbose(\r\n `Navigating to loginRequestUrl: ${loginRequestUrl}`\r\n );\r\n processHashOnRedirect =\r\n await this.navigationClient.navigateInternal(\r\n loginRequestUrl,\r\n navigationOptions\r\n );\r\n }\r\n\r\n // If navigateInternal implementation returns false, handle the hash now\r\n if (!processHashOnRedirect) {\r\n return await this.handleResponse(\r\n serverParams,\r\n request,\r\n pkceVerifier,\r\n serverTelemetryManager\r\n );\r\n }\r\n }\r\n\r\n return null;\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n (e as AuthError).setCorrelationId(this.correlationId);\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n }\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the response hash for a redirect request\r\n * Returns null if interactionType in the state value is not \"redirect\" or the hash does not contain known properties\r\n * @param hash\r\n */\r\n protected getRedirectResponse(\r\n userProvidedResponse: string\r\n ): [AuthorizeResponse | null, string] {\r\n this.logger.verbose(\"getRedirectResponseHash called\");\r\n // Get current location hash from window or cache.\r\n let responseString = userProvidedResponse;\r\n if (!responseString) {\r\n if (\r\n this.config.auth.OIDCOptions.serverResponseType ===\r\n ServerResponseType.QUERY\r\n ) {\r\n responseString = window.location.search;\r\n } else {\r\n responseString = window.location.hash;\r\n }\r\n }\r\n let response = UrlUtils.getDeserializedResponse(responseString);\r\n\r\n if (response) {\r\n try {\r\n ResponseHandler.validateInteractionType(\r\n response,\r\n this.browserCrypto,\r\n InteractionType.Redirect\r\n );\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n this.logger.error(\r\n `Interaction type validation failed due to ${e.errorCode}: ${e.errorMessage}`\r\n );\r\n }\r\n return [null, \"\"];\r\n }\r\n\r\n BrowserUtils.clearHash(window);\r\n this.logger.verbose(\r\n \"Hash contains known properties, returning response hash\"\r\n );\r\n return [response, responseString];\r\n }\r\n\r\n const cachedHash = this.browserStorage.getTemporaryCache(\r\n TemporaryCacheKeys.URL_HASH,\r\n true\r\n );\r\n this.browserStorage.removeItem(\r\n this.browserStorage.generateCacheKey(TemporaryCacheKeys.URL_HASH)\r\n );\r\n\r\n if (cachedHash) {\r\n response = UrlUtils.getDeserializedResponse(cachedHash);\r\n if (response) {\r\n this.logger.verbose(\r\n \"Hash does not contain known properties, returning cached hash\"\r\n );\r\n return [response, cachedHash];\r\n }\r\n }\r\n\r\n return [null, \"\"];\r\n }\r\n\r\n /**\r\n * Checks if hash exists and handles in window.\r\n * @param hash\r\n * @param state\r\n */\r\n protected async handleResponse(\r\n serverParams: AuthorizeResponse,\r\n request: CommonAuthorizationUrlRequest,\r\n codeVerifier: string,\r\n serverTelemetryManager: ServerTelemetryManager\r\n ): Promise {\r\n const state = serverParams.state;\r\n if (!state) {\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.noStateInHash);\r\n }\r\n\r\n if (serverParams.ear_jwe) {\r\n const discoveredAuthority = await invokeAsync(\r\n this.getDiscoveredAuthority.bind(this),\r\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )({\r\n requestAuthority: request.authority,\r\n requestAzureCloudOptions: request.azureCloudOptions,\r\n requestExtraQueryParameters: request.extraQueryParameters,\r\n account: request.account,\r\n });\r\n return invokeAsync(\r\n Authorize.handleResponseEAR,\r\n PerformanceEvents.HandleResponseEar,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(\r\n request,\r\n serverParams,\r\n ApiId.acquireTokenRedirect,\r\n this.config,\r\n discoveredAuthority,\r\n this.browserStorage,\r\n this.nativeStorage,\r\n this.eventHandler,\r\n this.logger,\r\n this.performanceClient,\r\n this.platformAuthProvider\r\n );\r\n }\r\n\r\n const authClient = await invokeAsync(\r\n this.createAuthCodeClient.bind(this),\r\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )({ serverTelemetryManager, requestAuthority: request.authority });\r\n return invokeAsync(\r\n Authorize.handleResponseCode,\r\n PerformanceEvents.HandleResponseCode,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(\r\n request,\r\n serverParams,\r\n codeVerifier,\r\n ApiId.acquireTokenRedirect,\r\n this.config,\r\n authClient,\r\n this.browserStorage,\r\n this.nativeStorage,\r\n this.eventHandler,\r\n this.logger,\r\n this.performanceClient,\r\n this.platformAuthProvider\r\n );\r\n }\r\n\r\n /**\r\n * Redirects window to given URL.\r\n * @param urlNavigate\r\n * @param onRedirectNavigateRequest - onRedirectNavigate callback provided on the request\r\n */\r\n async initiateAuthRequest(\r\n requestUrl: string,\r\n onRedirectNavigateRequest?: (url: string) => boolean | void\r\n ): Promise {\r\n this.logger.verbose(\"RedirectHandler.initiateAuthRequest called\");\r\n // Navigate if valid URL\r\n if (requestUrl) {\r\n this.logger.infoPii(\r\n `RedirectHandler.initiateAuthRequest: Navigate to: ${requestUrl}`\r\n );\r\n const navigationOptions: NavigationOptions = {\r\n apiId: ApiId.acquireTokenRedirect,\r\n timeout: this.config.system.redirectNavigationTimeout,\r\n noHistory: false,\r\n };\r\n\r\n const onRedirectNavigate =\r\n onRedirectNavigateRequest ||\r\n this.config.auth.onRedirectNavigate;\r\n\r\n // If onRedirectNavigate is implemented, invoke it and provide requestUrl\r\n if (typeof onRedirectNavigate === \"function\") {\r\n this.logger.verbose(\r\n \"RedirectHandler.initiateAuthRequest: Invoking onRedirectNavigate callback\"\r\n );\r\n const navigate = onRedirectNavigate(requestUrl);\r\n\r\n // Returning false from onRedirectNavigate will stop navigation\r\n if (navigate !== false) {\r\n this.logger.verbose(\r\n \"RedirectHandler.initiateAuthRequest: onRedirectNavigate did not return false, navigating\"\r\n );\r\n await this.navigationClient.navigateExternal(\r\n requestUrl,\r\n navigationOptions\r\n );\r\n return;\r\n } else {\r\n this.logger.verbose(\r\n \"RedirectHandler.initiateAuthRequest: onRedirectNavigate returned false, stopping navigation\"\r\n );\r\n return;\r\n }\r\n } else {\r\n // Navigate window to request URL\r\n this.logger.verbose(\r\n \"RedirectHandler.initiateAuthRequest: Navigating window to navigate url\"\r\n );\r\n await this.navigationClient.navigateExternal(\r\n requestUrl,\r\n navigationOptions\r\n );\r\n return;\r\n }\r\n } else {\r\n // Throw error if request URL is empty.\r\n this.logger.info(\r\n \"RedirectHandler.initiateAuthRequest: Navigate url is empty\"\r\n );\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.emptyNavigateUri\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Use to log out the current user, and redirect the user to the postLogoutRedirectUri.\r\n * Default behaviour is to redirect the user to `window.location.href`.\r\n * @param logoutRequest\r\n */\r\n async logout(logoutRequest?: EndSessionRequest): Promise {\r\n this.logger.verbose(\"logoutRedirect called\");\r\n const validLogoutRequest = this.initializeLogoutRequest(logoutRequest);\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(\r\n ApiId.logout\r\n );\r\n\r\n try {\r\n this.eventHandler.emitEvent(\r\n EventType.LOGOUT_START,\r\n InteractionType.Redirect,\r\n logoutRequest\r\n );\r\n\r\n // Clear cache on logout\r\n await this.clearCacheOnLogout(\r\n this.correlationId,\r\n validLogoutRequest.account\r\n );\r\n\r\n const navigationOptions: NavigationOptions = {\r\n apiId: ApiId.logout,\r\n timeout: this.config.system.redirectNavigationTimeout,\r\n noHistory: false,\r\n };\r\n\r\n const authClient = await invokeAsync(\r\n this.createAuthCodeClient.bind(this),\r\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )({\r\n serverTelemetryManager,\r\n requestAuthority: logoutRequest && logoutRequest.authority,\r\n requestExtraQueryParameters:\r\n logoutRequest?.extraQueryParameters,\r\n account: (logoutRequest && logoutRequest.account) || undefined,\r\n });\r\n\r\n if (authClient.authority.protocolMode === ProtocolMode.OIDC) {\r\n try {\r\n authClient.authority.endSessionEndpoint;\r\n } catch {\r\n if (validLogoutRequest.account?.homeAccountId) {\r\n this.eventHandler.emitEvent(\r\n EventType.LOGOUT_SUCCESS,\r\n InteractionType.Redirect,\r\n validLogoutRequest\r\n );\r\n\r\n return;\r\n }\r\n }\r\n }\r\n\r\n // Create logout string and navigate user window to logout.\r\n const logoutUri: string =\r\n authClient.getLogoutUri(validLogoutRequest);\r\n\r\n this.eventHandler.emitEvent(\r\n EventType.LOGOUT_SUCCESS,\r\n InteractionType.Redirect,\r\n validLogoutRequest\r\n );\r\n // Check if onRedirectNavigate is implemented, and invoke it if so\r\n if (\r\n logoutRequest &&\r\n typeof logoutRequest.onRedirectNavigate === \"function\"\r\n ) {\r\n const navigate = logoutRequest.onRedirectNavigate(logoutUri);\r\n\r\n if (navigate !== false) {\r\n this.logger.verbose(\r\n \"Logout onRedirectNavigate did not return false, navigating\"\r\n );\r\n // Ensure interaction is in progress\r\n if (!this.browserStorage.getInteractionInProgress()) {\r\n this.browserStorage.setInteractionInProgress(\r\n true,\r\n INTERACTION_TYPE.SIGNOUT\r\n );\r\n }\r\n await this.navigationClient.navigateExternal(\r\n logoutUri,\r\n navigationOptions\r\n );\r\n return;\r\n } else {\r\n // Ensure interaction is not in progress\r\n this.browserStorage.setInteractionInProgress(false);\r\n this.logger.verbose(\r\n \"Logout onRedirectNavigate returned false, stopping navigation\"\r\n );\r\n }\r\n } else {\r\n // Ensure interaction is in progress\r\n if (!this.browserStorage.getInteractionInProgress()) {\r\n this.browserStorage.setInteractionInProgress(\r\n true,\r\n INTERACTION_TYPE.SIGNOUT\r\n );\r\n }\r\n await this.navigationClient.navigateExternal(\r\n logoutUri,\r\n navigationOptions\r\n );\r\n return;\r\n }\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n (e as AuthError).setCorrelationId(this.correlationId);\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n }\r\n this.eventHandler.emitEvent(\r\n EventType.LOGOUT_FAILURE,\r\n InteractionType.Redirect,\r\n null,\r\n e as EventError\r\n );\r\n this.eventHandler.emitEvent(\r\n EventType.LOGOUT_END,\r\n InteractionType.Redirect\r\n );\r\n throw e;\r\n }\r\n\r\n this.eventHandler.emitEvent(\r\n EventType.LOGOUT_END,\r\n InteractionType.Redirect\r\n );\r\n }\r\n\r\n /**\r\n * Use to get the redirectStartPage either from request or use current window\r\n * @param requestStartPage\r\n */\r\n protected getRedirectStartPage(requestStartPage?: string): string {\r\n const redirectStartPage = requestStartPage || window.location.href;\r\n return UrlString.getAbsoluteUrl(\r\n redirectStartPage,\r\n BrowserUtils.getCurrentUri()\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n Logger,\r\n IPerformanceClient,\r\n PerformanceEvents,\r\n invokeAsync,\r\n invoke,\r\n ServerResponseType,\r\n Authority,\r\n CommonAuthorizationUrlRequest,\r\n} from \"@azure/msal-common/browser\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport {\r\n BrowserConfiguration,\r\n DEFAULT_IFRAME_TIMEOUT_MS,\r\n} from \"../config/Configuration.js\";\r\nimport { getCodeForm, getEARForm } from \"../protocol/Authorize.js\";\r\n\r\n/**\r\n * Creates a hidden iframe to given URL using user-requested scopes as an id.\r\n * @param urlNavigate\r\n * @param userRequestScopes\r\n */\r\nexport async function initiateCodeRequest(\r\n requestUrl: string,\r\n performanceClient: IPerformanceClient,\r\n logger: Logger,\r\n correlationId: string,\r\n navigateFrameWait?: number\r\n): Promise {\r\n performanceClient.addQueueMeasurement(\r\n PerformanceEvents.SilentHandlerInitiateAuthRequest,\r\n correlationId\r\n );\r\n\r\n if (!requestUrl) {\r\n // Throw error if request URL is empty.\r\n logger.info(\"Navigate url is empty\");\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.emptyNavigateUri);\r\n }\r\n if (navigateFrameWait) {\r\n return invokeAsync(\r\n loadFrame,\r\n PerformanceEvents.SilentHandlerLoadFrame,\r\n logger,\r\n performanceClient,\r\n correlationId\r\n )(requestUrl, navigateFrameWait, performanceClient, correlationId);\r\n }\r\n return invoke(\r\n loadFrameSync,\r\n PerformanceEvents.SilentHandlerLoadFrameSync,\r\n logger,\r\n performanceClient,\r\n correlationId\r\n )(requestUrl);\r\n}\r\n\r\nexport async function initiateCodeFlowWithPost(\r\n config: BrowserConfiguration,\r\n authority: Authority,\r\n request: CommonAuthorizationUrlRequest,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient\r\n): Promise {\r\n const frame = createHiddenIframe();\r\n if (!frame.contentDocument) {\r\n throw \"No document associated with iframe!\";\r\n }\r\n const form = await getCodeForm(\r\n frame.contentDocument,\r\n config,\r\n authority,\r\n request,\r\n logger,\r\n performanceClient\r\n );\r\n form.submit();\r\n return frame;\r\n}\r\n\r\nexport async function initiateEarRequest(\r\n config: BrowserConfiguration,\r\n authority: Authority,\r\n request: CommonAuthorizationUrlRequest,\r\n logger: Logger,\r\n performanceClient: IPerformanceClient\r\n): Promise {\r\n const frame = createHiddenIframe();\r\n if (!frame.contentDocument) {\r\n throw \"No document associated with iframe!\";\r\n }\r\n const form = await getEARForm(\r\n frame.contentDocument,\r\n config,\r\n authority,\r\n request,\r\n logger,\r\n performanceClient\r\n );\r\n form.submit();\r\n return frame;\r\n}\r\n\r\n/**\r\n * Monitors an iframe content window until it loads a url with a known hash, or hits a specified timeout.\r\n * @param iframe\r\n * @param timeout\r\n */\r\nexport async function monitorIframeForHash(\r\n iframe: HTMLIFrameElement,\r\n timeout: number,\r\n pollIntervalMilliseconds: number,\r\n performanceClient: IPerformanceClient,\r\n logger: Logger,\r\n correlationId: string,\r\n responseType: ServerResponseType\r\n): Promise {\r\n performanceClient.addQueueMeasurement(\r\n PerformanceEvents.SilentHandlerMonitorIframeForHash,\r\n correlationId\r\n );\r\n\r\n return new Promise((resolve, reject) => {\r\n if (timeout < DEFAULT_IFRAME_TIMEOUT_MS) {\r\n logger.warning(\r\n `system.loadFrameTimeout or system.iframeHashTimeout set to lower (${timeout}ms) than the default (${DEFAULT_IFRAME_TIMEOUT_MS}ms). This may result in timeouts.`\r\n );\r\n }\r\n\r\n /*\r\n * Polling for iframes can be purely timing based,\r\n * since we don't need to account for interaction.\r\n */\r\n const timeoutId = window.setTimeout(() => {\r\n window.clearInterval(intervalId);\r\n reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.monitorWindowTimeout\r\n )\r\n );\r\n }, timeout);\r\n\r\n const intervalId = window.setInterval(() => {\r\n let href: string = \"\";\r\n const contentWindow = iframe.contentWindow;\r\n try {\r\n /*\r\n * Will throw if cross origin,\r\n * which should be caught and ignored\r\n * since we need the interval to keep running while on STS UI.\r\n */\r\n href = contentWindow ? contentWindow.location.href : \"\";\r\n } catch (e) {}\r\n\r\n if (!href || href === \"about:blank\") {\r\n return;\r\n }\r\n\r\n let responseString = \"\";\r\n if (contentWindow) {\r\n if (responseType === ServerResponseType.QUERY) {\r\n responseString = contentWindow.location.search;\r\n } else {\r\n responseString = contentWindow.location.hash;\r\n }\r\n }\r\n window.clearTimeout(timeoutId);\r\n window.clearInterval(intervalId);\r\n resolve(responseString);\r\n }, pollIntervalMilliseconds);\r\n }).finally(() => {\r\n invoke(\r\n removeHiddenIframe,\r\n PerformanceEvents.RemoveHiddenIframe,\r\n logger,\r\n performanceClient,\r\n correlationId\r\n )(iframe);\r\n });\r\n}\r\n\r\n/**\r\n * @hidden\r\n * Loads iframe with authorization endpoint URL\r\n * @ignore\r\n * @deprecated\r\n */\r\nfunction loadFrame(\r\n urlNavigate: string,\r\n navigateFrameWait: number,\r\n performanceClient: IPerformanceClient,\r\n correlationId: string\r\n): Promise {\r\n performanceClient.addQueueMeasurement(\r\n PerformanceEvents.SilentHandlerLoadFrame,\r\n correlationId\r\n );\r\n\r\n /*\r\n * This trick overcomes iframe navigation in IE\r\n * IE does not load the page consistently in iframe\r\n */\r\n\r\n return new Promise((resolve, reject) => {\r\n const frameHandle = createHiddenIframe();\r\n\r\n window.setTimeout(() => {\r\n if (!frameHandle) {\r\n reject(\"Unable to load iframe\");\r\n return;\r\n }\r\n\r\n frameHandle.src = urlNavigate;\r\n\r\n resolve(frameHandle);\r\n }, navigateFrameWait);\r\n });\r\n}\r\n/**\r\n * @hidden\r\n * Loads the iframe synchronously when the navigateTimeFrame is set to `0`\r\n * @param urlNavigate\r\n * @param frameName\r\n * @param logger\r\n */\r\nfunction loadFrameSync(urlNavigate: string): HTMLIFrameElement {\r\n const frameHandle = createHiddenIframe();\r\n\r\n frameHandle.src = urlNavigate;\r\n\r\n return frameHandle;\r\n}\r\n\r\n/**\r\n * @hidden\r\n * Creates a new hidden iframe or gets an existing one for silent token renewal.\r\n * @ignore\r\n */\r\nfunction createHiddenIframe(): HTMLIFrameElement {\r\n const authFrame = document.createElement(\"iframe\");\r\n\r\n authFrame.className = \"msalSilentIframe\";\r\n authFrame.style.visibility = \"hidden\";\r\n authFrame.style.position = \"absolute\";\r\n authFrame.style.width = authFrame.style.height = \"0\";\r\n authFrame.style.border = \"0\";\r\n authFrame.setAttribute(\r\n \"sandbox\",\r\n \"allow-scripts allow-same-origin allow-forms\"\r\n );\r\n document.body.appendChild(authFrame);\r\n\r\n return authFrame;\r\n}\r\n\r\n/**\r\n * @hidden\r\n * Removes a hidden iframe from the page.\r\n * @ignore\r\n */\r\nfunction removeHiddenIframe(iframe: HTMLIFrameElement): void {\r\n if (document.body === iframe.parentNode) {\r\n document.body.removeChild(iframe);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n ICrypto,\r\n Logger,\r\n PromptValue,\r\n AuthorizationCodeClient,\r\n AuthError,\r\n IPerformanceClient,\r\n PerformanceEvents,\r\n invokeAsync,\r\n invoke,\r\n ProtocolMode,\r\n CommonAuthorizationUrlRequest,\r\n HttpMethod,\r\n} from \"@azure/msal-common/browser\";\r\nimport { StandardInteractionClient } from \"./StandardInteractionClient.js\";\r\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\r\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\r\nimport { EventHandler } from \"../event/EventHandler.js\";\r\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport {\r\n InteractionType,\r\n ApiId,\r\n BrowserConstants,\r\n} from \"../utils/BrowserConstants.js\";\r\nimport {\r\n initiateCodeRequest,\r\n initiateCodeFlowWithPost,\r\n initiateEarRequest,\r\n monitorIframeForHash,\r\n} from \"../interaction_handler/SilentHandler.js\";\r\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\r\nimport * as ResponseHandler from \"../response/ResponseHandler.js\";\r\nimport * as Authorize from \"../protocol/Authorize.js\";\r\nimport { generatePkceCodes } from \"../crypto/PkceGenerator.js\";\r\nimport { isPlatformAuthAllowed } from \"../broker/nativeBroker/PlatformAuthProvider.js\";\r\nimport { generateEarKey } from \"../crypto/BrowserCrypto.js\";\r\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\r\n\r\nexport class SilentIframeClient extends StandardInteractionClient {\r\n protected apiId: ApiId;\r\n protected nativeStorage: BrowserCacheManager;\r\n\r\n constructor(\r\n config: BrowserConfiguration,\r\n storageImpl: BrowserCacheManager,\r\n browserCrypto: ICrypto,\r\n logger: Logger,\r\n eventHandler: EventHandler,\r\n navigationClient: INavigationClient,\r\n apiId: ApiId,\r\n performanceClient: IPerformanceClient,\r\n nativeStorageImpl: BrowserCacheManager,\r\n platformAuthProvider?: IPlatformAuthHandler,\r\n correlationId?: string\r\n ) {\r\n super(\r\n config,\r\n storageImpl,\r\n browserCrypto,\r\n logger,\r\n eventHandler,\r\n navigationClient,\r\n performanceClient,\r\n platformAuthProvider,\r\n correlationId\r\n );\r\n this.apiId = apiId;\r\n this.nativeStorage = nativeStorageImpl;\r\n }\r\n\r\n /**\r\n * Acquires a token silently by opening a hidden iframe to the /authorize endpoint with prompt=none or prompt=no_session\r\n * @param request\r\n */\r\n async acquireToken(\r\n request: SsoSilentRequest\r\n ): Promise {\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.SilentIframeClientAcquireToken,\r\n request.correlationId\r\n );\r\n // Check that we have some SSO data\r\n if (\r\n !request.loginHint &&\r\n !request.sid &&\r\n (!request.account || !request.account.username)\r\n ) {\r\n this.logger.warning(\r\n \"No user hint provided. The authorization server may need more information to complete this request.\"\r\n );\r\n }\r\n\r\n // Check the prompt value\r\n const inputRequest = { ...request };\r\n if (inputRequest.prompt) {\r\n if (\r\n inputRequest.prompt !== PromptValue.NONE &&\r\n inputRequest.prompt !== PromptValue.NO_SESSION\r\n ) {\r\n this.logger.warning(\r\n `SilentIframeClient. Replacing invalid prompt ${inputRequest.prompt} with ${PromptValue.NONE}`\r\n );\r\n inputRequest.prompt = PromptValue.NONE;\r\n }\r\n } else {\r\n inputRequest.prompt = PromptValue.NONE;\r\n }\r\n\r\n // Create silent request\r\n const silentRequest: CommonAuthorizationUrlRequest = await invokeAsync(\r\n this.initializeAuthorizationRequest.bind(this),\r\n PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(inputRequest, InteractionType.Silent);\r\n silentRequest.platformBroker = isPlatformAuthAllowed(\r\n this.config,\r\n this.logger,\r\n this.platformAuthProvider,\r\n silentRequest.authenticationScheme\r\n );\r\n BrowserUtils.preconnect(silentRequest.authority);\r\n\r\n if (this.config.auth.protocolMode === ProtocolMode.EAR) {\r\n return this.executeEarFlow(silentRequest);\r\n } else {\r\n return this.executeCodeFlow(silentRequest);\r\n }\r\n }\r\n\r\n /**\r\n * Executes auth code + PKCE flow\r\n * @param request\r\n * @returns\r\n */\r\n async executeCodeFlow(\r\n request: CommonAuthorizationUrlRequest\r\n ): Promise {\r\n let authClient: AuthorizationCodeClient | undefined;\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(\r\n this.apiId\r\n );\r\n\r\n try {\r\n // Initialize the client\r\n authClient = await invokeAsync(\r\n this.createAuthCodeClient.bind(this),\r\n PerformanceEvents.StandardInteractionClientCreateAuthCodeClient,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )({\r\n serverTelemetryManager,\r\n requestAuthority: request.authority,\r\n requestAzureCloudOptions: request.azureCloudOptions,\r\n requestExtraQueryParameters: request.extraQueryParameters,\r\n account: request.account,\r\n });\r\n\r\n return await invokeAsync(\r\n this.silentTokenHelper.bind(this),\r\n PerformanceEvents.SilentIframeClientTokenHelper,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(authClient, request);\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n (e as AuthError).setCorrelationId(this.correlationId);\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n }\r\n\r\n if (\r\n !authClient ||\r\n !(e instanceof AuthError) ||\r\n e.errorCode !== BrowserConstants.INVALID_GRANT_ERROR\r\n ) {\r\n throw e;\r\n }\r\n\r\n this.performanceClient.addFields(\r\n {\r\n retryError: e.errorCode,\r\n },\r\n this.correlationId\r\n );\r\n\r\n return await invokeAsync(\r\n this.silentTokenHelper.bind(this),\r\n PerformanceEvents.SilentIframeClientTokenHelper,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )(authClient, request);\r\n }\r\n }\r\n\r\n /**\r\n * Executes EAR flow\r\n * @param request\r\n */\r\n async executeEarFlow(\r\n request: CommonAuthorizationUrlRequest\r\n ): Promise {\r\n const correlationId = request.correlationId;\r\n const discoveredAuthority = await invokeAsync(\r\n this.getDiscoveredAuthority.bind(this),\r\n PerformanceEvents.StandardInteractionClientGetDiscoveredAuthority,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )({\r\n requestAuthority: request.authority,\r\n requestAzureCloudOptions: request.azureCloudOptions,\r\n requestExtraQueryParameters: request.extraQueryParameters,\r\n account: request.account,\r\n });\r\n\r\n const earJwk = await invokeAsync(\r\n generateEarKey,\r\n PerformanceEvents.GenerateEarKey,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )();\r\n const silentRequest = {\r\n ...request,\r\n earJwk: earJwk,\r\n };\r\n const msalFrame = await invokeAsync(\r\n initiateEarRequest,\r\n PerformanceEvents.SilentHandlerInitiateAuthRequest,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n this.config,\r\n discoveredAuthority,\r\n silentRequest,\r\n this.logger,\r\n this.performanceClient\r\n );\r\n\r\n const responseType = this.config.auth.OIDCOptions.serverResponseType;\r\n // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.\r\n const responseString = await invokeAsync(\r\n monitorIframeForHash,\r\n PerformanceEvents.SilentHandlerMonitorIframeForHash,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n msalFrame,\r\n this.config.system.iframeHashTimeout,\r\n this.config.system.pollIntervalMilliseconds,\r\n this.performanceClient,\r\n this.logger,\r\n correlationId,\r\n responseType\r\n );\r\n\r\n const serverParams = invoke(\r\n ResponseHandler.deserializeResponse,\r\n PerformanceEvents.DeserializeResponse,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(responseString, responseType, this.logger);\r\n\r\n return invokeAsync(\r\n Authorize.handleResponseEAR,\r\n PerformanceEvents.HandleResponseEar,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n silentRequest,\r\n serverParams,\r\n this.apiId,\r\n this.config,\r\n discoveredAuthority,\r\n this.browserStorage,\r\n this.nativeStorage,\r\n this.eventHandler,\r\n this.logger,\r\n this.performanceClient,\r\n this.platformAuthProvider\r\n );\r\n }\r\n\r\n /**\r\n * Currently Unsupported\r\n */\r\n logout(): Promise {\r\n // Synchronous so we must reject\r\n return Promise.reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.silentLogoutUnsupported\r\n )\r\n );\r\n }\r\n\r\n /**\r\n * Helper which acquires an authorization code silently using a hidden iframe from given url\r\n * using the scopes requested as part of the id, and exchanges the code for a set of OAuth tokens.\r\n * @param navigateUrl\r\n * @param userRequestScopes\r\n */\r\n protected async silentTokenHelper(\r\n authClient: AuthorizationCodeClient,\r\n request: CommonAuthorizationUrlRequest\r\n ): Promise {\r\n const correlationId = request.correlationId;\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.SilentIframeClientTokenHelper,\r\n correlationId\r\n );\r\n const pkceCodes = await invokeAsync(\r\n generatePkceCodes,\r\n PerformanceEvents.GeneratePkceCodes,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(this.performanceClient, this.logger, correlationId);\r\n\r\n const silentRequest = {\r\n ...request,\r\n codeChallenge: pkceCodes.challenge,\r\n };\r\n\r\n let msalFrame: HTMLIFrameElement;\r\n\r\n if (request.httpMethod === HttpMethod.POST) {\r\n msalFrame = await invokeAsync(\r\n initiateCodeFlowWithPost,\r\n PerformanceEvents.SilentHandlerInitiateAuthRequest,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n this.config,\r\n authClient.authority,\r\n silentRequest,\r\n this.logger,\r\n this.performanceClient\r\n );\r\n } else {\r\n // Create authorize request url\r\n const navigateUrl = await invokeAsync(\r\n Authorize.getAuthCodeRequestUrl,\r\n PerformanceEvents.GetAuthCodeUrl,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n this.config,\r\n authClient.authority,\r\n silentRequest,\r\n this.logger,\r\n this.performanceClient\r\n );\r\n\r\n // Get the frame handle for the silent request\r\n msalFrame = await invokeAsync(\r\n initiateCodeRequest,\r\n PerformanceEvents.SilentHandlerInitiateAuthRequest,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n navigateUrl,\r\n this.performanceClient,\r\n this.logger,\r\n correlationId,\r\n this.config.system.navigateFrameWait\r\n );\r\n }\r\n\r\n const responseType = this.config.auth.OIDCOptions.serverResponseType;\r\n // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.\r\n const responseString = await invokeAsync(\r\n monitorIframeForHash,\r\n PerformanceEvents.SilentHandlerMonitorIframeForHash,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n msalFrame,\r\n this.config.system.iframeHashTimeout,\r\n this.config.system.pollIntervalMilliseconds,\r\n this.performanceClient,\r\n this.logger,\r\n correlationId,\r\n responseType\r\n );\r\n const serverParams = invoke(\r\n ResponseHandler.deserializeResponse,\r\n PerformanceEvents.DeserializeResponse,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(responseString, responseType, this.logger);\r\n\r\n return invokeAsync(\r\n Authorize.handleResponseCode,\r\n PerformanceEvents.HandleResponseCode,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n request,\r\n serverParams,\r\n pkceCodes.verifier,\r\n this.apiId,\r\n this.config,\r\n authClient,\r\n this.browserStorage,\r\n this.nativeStorage,\r\n this.eventHandler,\r\n this.logger,\r\n this.performanceClient,\r\n this.platformAuthProvider\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { StandardInteractionClient } from \"./StandardInteractionClient.js\";\r\nimport {\r\n CommonSilentFlowRequest,\r\n ServerTelemetryManager,\r\n RefreshTokenClient,\r\n AuthError,\r\n AzureCloudOptions,\r\n PerformanceEvents,\r\n invokeAsync,\r\n AccountInfo,\r\n StringDict,\r\n} from \"@azure/msal-common/browser\";\r\nimport { ApiId } from \"../utils/BrowserConstants.js\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { initializeBaseRequest } from \"../request/RequestHelpers.js\";\r\n\r\nexport class SilentRefreshClient extends StandardInteractionClient {\r\n /**\r\n * Exchanges the refresh token for new tokens\r\n * @param request\r\n */\r\n async acquireToken(\r\n request: CommonSilentFlowRequest\r\n ): Promise {\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.SilentRefreshClientAcquireToken,\r\n request.correlationId\r\n );\r\n\r\n const baseRequest = await invokeAsync(\r\n initializeBaseRequest,\r\n PerformanceEvents.InitializeBaseRequest,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(request, this.config, this.performanceClient, this.logger);\r\n const silentRequest: CommonSilentFlowRequest = {\r\n ...request,\r\n ...baseRequest,\r\n };\r\n\r\n if (request.redirectUri) {\r\n // Make sure any passed redirectUri is converted to an absolute URL - redirectUri is not a required parameter for refresh token redemption so only include if explicitly provided\r\n silentRequest.redirectUri = this.getRedirectUri(\r\n request.redirectUri\r\n );\r\n }\r\n\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(\r\n ApiId.acquireTokenSilent_silentFlow\r\n );\r\n\r\n const refreshTokenClient = await this.createRefreshTokenClient({\r\n serverTelemetryManager,\r\n authorityUrl: silentRequest.authority,\r\n azureCloudOptions: silentRequest.azureCloudOptions,\r\n account: silentRequest.account,\r\n });\r\n // Send request to renew token. Auth module will throw errors if token cannot be renewed.\r\n return invokeAsync(\r\n refreshTokenClient.acquireTokenByRefreshToken.bind(\r\n refreshTokenClient\r\n ),\r\n PerformanceEvents.RefreshTokenClientAcquireTokenByRefreshToken,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(silentRequest).catch((e: AuthError) => {\r\n (e as AuthError).setCorrelationId(this.correlationId);\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n throw e;\r\n }) as Promise;\r\n }\r\n\r\n /**\r\n * Currently Unsupported\r\n */\r\n logout(): Promise {\r\n // Synchronous so we must reject\r\n return Promise.reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.silentLogoutUnsupported\r\n )\r\n );\r\n }\r\n\r\n /**\r\n * Creates a Refresh Client with the given authority, or the default authority.\r\n * @param params {\r\n * serverTelemetryManager: ServerTelemetryManager;\r\n * authorityUrl?: string;\r\n * azureCloudOptions?: AzureCloudOptions;\r\n * extraQueryParams?: StringDict;\r\n * account?: AccountInfo;\r\n * }\r\n */\r\n protected async createRefreshTokenClient(params: {\r\n serverTelemetryManager: ServerTelemetryManager;\r\n authorityUrl?: string;\r\n azureCloudOptions?: AzureCloudOptions;\r\n extraQueryParameters?: StringDict;\r\n account?: AccountInfo;\r\n }): Promise {\r\n // Create auth module.\r\n const clientConfig = await invokeAsync(\r\n this.getClientConfiguration.bind(this),\r\n PerformanceEvents.StandardInteractionClientGetClientConfiguration,\r\n this.logger,\r\n this.performanceClient,\r\n this.correlationId\r\n )({\r\n serverTelemetryManager: params.serverTelemetryManager,\r\n requestAuthority: params.authorityUrl,\r\n requestAzureCloudOptions: params.azureCloudOptions,\r\n requestExtraQueryParameters: params.extraQueryParameters,\r\n account: params.account,\r\n });\r\n return new RefreshTokenClient(clientConfig, this.performanceClient);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n AccessTokenEntity,\r\n ICrypto,\r\n IdTokenEntity,\r\n Logger,\r\n ScopeSet,\r\n Authority,\r\n AuthorityOptions,\r\n ExternalTokenResponse,\r\n AccountEntity,\r\n AuthToken,\r\n RefreshTokenEntity,\r\n CacheRecord,\r\n TokenClaims,\r\n CacheHelpers,\r\n buildAccountToCache,\r\n TimeUtils,\r\n} from \"@azure/msal-common/browser\";\r\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\r\nimport type { SilentRequest } from \"../request/SilentRequest.js\";\r\nimport { BrowserCacheManager } from \"./BrowserCacheManager.js\";\r\nimport type { ITokenCache } from \"./ITokenCache.js\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport type { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { base64Decode } from \"../encode/Base64Decode.js\";\r\nimport * as BrowserCrypto from \"../crypto/BrowserCrypto.js\";\r\n\r\nexport type LoadTokenOptions = {\r\n clientInfo?: string;\r\n expiresOn?: number;\r\n extendedExpiresOn?: number;\r\n};\r\n\r\n/**\r\n * Token cache manager\r\n */\r\nexport class TokenCache implements ITokenCache {\r\n // Flag to indicate if in browser environment\r\n public isBrowserEnvironment: boolean;\r\n // Input configuration by developer/user\r\n protected config: BrowserConfiguration;\r\n // Browser cache storage\r\n private storage: BrowserCacheManager;\r\n // Logger\r\n private logger: Logger;\r\n // Crypto class\r\n private cryptoObj: ICrypto;\r\n\r\n constructor(\r\n configuration: BrowserConfiguration,\r\n storage: BrowserCacheManager,\r\n logger: Logger,\r\n cryptoObj: ICrypto\r\n ) {\r\n this.isBrowserEnvironment = typeof window !== \"undefined\";\r\n this.config = configuration;\r\n this.storage = storage;\r\n this.logger = logger;\r\n this.cryptoObj = cryptoObj;\r\n }\r\n\r\n // Move getAllAccounts here and cache utility APIs\r\n\r\n /**\r\n * API to load tokens to msal-browser cache.\r\n * @param request\r\n * @param response\r\n * @param options\r\n * @returns `AuthenticationResult` for the response that was loaded.\r\n */\r\n async loadExternalTokens(\r\n request: SilentRequest,\r\n response: ExternalTokenResponse,\r\n options: LoadTokenOptions\r\n ): Promise {\r\n if (!this.isBrowserEnvironment) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.nonBrowserEnvironment\r\n );\r\n }\r\n\r\n const correlationId =\r\n request.correlationId || BrowserCrypto.createNewGuid();\r\n\r\n const idTokenClaims = response.id_token\r\n ? AuthToken.extractTokenClaims(response.id_token, base64Decode)\r\n : undefined;\r\n\r\n const authorityOptions: AuthorityOptions = {\r\n protocolMode: this.config.auth.protocolMode,\r\n knownAuthorities: this.config.auth.knownAuthorities,\r\n cloudDiscoveryMetadata: this.config.auth.cloudDiscoveryMetadata,\r\n authorityMetadata: this.config.auth.authorityMetadata,\r\n skipAuthorityMetadataCache:\r\n this.config.auth.skipAuthorityMetadataCache,\r\n };\r\n const authority = request.authority\r\n ? new Authority(\r\n Authority.generateAuthority(\r\n request.authority,\r\n request.azureCloudOptions\r\n ),\r\n this.config.system.networkClient,\r\n this.storage,\r\n authorityOptions,\r\n this.logger,\r\n request.correlationId || BrowserCrypto.createNewGuid()\r\n )\r\n : undefined;\r\n\r\n const cacheRecordAccount: AccountEntity = await this.loadAccount(\r\n request,\r\n options.clientInfo || response.client_info || \"\",\r\n correlationId,\r\n idTokenClaims,\r\n authority\r\n );\r\n\r\n const idToken = await this.loadIdToken(\r\n response,\r\n cacheRecordAccount.homeAccountId,\r\n cacheRecordAccount.environment,\r\n cacheRecordAccount.realm,\r\n correlationId\r\n );\r\n\r\n const accessToken = await this.loadAccessToken(\r\n request,\r\n response,\r\n cacheRecordAccount.homeAccountId,\r\n cacheRecordAccount.environment,\r\n cacheRecordAccount.realm,\r\n options,\r\n correlationId\r\n );\r\n\r\n const refreshToken = await this.loadRefreshToken(\r\n response,\r\n cacheRecordAccount.homeAccountId,\r\n cacheRecordAccount.environment,\r\n correlationId\r\n );\r\n\r\n return this.generateAuthenticationResult(\r\n request,\r\n {\r\n account: cacheRecordAccount,\r\n idToken,\r\n accessToken,\r\n refreshToken,\r\n },\r\n idTokenClaims,\r\n authority\r\n );\r\n }\r\n\r\n /**\r\n * Helper function to load account to msal-browser cache\r\n * @param idToken\r\n * @param environment\r\n * @param clientInfo\r\n * @param authorityType\r\n * @param requestHomeAccountId\r\n * @returns `AccountEntity`\r\n */\r\n private async loadAccount(\r\n request: SilentRequest,\r\n clientInfo: string,\r\n correlationId: string,\r\n idTokenClaims?: TokenClaims,\r\n authority?: Authority\r\n ): Promise {\r\n this.logger.verbose(\"TokenCache - loading account\");\r\n\r\n if (request.account) {\r\n const accountEntity = AccountEntity.createFromAccountInfo(\r\n request.account\r\n );\r\n await this.storage.setAccount(accountEntity, correlationId);\r\n return accountEntity;\r\n } else if (!authority || (!clientInfo && !idTokenClaims)) {\r\n this.logger.error(\r\n \"TokenCache - if an account is not provided on the request, authority and either clientInfo or idToken must be provided instead.\"\r\n );\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.unableToLoadToken\r\n );\r\n }\r\n\r\n const homeAccountId = AccountEntity.generateHomeAccountId(\r\n clientInfo,\r\n authority.authorityType,\r\n this.logger,\r\n this.cryptoObj,\r\n idTokenClaims\r\n );\r\n\r\n const claimsTenantId = idTokenClaims?.tid;\r\n\r\n const cachedAccount = buildAccountToCache(\r\n this.storage,\r\n authority,\r\n homeAccountId,\r\n base64Decode,\r\n correlationId,\r\n idTokenClaims,\r\n clientInfo,\r\n authority.hostnameAndPort,\r\n claimsTenantId,\r\n undefined, // authCodePayload\r\n undefined, // nativeAccountId\r\n this.logger\r\n );\r\n\r\n await this.storage.setAccount(cachedAccount, correlationId);\r\n return cachedAccount;\r\n }\r\n\r\n /**\r\n * Helper function to load id tokens to msal-browser cache\r\n * @param idToken\r\n * @param homeAccountId\r\n * @param environment\r\n * @param tenantId\r\n * @returns `IdTokenEntity`\r\n */\r\n private async loadIdToken(\r\n response: ExternalTokenResponse,\r\n homeAccountId: string,\r\n environment: string,\r\n tenantId: string,\r\n correlationId: string\r\n ): Promise {\r\n if (!response.id_token) {\r\n this.logger.verbose(\"TokenCache - no id token found in response\");\r\n return null;\r\n }\r\n\r\n this.logger.verbose(\"TokenCache - loading id token\");\r\n const idTokenEntity = CacheHelpers.createIdTokenEntity(\r\n homeAccountId,\r\n environment,\r\n response.id_token,\r\n this.config.auth.clientId,\r\n tenantId\r\n );\r\n\r\n await this.storage.setIdTokenCredential(idTokenEntity, correlationId);\r\n return idTokenEntity;\r\n }\r\n\r\n /**\r\n * Helper function to load access tokens to msal-browser cache\r\n * @param request\r\n * @param response\r\n * @param homeAccountId\r\n * @param environment\r\n * @param tenantId\r\n * @returns `AccessTokenEntity`\r\n */\r\n private async loadAccessToken(\r\n request: SilentRequest,\r\n response: ExternalTokenResponse,\r\n homeAccountId: string,\r\n environment: string,\r\n tenantId: string,\r\n options: LoadTokenOptions,\r\n correlationId: string\r\n ): Promise {\r\n if (!response.access_token) {\r\n this.logger.verbose(\r\n \"TokenCache - no access token found in response\"\r\n );\r\n return null;\r\n } else if (!response.expires_in) {\r\n this.logger.error(\r\n \"TokenCache - no expiration set on the access token. Cannot add it to the cache.\"\r\n );\r\n return null;\r\n } else if (\r\n !response.scope &&\r\n (!request.scopes || !request.scopes.length)\r\n ) {\r\n this.logger.error(\r\n \"TokenCache - scopes not specified in the request or response. Cannot add token to the cache.\"\r\n );\r\n return null;\r\n }\r\n\r\n this.logger.verbose(\"TokenCache - loading access token\");\r\n\r\n const scopes = response.scope\r\n ? ScopeSet.fromString(response.scope)\r\n : new ScopeSet(request.scopes);\r\n const expiresOn =\r\n options.expiresOn || response.expires_in + TimeUtils.nowSeconds();\r\n\r\n const extendedExpiresOn =\r\n options.extendedExpiresOn ||\r\n (response.ext_expires_in || response.expires_in) +\r\n TimeUtils.nowSeconds();\r\n\r\n const accessTokenEntity = CacheHelpers.createAccessTokenEntity(\r\n homeAccountId,\r\n environment,\r\n response.access_token,\r\n this.config.auth.clientId,\r\n tenantId,\r\n scopes.printScopes(),\r\n expiresOn,\r\n extendedExpiresOn,\r\n base64Decode\r\n );\r\n\r\n await this.storage.setAccessTokenCredential(\r\n accessTokenEntity,\r\n correlationId\r\n );\r\n return accessTokenEntity;\r\n }\r\n\r\n /**\r\n * Helper function to load refresh tokens to msal-browser cache\r\n * @param request\r\n * @param response\r\n * @param homeAccountId\r\n * @param environment\r\n * @returns `RefreshTokenEntity`\r\n */\r\n private async loadRefreshToken(\r\n response: ExternalTokenResponse,\r\n homeAccountId: string,\r\n environment: string,\r\n correlationId: string\r\n ): Promise {\r\n if (!response.refresh_token) {\r\n this.logger.verbose(\r\n \"TokenCache - no refresh token found in response\"\r\n );\r\n return null;\r\n }\r\n\r\n this.logger.verbose(\"TokenCache - loading refresh token\");\r\n const refreshTokenEntity = CacheHelpers.createRefreshTokenEntity(\r\n homeAccountId,\r\n environment,\r\n response.refresh_token,\r\n this.config.auth.clientId,\r\n response.foci,\r\n undefined, // userAssertionHash\r\n response.refresh_token_expires_in\r\n );\r\n\r\n await this.storage.setRefreshTokenCredential(\r\n refreshTokenEntity,\r\n correlationId\r\n );\r\n return refreshTokenEntity;\r\n }\r\n\r\n /**\r\n * Helper function to generate an `AuthenticationResult` for the result.\r\n * @param request\r\n * @param idTokenObj\r\n * @param cacheRecord\r\n * @param authority\r\n * @returns `AuthenticationResult`\r\n */\r\n private generateAuthenticationResult(\r\n request: SilentRequest,\r\n cacheRecord: CacheRecord & { account: AccountEntity },\r\n idTokenClaims?: TokenClaims,\r\n authority?: Authority\r\n ): AuthenticationResult {\r\n let accessToken: string = \"\";\r\n let responseScopes: Array = [];\r\n let expiresOn: Date | null = null;\r\n let extExpiresOn: Date | undefined;\r\n\r\n if (cacheRecord?.accessToken) {\r\n accessToken = cacheRecord.accessToken.secret;\r\n responseScopes = ScopeSet.fromString(\r\n cacheRecord.accessToken.target\r\n ).asArray();\r\n // Access token expiresOn stored in seconds, converting to Date for AuthenticationResult\r\n expiresOn = TimeUtils.toDateFromSeconds(\r\n cacheRecord.accessToken.expiresOn\r\n );\r\n extExpiresOn = TimeUtils.toDateFromSeconds(\r\n cacheRecord.accessToken.extendedExpiresOn\r\n );\r\n }\r\n\r\n const accountEntity = cacheRecord.account;\r\n\r\n return {\r\n authority: authority ? authority.canonicalAuthority : \"\",\r\n uniqueId: cacheRecord.account.localAccountId,\r\n tenantId: cacheRecord.account.realm,\r\n scopes: responseScopes,\r\n account: accountEntity.getAccountInfo(),\r\n idToken: cacheRecord.idToken?.secret || \"\",\r\n idTokenClaims: idTokenClaims || {},\r\n accessToken: accessToken,\r\n fromCache: true,\r\n expiresOn: expiresOn,\r\n correlationId: request.correlationId || \"\",\r\n requestId: \"\",\r\n extExpiresOn: extExpiresOn,\r\n familyId: cacheRecord.refreshToken?.familyId || \"\",\r\n tokenType: cacheRecord?.accessToken?.tokenType || \"\",\r\n state: request.state || \"\",\r\n cloudGraphHostName: accountEntity.cloudGraphHostName || \"\",\r\n msGraphHost: accountEntity.msGraphHost || \"\",\r\n fromNativeBroker: false,\r\n };\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n AuthorizationCodeClient,\r\n ClientConfiguration,\r\n} from \"@azure/msal-common/browser\";\r\n\r\nexport class HybridSpaAuthorizationCodeClient extends AuthorizationCodeClient {\r\n constructor(config: ClientConfiguration) {\r\n super(config);\r\n this.includeRedirectUri = false;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n ICrypto,\r\n Logger,\r\n CommonAuthorizationCodeRequest,\r\n AuthError,\r\n IPerformanceClient,\r\n PerformanceEvents,\r\n invokeAsync,\r\n CommonAuthorizationUrlRequest,\r\n} from \"@azure/msal-common/browser\";\r\nimport { StandardInteractionClient } from \"./StandardInteractionClient.js\";\r\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\r\nimport { BrowserCacheManager } from \"../cache/BrowserCacheManager.js\";\r\nimport { EventHandler } from \"../event/EventHandler.js\";\r\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { InteractionType, ApiId } from \"../utils/BrowserConstants.js\";\r\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\r\nimport { HybridSpaAuthorizationCodeClient } from \"./HybridSpaAuthorizationCodeClient.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { InteractionHandler } from \"../interaction_handler/InteractionHandler.js\";\r\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\r\n\r\nexport class SilentAuthCodeClient extends StandardInteractionClient {\r\n private apiId: ApiId;\r\n\r\n constructor(\r\n config: BrowserConfiguration,\r\n storageImpl: BrowserCacheManager,\r\n browserCrypto: ICrypto,\r\n logger: Logger,\r\n eventHandler: EventHandler,\r\n navigationClient: INavigationClient,\r\n apiId: ApiId,\r\n performanceClient: IPerformanceClient,\r\n platformAuthProvider?: IPlatformAuthHandler,\r\n correlationId?: string\r\n ) {\r\n super(\r\n config,\r\n storageImpl,\r\n browserCrypto,\r\n logger,\r\n eventHandler,\r\n navigationClient,\r\n performanceClient,\r\n platformAuthProvider,\r\n correlationId\r\n );\r\n this.apiId = apiId;\r\n }\r\n\r\n /**\r\n * Acquires a token silently by redeeming an authorization code against the /token endpoint\r\n * @param request\r\n */\r\n async acquireToken(\r\n request: AuthorizationCodeRequest\r\n ): Promise {\r\n // Auth code payload is required\r\n if (!request.code) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.authCodeRequired\r\n );\r\n }\r\n\r\n // Create silent request\r\n const silentRequest: CommonAuthorizationUrlRequest = await invokeAsync(\r\n this.initializeAuthorizationRequest.bind(this),\r\n PerformanceEvents.StandardInteractionClientInitializeAuthorizationRequest,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(request, InteractionType.Silent);\r\n\r\n const serverTelemetryManager = this.initializeServerTelemetryManager(\r\n this.apiId\r\n );\r\n\r\n try {\r\n // Create auth code request (PKCE not needed)\r\n const authCodeRequest: CommonAuthorizationCodeRequest = {\r\n ...silentRequest,\r\n code: request.code,\r\n };\r\n\r\n // Initialize the client\r\n const clientConfig = await invokeAsync(\r\n this.getClientConfiguration.bind(this),\r\n PerformanceEvents.StandardInteractionClientGetClientConfiguration,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )({\r\n serverTelemetryManager,\r\n requestAuthority: silentRequest.authority,\r\n requestAzureCloudOptions: silentRequest.azureCloudOptions,\r\n requestExtraQueryParameters: silentRequest.extraQueryParameters,\r\n account: silentRequest.account,\r\n });\r\n const authClient: HybridSpaAuthorizationCodeClient =\r\n new HybridSpaAuthorizationCodeClient(clientConfig);\r\n this.logger.verbose(\"Auth code client created\");\r\n\r\n // Create silent handler\r\n const interactionHandler = new InteractionHandler(\r\n authClient,\r\n this.browserStorage,\r\n authCodeRequest,\r\n this.logger,\r\n this.performanceClient\r\n );\r\n\r\n // Handle auth code parameters from request\r\n return await invokeAsync(\r\n interactionHandler.handleCodeResponseFromServer.bind(\r\n interactionHandler\r\n ),\r\n PerformanceEvents.HandleCodeResponseFromServer,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(\r\n {\r\n code: request.code,\r\n msgraph_host: request.msGraphHost,\r\n cloud_graph_host_name: request.cloudGraphHostName,\r\n cloud_instance_host_name: request.cloudInstanceHostName,\r\n },\r\n silentRequest,\r\n false\r\n );\r\n } catch (e) {\r\n if (e instanceof AuthError) {\r\n (e as AuthError).setCorrelationId(this.correlationId);\r\n serverTelemetryManager.cacheFailedRequest(e);\r\n }\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Currently Unsupported\r\n */\r\n logout(): Promise {\r\n // Synchronous so we must reject\r\n return Promise.reject(\r\n createBrowserAuthError(\r\n BrowserAuthErrorCodes.silentLogoutUnsupported\r\n )\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { InProgressPerformanceEvent, Logger } from \"@azure/msal-common/browser\";\r\n\r\nexport function collectInstanceStats(\r\n currentClientId: string,\r\n performanceEvent: InProgressPerformanceEvent,\r\n logger: Logger\r\n): void {\r\n const frameInstances: string[] =\r\n // @ts-ignore\r\n window.msal?.clientIds || [];\r\n\r\n const msalInstanceCount = frameInstances.length;\r\n\r\n const sameClientIdInstanceCount = frameInstances.filter(\r\n (i) => i === currentClientId\r\n ).length;\r\n\r\n if (sameClientIdInstanceCount > 1) {\r\n logger.warning(\r\n \"There is already an instance of MSAL.js in the window with the same client id.\"\r\n );\r\n }\r\n performanceEvent.add({\r\n msalInstanceCount: msalInstanceCount,\r\n sameClientIdInstanceCount: sameClientIdInstanceCount,\r\n });\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { CryptoOps } from \"../crypto/CryptoOps.js\";\r\nimport {\r\n InteractionRequiredAuthError,\r\n AccountInfo,\r\n Constants,\r\n INetworkModule,\r\n Logger,\r\n CommonSilentFlowRequest,\r\n ICrypto,\r\n DEFAULT_CRYPTO_IMPLEMENTATION,\r\n AuthError,\r\n PerformanceEvents,\r\n PerformanceCallbackFunction,\r\n IPerformanceClient,\r\n BaseAuthRequest,\r\n PromptValue,\r\n InProgressPerformanceEvent,\r\n getRequestThumbprint,\r\n AccountEntity,\r\n invokeAsync,\r\n invoke,\r\n createClientAuthError,\r\n ClientAuthErrorCodes,\r\n AccountFilter,\r\n buildStaticAuthorityOptions,\r\n InteractionRequiredAuthErrorCodes,\r\n PkceCodes,\r\n} from \"@azure/msal-common/browser\";\r\nimport {\r\n BrowserCacheManager,\r\n DEFAULT_BROWSER_CACHE_MANAGER,\r\n} from \"../cache/BrowserCacheManager.js\";\r\nimport * as AccountManager from \"../cache/AccountManager.js\";\r\nimport { BrowserConfiguration, CacheOptions } from \"../config/Configuration.js\";\r\nimport {\r\n InteractionType,\r\n ApiId,\r\n BrowserCacheLocation,\r\n WrapperSKU,\r\n CacheLookupPolicy,\r\n DEFAULT_REQUEST,\r\n BrowserConstants,\r\n iFrameRenewalPolicies,\r\n INTERACTION_TYPE,\r\n} from \"../utils/BrowserConstants.js\";\r\nimport * as BrowserUtils from \"../utils/BrowserUtils.js\";\r\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\r\nimport { PopupRequest } from \"../request/PopupRequest.js\";\r\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\r\nimport { EventCallbackFunction, EventError } from \"../event/EventMessage.js\";\r\nimport { EventType } from \"../event/EventType.js\";\r\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\r\nimport { EndSessionPopupRequest } from \"../request/EndSessionPopupRequest.js\";\r\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\r\nimport { EventHandler } from \"../event/EventHandler.js\";\r\nimport { PopupClient } from \"../interaction_client/PopupClient.js\";\r\nimport { RedirectClient } from \"../interaction_client/RedirectClient.js\";\r\nimport { SilentIframeClient } from \"../interaction_client/SilentIframeClient.js\";\r\nimport { SilentRefreshClient } from \"../interaction_client/SilentRefreshClient.js\";\r\nimport { TokenCache } from \"../cache/TokenCache.js\";\r\nimport { ITokenCache } from \"../cache/ITokenCache.js\";\r\nimport { PlatformAuthInteractionClient } from \"../interaction_client/PlatformAuthInteractionClient.js\";\r\nimport { SilentRequest } from \"../request/SilentRequest.js\";\r\nimport {\r\n NativeAuthError,\r\n isFatalNativeAuthError,\r\n} from \"../error/NativeAuthError.js\";\r\nimport { SilentCacheClient } from \"../interaction_client/SilentCacheClient.js\";\r\nimport { SilentAuthCodeClient } from \"../interaction_client/SilentAuthCodeClient.js\";\r\nimport {\r\n createBrowserAuthError,\r\n BrowserAuthErrorCodes,\r\n} from \"../error/BrowserAuthError.js\";\r\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\r\nimport { PlatformAuthRequest } from \"../broker/nativeBroker/PlatformAuthRequest.js\";\r\nimport { StandardOperatingContext } from \"../operatingcontext/StandardOperatingContext.js\";\r\nimport { BaseOperatingContext } from \"../operatingcontext/BaseOperatingContext.js\";\r\nimport { IController } from \"./IController.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\r\nimport { createNewGuid } from \"../crypto/BrowserCrypto.js\";\r\nimport { initializeSilentRequest } from \"../request/RequestHelpers.js\";\r\nimport { InitializeApplicationRequest } from \"../request/InitializeApplicationRequest.js\";\r\nimport { generatePkceCodes } from \"../crypto/PkceGenerator.js\";\r\nimport {\r\n getPlatformAuthProvider,\r\n isPlatformAuthAllowed,\r\n} from \"../broker/nativeBroker/PlatformAuthProvider.js\";\r\nimport { IPlatformAuthHandler } from \"../broker/nativeBroker/IPlatformAuthHandler.js\";\r\nimport { collectInstanceStats } from \"../utils/MsalFrameStatsUtils.js\";\r\n\r\nfunction getAccountType(\r\n account?: AccountInfo\r\n): \"AAD\" | \"MSA\" | \"B2C\" | undefined {\r\n const idTokenClaims = account?.idTokenClaims;\r\n if (idTokenClaims?.tfp || idTokenClaims?.acr) {\r\n return \"B2C\";\r\n }\r\n\r\n if (!idTokenClaims?.tid) {\r\n return undefined;\r\n } else if (idTokenClaims?.tid === \"9188040d-6c67-4c5b-b112-36a304b66dad\") {\r\n return \"MSA\";\r\n }\r\n return \"AAD\";\r\n}\r\n\r\nfunction preflightCheck(\r\n initialized: boolean,\r\n performanceEvent: InProgressPerformanceEvent\r\n) {\r\n try {\r\n BrowserUtils.preflightCheck(initialized);\r\n } catch (e) {\r\n performanceEvent.end({ success: false }, e);\r\n throw e;\r\n }\r\n}\r\n\r\nexport class StandardController implements IController {\r\n // OperatingContext\r\n protected readonly operatingContext: StandardOperatingContext;\r\n\r\n // Crypto interface implementation\r\n protected readonly browserCrypto: ICrypto;\r\n\r\n // Storage interface implementation\r\n protected readonly browserStorage: BrowserCacheManager;\r\n\r\n // Native Cache in memory storage implementation\r\n protected readonly nativeInternalStorage: BrowserCacheManager;\r\n\r\n // Network interface implementation\r\n protected readonly networkClient: INetworkModule;\r\n\r\n // Navigation interface implementation\r\n protected navigationClient: INavigationClient;\r\n\r\n // Input configuration by developer/user\r\n protected readonly config: BrowserConfiguration;\r\n\r\n // Token cache implementation\r\n private tokenCache: TokenCache;\r\n\r\n // Logger\r\n protected logger: Logger;\r\n\r\n // Flag to indicate if in browser environment\r\n protected isBrowserEnvironment: boolean;\r\n\r\n protected readonly eventHandler: EventHandler;\r\n\r\n // Redirect Response Object\r\n protected readonly redirectResponse: Map<\r\n string,\r\n Promise\r\n >;\r\n\r\n // Native Extension Provider\r\n protected platformAuthProvider: IPlatformAuthHandler | undefined;\r\n\r\n // Hybrid auth code responses\r\n private hybridAuthCodeResponses: Map>;\r\n\r\n // Performance telemetry client\r\n protected readonly performanceClient: IPerformanceClient;\r\n\r\n // Flag representing whether or not the initialize API has been called and completed\r\n protected initialized: boolean;\r\n\r\n // Active requests\r\n private activeSilentTokenRequests: Map<\r\n string,\r\n Promise\r\n >;\r\n\r\n // Active Iframe request\r\n private activeIframeRequest: [Promise, string] | undefined;\r\n\r\n private ssoSilentMeasurement?: InProgressPerformanceEvent;\r\n private acquireTokenByCodeAsyncMeasurement?: InProgressPerformanceEvent;\r\n\r\n private pkceCode: PkceCodes | undefined;\r\n\r\n /**\r\n * @constructor\r\n * Constructor for the PublicClientApplication used to instantiate the PublicClientApplication object\r\n *\r\n * Important attributes in the Configuration object for auth are:\r\n * - clientID: the application ID of your application. You can obtain one by registering your application with our Application registration portal : https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredAppsPreview\r\n * - authority: the authority URL for your application.\r\n * - redirect_uri: the uri of your application registered in the portal.\r\n *\r\n * In Azure AD, authority is a URL indicating the Azure active directory that MSAL uses to obtain tokens.\r\n * It is of the form https://login.microsoftonline.com/{Enter_the_Tenant_Info_Here}\r\n * If your application supports Accounts in one organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with the Tenant Id or Tenant name (for example, contoso.microsoft.com).\r\n * If your application supports Accounts in any organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with organizations.\r\n * If your application supports Accounts in any organizational directory and personal Microsoft accounts, replace \"Enter_the_Tenant_Info_Here\" value with common.\r\n * To restrict support to Personal Microsoft accounts only, replace \"Enter_the_Tenant_Info_Here\" value with consumers.\r\n *\r\n * In Azure B2C, authority is of the form https://{instance}/tfp/{tenant}/{policyName}/\r\n * Full B2C functionality will be available in this library in future versions.\r\n *\r\n * @param configuration Object for the MSAL PublicClientApplication instance\r\n */\r\n constructor(operatingContext: StandardOperatingContext) {\r\n this.operatingContext = operatingContext;\r\n this.isBrowserEnvironment =\r\n this.operatingContext.isBrowserEnvironment();\r\n // Set the configuration.\r\n this.config = operatingContext.getConfig();\r\n this.initialized = false;\r\n\r\n // Initialize logger\r\n this.logger = this.operatingContext.getLogger();\r\n\r\n // Initialize the network module class.\r\n this.networkClient = this.config.system.networkClient;\r\n\r\n // Initialize the navigation client class.\r\n this.navigationClient = this.config.system.navigationClient;\r\n\r\n // Initialize redirectResponse Map\r\n this.redirectResponse = new Map();\r\n\r\n // Initial hybrid spa map\r\n this.hybridAuthCodeResponses = new Map();\r\n\r\n // Initialize performance client\r\n this.performanceClient = this.config.telemetry.client;\r\n\r\n // Initialize the crypto class.\r\n this.browserCrypto = this.isBrowserEnvironment\r\n ? new CryptoOps(this.logger, this.performanceClient)\r\n : DEFAULT_CRYPTO_IMPLEMENTATION;\r\n\r\n this.eventHandler = new EventHandler(this.logger);\r\n\r\n // Initialize the browser storage class.\r\n this.browserStorage = this.isBrowserEnvironment\r\n ? new BrowserCacheManager(\r\n this.config.auth.clientId,\r\n this.config.cache,\r\n this.browserCrypto,\r\n this.logger,\r\n this.performanceClient,\r\n this.eventHandler,\r\n buildStaticAuthorityOptions(this.config.auth)\r\n )\r\n : DEFAULT_BROWSER_CACHE_MANAGER(\r\n this.config.auth.clientId,\r\n this.logger,\r\n this.performanceClient,\r\n this.eventHandler\r\n );\r\n\r\n // initialize in memory storage for native flows\r\n const nativeCacheOptions: Required = {\r\n cacheLocation: BrowserCacheLocation.MemoryStorage,\r\n cacheRetentionDays: 5,\r\n temporaryCacheLocation: BrowserCacheLocation.MemoryStorage,\r\n storeAuthStateInCookie: false,\r\n secureCookies: false,\r\n cacheMigrationEnabled: false,\r\n claimsBasedCachingEnabled: false,\r\n };\r\n this.nativeInternalStorage = new BrowserCacheManager(\r\n this.config.auth.clientId,\r\n nativeCacheOptions,\r\n this.browserCrypto,\r\n this.logger,\r\n this.performanceClient,\r\n this.eventHandler\r\n );\r\n\r\n // Initialize the token cache\r\n this.tokenCache = new TokenCache(\r\n this.config,\r\n this.browserStorage,\r\n this.logger,\r\n this.browserCrypto\r\n );\r\n\r\n this.activeSilentTokenRequests = new Map();\r\n\r\n // Register listener functions\r\n this.trackPageVisibility = this.trackPageVisibility.bind(this);\r\n\r\n // Register listener functions\r\n this.trackPageVisibilityWithMeasurement =\r\n this.trackPageVisibilityWithMeasurement.bind(this);\r\n }\r\n\r\n static async createController(\r\n operatingContext: BaseOperatingContext,\r\n request?: InitializeApplicationRequest\r\n ): Promise {\r\n const controller = new StandardController(operatingContext);\r\n await controller.initialize(request);\r\n return controller;\r\n }\r\n\r\n private trackPageVisibility(correlationId?: string): void {\r\n if (!correlationId) {\r\n return;\r\n }\r\n this.logger.info(\"Perf: Visibility change detected\");\r\n this.performanceClient.incrementFields(\r\n { visibilityChangeCount: 1 },\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Initializer function to perform async startup tasks such as connecting to WAM extension\r\n * @param request {?InitializeApplicationRequest} correlation id\r\n */\r\n async initialize(\r\n request?: InitializeApplicationRequest,\r\n isBroker?: boolean\r\n ): Promise {\r\n this.logger.trace(\"initialize called\");\r\n if (this.initialized) {\r\n this.logger.info(\r\n \"initialize has already been called, exiting early.\"\r\n );\r\n return;\r\n }\r\n\r\n if (!this.isBrowserEnvironment) {\r\n this.logger.info(\"in non-browser environment, exiting early.\");\r\n this.initialized = true;\r\n this.eventHandler.emitEvent(EventType.INITIALIZE_END);\r\n return;\r\n }\r\n\r\n const initCorrelationId =\r\n request?.correlationId || this.getRequestCorrelationId();\r\n const allowPlatformBroker = this.config.system.allowPlatformBroker;\r\n const initMeasurement = this.performanceClient.startMeasurement(\r\n PerformanceEvents.InitializeClientApplication,\r\n initCorrelationId\r\n );\r\n this.eventHandler.emitEvent(EventType.INITIALIZE_START);\r\n\r\n // Broker applications are initialized twice, so we avoid double-counting it\r\n if (!isBroker) {\r\n try {\r\n this.logMultipleInstances(initMeasurement);\r\n } catch {}\r\n }\r\n\r\n await invokeAsync(\r\n this.browserStorage.initialize.bind(this.browserStorage),\r\n PerformanceEvents.InitializeCache,\r\n this.logger,\r\n this.performanceClient,\r\n initCorrelationId\r\n )(initCorrelationId);\r\n\r\n if (allowPlatformBroker) {\r\n try {\r\n // check if platform authentication is available via DOM or browser extension and create relevant handlers\r\n this.platformAuthProvider = await getPlatformAuthProvider(\r\n this.logger,\r\n this.performanceClient,\r\n initCorrelationId,\r\n this.config.system.nativeBrokerHandshakeTimeout\r\n );\r\n } catch (e) {\r\n this.logger.verbose(e as string);\r\n }\r\n }\r\n\r\n if (!this.config.cache.claimsBasedCachingEnabled) {\r\n this.logger.verbose(\r\n \"Claims-based caching is disabled. Clearing the previous cache with claims\"\r\n );\r\n\r\n invoke(\r\n this.browserStorage.clearTokensAndKeysWithClaims.bind(\r\n this.browserStorage\r\n ),\r\n PerformanceEvents.ClearTokensAndKeysWithClaims,\r\n this.logger,\r\n this.performanceClient,\r\n initCorrelationId\r\n )(initCorrelationId);\r\n }\r\n\r\n this.config.system.asyncPopups &&\r\n (await this.preGeneratePkceCodes(initCorrelationId));\r\n this.initialized = true;\r\n this.eventHandler.emitEvent(EventType.INITIALIZE_END);\r\n initMeasurement.end({\r\n allowPlatformBroker: allowPlatformBroker,\r\n success: true,\r\n });\r\n }\r\n\r\n // #region Redirect Flow\r\n\r\n /**\r\n * Event handler function which allows users to fire events after the PublicClientApplication object\r\n * has loaded during redirect flows. This should be invoked on all page loads involved in redirect\r\n * auth flows.\r\n * @param hash Hash to process. Defaults to the current value of window.location.hash. Only needs to be provided explicitly if the response to be handled is not contained in the current value.\r\n * @returns Token response or null. If the return value is null, then no auth redirect was detected.\r\n */\r\n async handleRedirectPromise(\r\n hash?: string\r\n ): Promise {\r\n this.logger.verbose(\"handleRedirectPromise called\");\r\n // Block token acquisition before initialize has been called\r\n BrowserUtils.blockAPICallsBeforeInitialize(this.initialized);\r\n\r\n if (this.isBrowserEnvironment) {\r\n /**\r\n * Store the promise on the PublicClientApplication instance if this is the first invocation of handleRedirectPromise,\r\n * otherwise return the promise from the first invocation. Prevents race conditions when handleRedirectPromise is called\r\n * several times concurrently.\r\n */\r\n const redirectResponseKey = hash || \"\";\r\n let response = this.redirectResponse.get(redirectResponseKey);\r\n if (typeof response === \"undefined\") {\r\n response = this.handleRedirectPromiseInternal(hash);\r\n this.redirectResponse.set(redirectResponseKey, response);\r\n this.logger.verbose(\r\n \"handleRedirectPromise has been called for the first time, storing the promise\"\r\n );\r\n } else {\r\n this.logger.verbose(\r\n \"handleRedirectPromise has been called previously, returning the result from the first call\"\r\n );\r\n }\r\n\r\n return response;\r\n }\r\n this.logger.verbose(\r\n \"handleRedirectPromise returns null, not browser environment\"\r\n );\r\n return null;\r\n }\r\n\r\n /**\r\n * The internal details of handleRedirectPromise. This is separated out to a helper to allow handleRedirectPromise to memoize requests\r\n * @param hash\r\n * @returns\r\n */\r\n private async handleRedirectPromiseInternal(\r\n hash?: string\r\n ): Promise {\r\n if (!this.browserStorage.isInteractionInProgress(true)) {\r\n this.logger.info(\r\n \"handleRedirectPromise called but there is no interaction in progress, returning null.\"\r\n );\r\n return null;\r\n }\r\n\r\n const interactionType =\r\n this.browserStorage.getInteractionInProgress()?.type;\r\n if (interactionType === INTERACTION_TYPE.SIGNOUT) {\r\n this.logger.verbose(\r\n \"handleRedirectPromise removing interaction_in_progress flag and returning null after sign-out\"\r\n );\r\n this.browserStorage.setInteractionInProgress(false);\r\n return Promise.resolve(null);\r\n }\r\n\r\n const loggedInAccounts = this.getAllAccounts();\r\n const platformBrokerRequest: PlatformAuthRequest | null =\r\n this.browserStorage.getCachedNativeRequest();\r\n const useNative =\r\n platformBrokerRequest && this.platformAuthProvider && !hash;\r\n\r\n let rootMeasurement: InProgressPerformanceEvent;\r\n\r\n this.eventHandler.emitEvent(\r\n EventType.HANDLE_REDIRECT_START,\r\n InteractionType.Redirect\r\n );\r\n\r\n let redirectResponse: Promise;\r\n try {\r\n if (useNative && this.platformAuthProvider) {\r\n rootMeasurement = this.performanceClient.startMeasurement(\r\n PerformanceEvents.AcquireTokenRedirect,\r\n platformBrokerRequest?.correlationId || \"\"\r\n );\r\n this.logger.trace(\r\n \"handleRedirectPromise - acquiring token from native platform\"\r\n );\r\n rootMeasurement.add({\r\n isPlatformBrokerRequest: true,\r\n });\r\n const nativeClient = new PlatformAuthInteractionClient(\r\n this.config,\r\n this.browserStorage,\r\n this.browserCrypto,\r\n this.logger,\r\n this.eventHandler,\r\n this.navigationClient,\r\n ApiId.handleRedirectPromise,\r\n this.performanceClient,\r\n this.platformAuthProvider,\r\n platformBrokerRequest.accountId,\r\n this.nativeInternalStorage,\r\n platformBrokerRequest.correlationId\r\n );\r\n\r\n redirectResponse = invokeAsync(\r\n nativeClient.handleRedirectPromise.bind(nativeClient),\r\n PerformanceEvents.HandleNativeRedirectPromiseMeasurement,\r\n this.logger,\r\n this.performanceClient,\r\n rootMeasurement.event.correlationId\r\n )(this.performanceClient, rootMeasurement.event.correlationId);\r\n } else {\r\n const [standardRequest, codeVerifier] =\r\n this.browserStorage.getCachedRequest();\r\n const correlationId = standardRequest.correlationId;\r\n // Reset rootMeasurement now that we have correlationId\r\n rootMeasurement = this.performanceClient.startMeasurement(\r\n PerformanceEvents.AcquireTokenRedirect,\r\n correlationId\r\n );\r\n this.logger.trace(\r\n \"handleRedirectPromise - acquiring token from web flow\"\r\n );\r\n const redirectClient = this.createRedirectClient(correlationId);\r\n redirectResponse = invokeAsync(\r\n redirectClient.handleRedirectPromise.bind(redirectClient),\r\n PerformanceEvents.HandleRedirectPromiseMeasurement,\r\n this.logger,\r\n this.performanceClient,\r\n rootMeasurement.event.correlationId\r\n )(hash, standardRequest, codeVerifier, rootMeasurement);\r\n }\r\n } catch (e) {\r\n this.browserStorage.resetRequestCache();\r\n throw e;\r\n }\r\n\r\n return redirectResponse\r\n .then((result: AuthenticationResult | null) => {\r\n if (result) {\r\n this.browserStorage.resetRequestCache();\r\n // Emit login event if number of accounts change\r\n const isLoggingIn =\r\n loggedInAccounts.length < this.getAllAccounts().length;\r\n if (isLoggingIn) {\r\n this.eventHandler.emitEvent(\r\n EventType.LOGIN_SUCCESS,\r\n InteractionType.Redirect,\r\n result\r\n );\r\n this.logger.verbose(\r\n \"handleRedirectResponse returned result, login success\"\r\n );\r\n } else {\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_SUCCESS,\r\n InteractionType.Redirect,\r\n result\r\n );\r\n this.logger.verbose(\r\n \"handleRedirectResponse returned result, acquire token success\"\r\n );\r\n }\r\n rootMeasurement.end({\r\n success: true,\r\n accountType: getAccountType(result.account),\r\n });\r\n } else {\r\n /*\r\n * Instrument an event only if an error code is set. Otherwise, discard it when the redirect response\r\n * is empty and the error code is missing.\r\n */\r\n if (rootMeasurement.event.errorCode) {\r\n rootMeasurement.end({ success: false });\r\n } else {\r\n rootMeasurement.discard();\r\n }\r\n }\r\n\r\n this.eventHandler.emitEvent(\r\n EventType.HANDLE_REDIRECT_END,\r\n InteractionType.Redirect\r\n );\r\n\r\n return result;\r\n })\r\n .catch((e) => {\r\n this.browserStorage.resetRequestCache();\r\n const eventError = e as EventError;\r\n // Emit login event if there is an account\r\n if (loggedInAccounts.length > 0) {\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_FAILURE,\r\n InteractionType.Redirect,\r\n null,\r\n eventError\r\n );\r\n } else {\r\n this.eventHandler.emitEvent(\r\n EventType.LOGIN_FAILURE,\r\n InteractionType.Redirect,\r\n null,\r\n eventError\r\n );\r\n }\r\n this.eventHandler.emitEvent(\r\n EventType.HANDLE_REDIRECT_END,\r\n InteractionType.Redirect\r\n );\r\n\r\n rootMeasurement.end(\r\n {\r\n success: false,\r\n },\r\n eventError\r\n );\r\n\r\n throw e;\r\n });\r\n }\r\n\r\n /**\r\n * Use when you want to obtain an access_token for your API by redirecting the user's browser window to the authorization endpoint. This function redirects\r\n * the page, so any code that follows this function will not execute.\r\n *\r\n * IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current\r\n * browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.\r\n *\r\n * @param request\r\n */\r\n async acquireTokenRedirect(request: RedirectRequest): Promise {\r\n // Preflight request\r\n const correlationId = this.getRequestCorrelationId(request);\r\n this.logger.verbose(\"acquireTokenRedirect called\", correlationId);\r\n\r\n const atrMeasurement = this.performanceClient.startMeasurement(\r\n PerformanceEvents.AcquireTokenPreRedirect,\r\n correlationId\r\n );\r\n atrMeasurement.add({\r\n accountType: getAccountType(request.account),\r\n scenarioId: request.scenarioId,\r\n });\r\n\r\n // Override on request only if set, as onRedirectNavigate field is deprecated\r\n const onRedirectNavigateCb = request.onRedirectNavigate;\r\n if (onRedirectNavigateCb) {\r\n request.onRedirectNavigate = (url: string) => {\r\n const navigate =\r\n typeof onRedirectNavigateCb === \"function\"\r\n ? onRedirectNavigateCb(url)\r\n : undefined;\r\n atrMeasurement.add({\r\n navigateCallbackResult: navigate !== false,\r\n });\r\n atrMeasurement.event =\r\n atrMeasurement.end({ success: true }) ||\r\n atrMeasurement.event;\r\n return navigate;\r\n };\r\n } else {\r\n const configOnRedirectNavigateCb =\r\n this.config.auth.onRedirectNavigate;\r\n this.config.auth.onRedirectNavigate = (url: string) => {\r\n const navigate =\r\n typeof configOnRedirectNavigateCb === \"function\"\r\n ? configOnRedirectNavigateCb(url)\r\n : undefined;\r\n atrMeasurement.add({\r\n navigateCallbackResult: navigate !== false,\r\n });\r\n atrMeasurement.event =\r\n atrMeasurement.end({ success: true }) ||\r\n atrMeasurement.event;\r\n return navigate;\r\n };\r\n }\r\n\r\n // If logged in, emit acquire token events\r\n const isLoggedIn = this.getAllAccounts().length > 0;\r\n try {\r\n BrowserUtils.redirectPreflightCheck(this.initialized, this.config);\r\n this.browserStorage.setInteractionInProgress(\r\n true,\r\n INTERACTION_TYPE.SIGNIN\r\n );\r\n\r\n if (isLoggedIn) {\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_START,\r\n InteractionType.Redirect,\r\n request\r\n );\r\n } else {\r\n this.eventHandler.emitEvent(\r\n EventType.LOGIN_START,\r\n InteractionType.Redirect,\r\n request\r\n );\r\n }\r\n\r\n let result: Promise;\r\n\r\n if (\r\n this.platformAuthProvider &&\r\n this.canUsePlatformBroker(request)\r\n ) {\r\n const nativeClient = new PlatformAuthInteractionClient(\r\n this.config,\r\n this.browserStorage,\r\n this.browserCrypto,\r\n this.logger,\r\n this.eventHandler,\r\n this.navigationClient,\r\n ApiId.acquireTokenRedirect,\r\n this.performanceClient,\r\n this.platformAuthProvider,\r\n this.getNativeAccountId(request),\r\n this.nativeInternalStorage,\r\n correlationId\r\n );\r\n\r\n result = nativeClient\r\n .acquireTokenRedirect(request, atrMeasurement)\r\n .catch((e: AuthError) => {\r\n atrMeasurement.add({\r\n brokerErrorName: e.name,\r\n brokerErrorCode: e.errorCode,\r\n });\r\n if (\r\n e instanceof NativeAuthError &&\r\n isFatalNativeAuthError(e)\r\n ) {\r\n this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt platform broker calls\r\n const redirectClient =\r\n this.createRedirectClient(correlationId);\r\n return redirectClient.acquireToken(request);\r\n } else if (e instanceof InteractionRequiredAuthError) {\r\n this.logger.verbose(\r\n \"acquireTokenRedirect - Resolving interaction required error thrown by native broker by falling back to web flow\"\r\n );\r\n const redirectClient =\r\n this.createRedirectClient(correlationId);\r\n return redirectClient.acquireToken(request);\r\n }\r\n throw e;\r\n });\r\n } else {\r\n const redirectClient = this.createRedirectClient(correlationId);\r\n result = redirectClient.acquireToken(request);\r\n }\r\n\r\n return await result;\r\n } catch (e) {\r\n this.browserStorage.resetRequestCache();\r\n /*\r\n * Pre-redirect event completes before navigation occurs.\r\n * Timed out navigation needs to be instrumented separately as a post-redirect event.\r\n */\r\n if (atrMeasurement.event.status === 2) {\r\n this.performanceClient\r\n .startMeasurement(\r\n PerformanceEvents.AcquireTokenRedirect,\r\n correlationId\r\n )\r\n .end({ success: false }, e);\r\n } else {\r\n atrMeasurement.end({ success: false }, e);\r\n }\r\n\r\n if (isLoggedIn) {\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_FAILURE,\r\n InteractionType.Redirect,\r\n null,\r\n e as EventError\r\n );\r\n } else {\r\n this.eventHandler.emitEvent(\r\n EventType.LOGIN_FAILURE,\r\n InteractionType.Redirect,\r\n null,\r\n e as EventError\r\n );\r\n }\r\n throw e;\r\n }\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Popup Flow\r\n\r\n /**\r\n * Use when you want to obtain an access_token for your API via opening a popup window in the user's browser\r\n *\r\n * @param request\r\n *\r\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\r\n */\r\n acquireTokenPopup(request: PopupRequest): Promise {\r\n const correlationId = this.getRequestCorrelationId(request);\r\n const atPopupMeasurement = this.performanceClient.startMeasurement(\r\n PerformanceEvents.AcquireTokenPopup,\r\n correlationId\r\n );\r\n\r\n atPopupMeasurement.add({\r\n scenarioId: request.scenarioId,\r\n accountType: getAccountType(request.account),\r\n });\r\n\r\n try {\r\n this.logger.verbose(\"acquireTokenPopup called\", correlationId);\r\n preflightCheck(this.initialized, atPopupMeasurement);\r\n this.browserStorage.setInteractionInProgress(\r\n true,\r\n INTERACTION_TYPE.SIGNIN\r\n );\r\n } catch (e) {\r\n // Since this function is syncronous we need to reject\r\n return Promise.reject(e);\r\n }\r\n\r\n // If logged in, emit acquire token events\r\n const loggedInAccounts = this.getAllAccounts();\r\n if (loggedInAccounts.length > 0) {\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_START,\r\n InteractionType.Popup,\r\n request\r\n );\r\n } else {\r\n this.eventHandler.emitEvent(\r\n EventType.LOGIN_START,\r\n InteractionType.Popup,\r\n request\r\n );\r\n }\r\n\r\n let result: Promise;\r\n const pkce = this.getPreGeneratedPkceCodes(correlationId);\r\n\r\n if (this.canUsePlatformBroker(request)) {\r\n atPopupMeasurement.add({\r\n isPlatformBrokerRequest: true,\r\n });\r\n result = this.acquireTokenNative(\r\n {\r\n ...request,\r\n correlationId,\r\n },\r\n ApiId.acquireTokenPopup\r\n )\r\n .then((response) => {\r\n atPopupMeasurement.end({\r\n success: true,\r\n accountType: getAccountType(response.account),\r\n });\r\n return response;\r\n })\r\n .catch((e: AuthError) => {\r\n atPopupMeasurement.add({\r\n brokerErrorName: e.name,\r\n brokerErrorCode: e.errorCode,\r\n });\r\n if (\r\n e instanceof NativeAuthError &&\r\n isFatalNativeAuthError(e)\r\n ) {\r\n this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to continuing to attempt platform broker calls\r\n const popupClient =\r\n this.createPopupClient(correlationId);\r\n return popupClient.acquireToken(request, pkce);\r\n } else if (e instanceof InteractionRequiredAuthError) {\r\n this.logger.verbose(\r\n \"acquireTokenPopup - Resolving interaction required error thrown by native broker by falling back to web flow\"\r\n );\r\n const popupClient =\r\n this.createPopupClient(correlationId);\r\n return popupClient.acquireToken(request, pkce);\r\n }\r\n throw e;\r\n });\r\n } else {\r\n const popupClient = this.createPopupClient(correlationId);\r\n result = popupClient.acquireToken(request, pkce);\r\n }\r\n\r\n return result\r\n .then((result) => {\r\n /*\r\n * If logged in, emit acquire token events\r\n */\r\n const isLoggingIn =\r\n loggedInAccounts.length < this.getAllAccounts().length;\r\n if (isLoggingIn) {\r\n this.eventHandler.emitEvent(\r\n EventType.LOGIN_SUCCESS,\r\n InteractionType.Popup,\r\n result\r\n );\r\n } else {\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_SUCCESS,\r\n InteractionType.Popup,\r\n result\r\n );\r\n }\r\n\r\n atPopupMeasurement.end({\r\n success: true,\r\n accessTokenSize: result.accessToken.length,\r\n idTokenSize: result.idToken.length,\r\n accountType: getAccountType(result.account),\r\n });\r\n return result;\r\n })\r\n .catch((e: Error) => {\r\n if (loggedInAccounts.length > 0) {\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_FAILURE,\r\n InteractionType.Popup,\r\n null,\r\n e\r\n );\r\n } else {\r\n this.eventHandler.emitEvent(\r\n EventType.LOGIN_FAILURE,\r\n InteractionType.Popup,\r\n null,\r\n e\r\n );\r\n }\r\n\r\n atPopupMeasurement.end(\r\n {\r\n success: false,\r\n },\r\n e\r\n );\r\n\r\n // Since this function is syncronous we need to reject\r\n return Promise.reject(e);\r\n })\r\n .finally(async () => {\r\n this.browserStorage.setInteractionInProgress(false);\r\n if (this.config.system.asyncPopups) {\r\n await this.preGeneratePkceCodes(correlationId);\r\n }\r\n });\r\n }\r\n\r\n private trackPageVisibilityWithMeasurement(): void {\r\n const measurement =\r\n this.ssoSilentMeasurement ||\r\n this.acquireTokenByCodeAsyncMeasurement;\r\n if (!measurement) {\r\n return;\r\n }\r\n\r\n this.logger.info(\r\n \"Perf: Visibility change detected in \",\r\n measurement.event.name\r\n );\r\n measurement.increment({\r\n visibilityChangeCount: 1,\r\n });\r\n }\r\n // #endregion\r\n\r\n // #region Silent Flow\r\n\r\n /**\r\n * This function uses a hidden iframe to fetch an authorization code from the eSTS. There are cases where this may not work:\r\n * - Any browser using a form of Intelligent Tracking Prevention\r\n * - If there is not an established session with the service\r\n *\r\n * In these cases, the request must be done inside a popup or full frame redirect.\r\n *\r\n * For the cases where interaction is required, you cannot send a request with prompt=none.\r\n *\r\n * If your refresh token has expired, you can use this function to fetch a new set of tokens silently as long as\r\n * you session on the server still exists.\r\n * @param request {@link SsoSilentRequest}\r\n *\r\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\r\n */\r\n async ssoSilent(request: SsoSilentRequest): Promise {\r\n const correlationId = this.getRequestCorrelationId(request);\r\n const validRequest = {\r\n ...request,\r\n // will be PromptValue.NONE or PromptValue.NO_SESSION\r\n prompt: request.prompt,\r\n correlationId: correlationId,\r\n };\r\n this.ssoSilentMeasurement = this.performanceClient.startMeasurement(\r\n PerformanceEvents.SsoSilent,\r\n correlationId\r\n );\r\n this.ssoSilentMeasurement?.add({\r\n scenarioId: request.scenarioId,\r\n accountType: getAccountType(request.account),\r\n });\r\n preflightCheck(this.initialized, this.ssoSilentMeasurement);\r\n this.ssoSilentMeasurement?.increment({\r\n visibilityChangeCount: 0,\r\n });\r\n\r\n document.addEventListener(\r\n \"visibilitychange\",\r\n this.trackPageVisibilityWithMeasurement\r\n );\r\n this.logger.verbose(\"ssoSilent called\", correlationId);\r\n this.eventHandler.emitEvent(\r\n EventType.SSO_SILENT_START,\r\n InteractionType.Silent,\r\n validRequest\r\n );\r\n\r\n let result: Promise;\r\n\r\n if (this.canUsePlatformBroker(validRequest)) {\r\n this.ssoSilentMeasurement?.add({\r\n isPlatformBrokerRequest: true,\r\n });\r\n result = this.acquireTokenNative(\r\n validRequest,\r\n ApiId.ssoSilent\r\n ).catch((e: AuthError) => {\r\n this.ssoSilentMeasurement?.add({\r\n brokerErrorName: e.name,\r\n brokerErrorCode: e.errorCode,\r\n });\r\n // If native token acquisition fails for availability reasons fallback to standard flow\r\n if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {\r\n this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt\r\n const silentIframeClient = this.createSilentIframeClient(\r\n validRequest.correlationId\r\n );\r\n return silentIframeClient.acquireToken(validRequest);\r\n }\r\n throw e;\r\n });\r\n } else {\r\n const silentIframeClient = this.createSilentIframeClient(\r\n validRequest.correlationId\r\n );\r\n result = silentIframeClient.acquireToken(validRequest);\r\n }\r\n\r\n return result\r\n .then((response) => {\r\n this.eventHandler.emitEvent(\r\n EventType.SSO_SILENT_SUCCESS,\r\n InteractionType.Silent,\r\n response\r\n );\r\n this.ssoSilentMeasurement?.end({\r\n success: true,\r\n accessTokenSize: response.accessToken.length,\r\n idTokenSize: response.idToken.length,\r\n accountType: getAccountType(response.account),\r\n });\r\n return response;\r\n })\r\n .catch((e: Error) => {\r\n this.eventHandler.emitEvent(\r\n EventType.SSO_SILENT_FAILURE,\r\n InteractionType.Silent,\r\n null,\r\n e\r\n );\r\n this.ssoSilentMeasurement?.end(\r\n {\r\n success: false,\r\n },\r\n e\r\n );\r\n throw e;\r\n })\r\n .finally(() => {\r\n document.removeEventListener(\r\n \"visibilitychange\",\r\n this.trackPageVisibilityWithMeasurement\r\n );\r\n });\r\n }\r\n\r\n /**\r\n * This function redeems an authorization code (passed as code) from the eSTS token endpoint.\r\n * This authorization code should be acquired server-side using a confidential client to acquire a spa_code.\r\n * This API is not indended for normal authorization code acquisition and redemption.\r\n *\r\n * Redemption of this authorization code will not require PKCE, as it was acquired by a confidential client.\r\n *\r\n * @param request {@link AuthorizationCodeRequest}\r\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\r\n */\r\n async acquireTokenByCode(\r\n request: AuthorizationCodeRequest\r\n ): Promise {\r\n const correlationId = this.getRequestCorrelationId(request);\r\n this.logger.trace(\"acquireTokenByCode called\", correlationId);\r\n const atbcMeasurement = this.performanceClient.startMeasurement(\r\n PerformanceEvents.AcquireTokenByCode,\r\n correlationId\r\n );\r\n preflightCheck(this.initialized, atbcMeasurement);\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_BY_CODE_START,\r\n InteractionType.Silent,\r\n request\r\n );\r\n atbcMeasurement.add({ scenarioId: request.scenarioId });\r\n\r\n try {\r\n if (request.code && request.nativeAccountId) {\r\n // Throw error in case server returns both spa_code and spa_accountid in exchange for auth code.\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.spaCodeAndNativeAccountIdPresent\r\n );\r\n } else if (request.code) {\r\n const hybridAuthCode = request.code;\r\n let response = this.hybridAuthCodeResponses.get(hybridAuthCode);\r\n if (!response) {\r\n this.logger.verbose(\r\n \"Initiating new acquireTokenByCode request\",\r\n correlationId\r\n );\r\n response = this.acquireTokenByCodeAsync({\r\n ...request,\r\n correlationId,\r\n })\r\n .then((result: AuthenticationResult) => {\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_BY_CODE_SUCCESS,\r\n InteractionType.Silent,\r\n result\r\n );\r\n this.hybridAuthCodeResponses.delete(hybridAuthCode);\r\n atbcMeasurement.end({\r\n success: true,\r\n accessTokenSize: result.accessToken.length,\r\n idTokenSize: result.idToken.length,\r\n accountType: getAccountType(result.account),\r\n });\r\n return result;\r\n })\r\n .catch((error: Error) => {\r\n this.hybridAuthCodeResponses.delete(hybridAuthCode);\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_BY_CODE_FAILURE,\r\n InteractionType.Silent,\r\n null,\r\n error\r\n );\r\n atbcMeasurement.end(\r\n {\r\n success: false,\r\n },\r\n error\r\n );\r\n throw error;\r\n });\r\n this.hybridAuthCodeResponses.set(hybridAuthCode, response);\r\n } else {\r\n this.logger.verbose(\r\n \"Existing acquireTokenByCode request found\",\r\n correlationId\r\n );\r\n atbcMeasurement.discard();\r\n }\r\n return await response;\r\n } else if (request.nativeAccountId) {\r\n if (\r\n this.canUsePlatformBroker(request, request.nativeAccountId)\r\n ) {\r\n atbcMeasurement.add({\r\n isPlatformBrokerRequest: true,\r\n });\r\n const result = await this.acquireTokenNative(\r\n {\r\n ...request,\r\n correlationId,\r\n },\r\n ApiId.acquireTokenByCode,\r\n request.nativeAccountId\r\n ).catch((e: AuthError) => {\r\n // If native token acquisition fails for availability reasons fallback to standard flow\r\n if (\r\n e instanceof NativeAuthError &&\r\n isFatalNativeAuthError(e)\r\n ) {\r\n this.platformAuthProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt\r\n }\r\n atbcMeasurement.add({\r\n brokerErrorName: e.name,\r\n brokerErrorCode: e.errorCode,\r\n });\r\n throw e;\r\n });\r\n atbcMeasurement.end({\r\n accountType: getAccountType(result.account),\r\n success: true,\r\n });\r\n return result;\r\n } else {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.unableToAcquireTokenFromNativePlatform\r\n );\r\n }\r\n } else {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.authCodeOrNativeAccountIdRequired\r\n );\r\n }\r\n } catch (e) {\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_BY_CODE_FAILURE,\r\n InteractionType.Silent,\r\n null,\r\n e as EventError\r\n );\r\n atbcMeasurement.end(\r\n {\r\n success: false,\r\n },\r\n e\r\n );\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Creates a SilentAuthCodeClient to redeem an authorization code.\r\n * @param request\r\n * @returns Result of the operation to redeem the authorization code\r\n */\r\n private async acquireTokenByCodeAsync(\r\n request: AuthorizationCodeRequest\r\n ): Promise {\r\n this.logger.trace(\r\n \"acquireTokenByCodeAsync called\",\r\n request.correlationId\r\n );\r\n this.acquireTokenByCodeAsyncMeasurement =\r\n this.performanceClient.startMeasurement(\r\n PerformanceEvents.AcquireTokenByCodeAsync,\r\n request.correlationId\r\n );\r\n this.acquireTokenByCodeAsyncMeasurement?.increment({\r\n visibilityChangeCount: 0,\r\n });\r\n document.addEventListener(\r\n \"visibilitychange\",\r\n this.trackPageVisibilityWithMeasurement\r\n );\r\n const silentAuthCodeClient = this.createSilentAuthCodeClient(\r\n request.correlationId\r\n );\r\n const silentTokenResult = await silentAuthCodeClient\r\n .acquireToken(request)\r\n .then((response) => {\r\n this.acquireTokenByCodeAsyncMeasurement?.end({\r\n success: true,\r\n fromCache: response.fromCache,\r\n });\r\n return response;\r\n })\r\n .catch((tokenRenewalError: Error) => {\r\n this.acquireTokenByCodeAsyncMeasurement?.end(\r\n {\r\n success: false,\r\n },\r\n tokenRenewalError\r\n );\r\n throw tokenRenewalError;\r\n })\r\n .finally(() => {\r\n document.removeEventListener(\r\n \"visibilitychange\",\r\n this.trackPageVisibilityWithMeasurement\r\n );\r\n });\r\n return silentTokenResult;\r\n }\r\n\r\n /**\r\n * Attempt to acquire an access token from the cache\r\n * @param silentCacheClient SilentCacheClient\r\n * @param commonRequest CommonSilentFlowRequest\r\n * @param silentRequest SilentRequest\r\n * @returns A promise that, when resolved, returns the access token\r\n */\r\n protected async acquireTokenFromCache(\r\n commonRequest: CommonSilentFlowRequest,\r\n cacheLookupPolicy: CacheLookupPolicy\r\n ): Promise {\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.AcquireTokenFromCache,\r\n commonRequest.correlationId\r\n );\r\n switch (cacheLookupPolicy) {\r\n case CacheLookupPolicy.Default:\r\n case CacheLookupPolicy.AccessToken:\r\n case CacheLookupPolicy.AccessTokenAndRefreshToken:\r\n const silentCacheClient = this.createSilentCacheClient(\r\n commonRequest.correlationId\r\n );\r\n return invokeAsync(\r\n silentCacheClient.acquireToken.bind(silentCacheClient),\r\n PerformanceEvents.SilentCacheClientAcquireToken,\r\n this.logger,\r\n this.performanceClient,\r\n commonRequest.correlationId\r\n )(commonRequest);\r\n default:\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.tokenRefreshRequired\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Attempt to acquire an access token via a refresh token\r\n * @param commonRequest CommonSilentFlowRequest\r\n * @param cacheLookupPolicy CacheLookupPolicy\r\n * @returns A promise that, when resolved, returns the access token\r\n */\r\n public async acquireTokenByRefreshToken(\r\n commonRequest: CommonSilentFlowRequest,\r\n cacheLookupPolicy: CacheLookupPolicy\r\n ): Promise {\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.AcquireTokenByRefreshToken,\r\n commonRequest.correlationId\r\n );\r\n switch (cacheLookupPolicy) {\r\n case CacheLookupPolicy.Default:\r\n case CacheLookupPolicy.AccessTokenAndRefreshToken:\r\n case CacheLookupPolicy.RefreshToken:\r\n case CacheLookupPolicy.RefreshTokenAndNetwork:\r\n const silentRefreshClient = this.createSilentRefreshClient(\r\n commonRequest.correlationId\r\n );\r\n\r\n return invokeAsync(\r\n silentRefreshClient.acquireToken.bind(silentRefreshClient),\r\n PerformanceEvents.SilentRefreshClientAcquireToken,\r\n this.logger,\r\n this.performanceClient,\r\n commonRequest.correlationId\r\n )(commonRequest);\r\n default:\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.tokenRefreshRequired\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Attempt to acquire an access token via an iframe\r\n * @param request CommonSilentFlowRequest\r\n * @returns A promise that, when resolved, returns the access token\r\n */\r\n protected async acquireTokenBySilentIframe(\r\n request: CommonSilentFlowRequest\r\n ): Promise {\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.AcquireTokenBySilentIframe,\r\n request.correlationId\r\n );\r\n\r\n const silentIframeClient = this.createSilentIframeClient(\r\n request.correlationId\r\n );\r\n\r\n return invokeAsync(\r\n silentIframeClient.acquireToken.bind(silentIframeClient),\r\n PerformanceEvents.SilentIframeClientAcquireToken,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(request);\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Logout\r\n\r\n /**\r\n * Deprecated logout function. Use logoutRedirect or logoutPopup instead\r\n * @param logoutRequest\r\n * @deprecated\r\n */\r\n async logout(logoutRequest?: EndSessionRequest): Promise {\r\n const correlationId = this.getRequestCorrelationId(logoutRequest);\r\n this.logger.warning(\r\n \"logout API is deprecated and will be removed in msal-browser v3.0.0. Use logoutRedirect instead.\",\r\n correlationId\r\n );\r\n return this.logoutRedirect({\r\n correlationId,\r\n ...logoutRequest,\r\n });\r\n }\r\n\r\n /**\r\n * Use to log out the current user, and redirect the user to the postLogoutRedirectUri.\r\n * Default behaviour is to redirect the user to `window.location.href`.\r\n * @param logoutRequest\r\n */\r\n async logoutRedirect(logoutRequest?: EndSessionRequest): Promise {\r\n const correlationId = this.getRequestCorrelationId(logoutRequest);\r\n BrowserUtils.redirectPreflightCheck(this.initialized, this.config);\r\n this.browserStorage.setInteractionInProgress(\r\n true,\r\n INTERACTION_TYPE.SIGNOUT\r\n );\r\n\r\n const redirectClient = this.createRedirectClient(correlationId);\r\n return redirectClient.logout(logoutRequest);\r\n }\r\n\r\n /**\r\n * Clears local cache for the current user then opens a popup window prompting the user to sign-out of the server\r\n * @param logoutRequest\r\n */\r\n logoutPopup(logoutRequest?: EndSessionPopupRequest): Promise {\r\n try {\r\n const correlationId = this.getRequestCorrelationId(logoutRequest);\r\n BrowserUtils.preflightCheck(this.initialized);\r\n this.browserStorage.setInteractionInProgress(\r\n true,\r\n INTERACTION_TYPE.SIGNOUT\r\n );\r\n\r\n const popupClient = this.createPopupClient(correlationId);\r\n return popupClient.logout(logoutRequest).finally(() => {\r\n this.browserStorage.setInteractionInProgress(false);\r\n });\r\n } catch (e) {\r\n // Since this function is syncronous we need to reject\r\n return Promise.reject(e);\r\n }\r\n }\r\n\r\n /**\r\n * Creates a cache interaction client to clear broswer cache.\r\n * @param logoutRequest\r\n */\r\n async clearCache(logoutRequest?: ClearCacheRequest): Promise {\r\n if (!this.isBrowserEnvironment) {\r\n this.logger.info(\"in non-browser environment, returning early.\");\r\n return;\r\n }\r\n const correlationId = this.getRequestCorrelationId(logoutRequest);\r\n const cacheClient = this.createSilentCacheClient(correlationId);\r\n return cacheClient.logout(logoutRequest);\r\n }\r\n\r\n // #endregion\r\n\r\n // #region Account APIs\r\n\r\n /**\r\n * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.\r\n * @param accountFilter - (Optional) filter to narrow down the accounts returned\r\n * @returns Array of AccountInfo objects in cache\r\n */\r\n getAllAccounts(accountFilter?: AccountFilter): AccountInfo[] {\r\n const correlationId = this.getRequestCorrelationId();\r\n return AccountManager.getAllAccounts(\r\n this.logger,\r\n this.browserStorage,\r\n this.isBrowserEnvironment,\r\n correlationId,\r\n accountFilter\r\n );\r\n }\r\n\r\n /**\r\n * Returns the first account found in the cache that matches the account filter passed in.\r\n * @param accountFilter\r\n * @returns The first account found in the cache matching the provided filter or null if no account could be found.\r\n */\r\n getAccount(accountFilter: AccountFilter): AccountInfo | null {\r\n const correlationId = this.getRequestCorrelationId();\r\n return AccountManager.getAccount(\r\n accountFilter,\r\n this.logger,\r\n this.browserStorage,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching username.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found.\r\n * This API is provided for convenience but getAccountById should be used for best reliability\r\n * @param username\r\n * @returns The account object stored in MSAL\r\n */\r\n getAccountByUsername(username: string): AccountInfo | null {\r\n const correlationId = this.getRequestCorrelationId();\r\n return AccountManager.getAccountByUsername(\r\n username,\r\n this.logger,\r\n this.browserStorage,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching homeAccountId.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found\r\n * @param homeAccountId\r\n * @returns The account object stored in MSAL\r\n */\r\n getAccountByHomeId(homeAccountId: string): AccountInfo | null {\r\n const correlationId = this.getRequestCorrelationId();\r\n return AccountManager.getAccountByHomeId(\r\n homeAccountId,\r\n this.logger,\r\n this.browserStorage,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching localAccountId.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found\r\n * @param localAccountId\r\n * @returns The account object stored in MSAL\r\n */\r\n getAccountByLocalId(localAccountId: string): AccountInfo | null {\r\n const correlationId = this.getRequestCorrelationId();\r\n return AccountManager.getAccountByLocalId(\r\n localAccountId,\r\n this.logger,\r\n this.browserStorage,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Sets the account to use as the active account. If no account is passed to the acquireToken APIs, then MSAL will use this active account.\r\n * @param account\r\n */\r\n setActiveAccount(account: AccountInfo | null): void {\r\n const correlationId = this.getRequestCorrelationId();\r\n AccountManager.setActiveAccount(\r\n account,\r\n this.browserStorage,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Gets the currently active account\r\n */\r\n getActiveAccount(): AccountInfo | null {\r\n const correlationId = this.getRequestCorrelationId();\r\n return AccountManager.getActiveAccount(\r\n this.browserStorage,\r\n correlationId\r\n );\r\n }\r\n\r\n // #endregion\r\n\r\n /**\r\n * Hydrates the cache with the tokens from an AuthenticationResult\r\n * @param result\r\n * @param request\r\n * @returns\r\n */\r\n async hydrateCache(\r\n result: AuthenticationResult,\r\n request:\r\n | SilentRequest\r\n | SsoSilentRequest\r\n | RedirectRequest\r\n | PopupRequest\r\n ): Promise {\r\n this.logger.verbose(\"hydrateCache called\");\r\n\r\n // Account gets saved to browser storage regardless of native or not\r\n const accountEntity = AccountEntity.createFromAccountInfo(\r\n result.account,\r\n result.cloudGraphHostName,\r\n result.msGraphHost\r\n );\r\n await this.browserStorage.setAccount(\r\n accountEntity,\r\n result.correlationId\r\n );\r\n\r\n if (result.fromNativeBroker) {\r\n this.logger.verbose(\r\n \"Response was from native broker, storing in-memory\"\r\n );\r\n // Tokens from native broker are stored in-memory\r\n return this.nativeInternalStorage.hydrateCache(result, request);\r\n } else {\r\n return this.browserStorage.hydrateCache(result, request);\r\n }\r\n }\r\n\r\n // #region Helpers\r\n\r\n /**\r\n * Acquire a token from native device (e.g. WAM)\r\n * @param request\r\n */\r\n public async acquireTokenNative(\r\n request: PopupRequest | SilentRequest | SsoSilentRequest,\r\n apiId: ApiId,\r\n accountId?: string,\r\n cacheLookupPolicy?: CacheLookupPolicy\r\n ): Promise {\r\n this.logger.trace(\"acquireTokenNative called\");\r\n if (!this.platformAuthProvider) {\r\n throw createBrowserAuthError(\r\n BrowserAuthErrorCodes.nativeConnectionNotEstablished\r\n );\r\n }\r\n const nativeClient = new PlatformAuthInteractionClient(\r\n this.config,\r\n this.browserStorage,\r\n this.browserCrypto,\r\n this.logger,\r\n this.eventHandler,\r\n this.navigationClient,\r\n apiId,\r\n this.performanceClient,\r\n this.platformAuthProvider,\r\n accountId || this.getNativeAccountId(request),\r\n this.nativeInternalStorage,\r\n request.correlationId\r\n );\r\n\r\n return nativeClient.acquireToken(request, cacheLookupPolicy);\r\n }\r\n\r\n /**\r\n * Returns boolean indicating if this request can use the platform broker\r\n * @param request\r\n */\r\n public canUsePlatformBroker(\r\n request: RedirectRequest | PopupRequest | SsoSilentRequest,\r\n accountId?: string\r\n ): boolean {\r\n this.logger.trace(\"canUsePlatformBroker called\");\r\n if (!this.platformAuthProvider) {\r\n this.logger.trace(\r\n \"canUsePlatformBroker: platform broker unavilable, returning false\"\r\n );\r\n return false;\r\n }\r\n\r\n if (\r\n !isPlatformAuthAllowed(\r\n this.config,\r\n this.logger,\r\n this.platformAuthProvider,\r\n request.authenticationScheme\r\n )\r\n ) {\r\n this.logger.trace(\r\n \"canUsePlatformBroker: isBrokerAvailable returned false, returning false\"\r\n );\r\n return false;\r\n }\r\n\r\n if (request.prompt) {\r\n switch (request.prompt) {\r\n case PromptValue.NONE:\r\n case PromptValue.CONSENT:\r\n case PromptValue.LOGIN:\r\n this.logger.trace(\r\n \"canUsePlatformBroker: prompt is compatible with platform broker flow\"\r\n );\r\n break;\r\n default:\r\n this.logger.trace(\r\n `canUsePlatformBroker: prompt = ${request.prompt} is not compatible with platform broker flow, returning false`\r\n );\r\n return false;\r\n }\r\n }\r\n\r\n if (!accountId && !this.getNativeAccountId(request)) {\r\n this.logger.trace(\r\n \"canUsePlatformBroker: nativeAccountId is not available, returning false\"\r\n );\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the native accountId from the account\r\n * @param request\r\n * @returns\r\n */\r\n public getNativeAccountId(\r\n request: RedirectRequest | PopupRequest | SsoSilentRequest\r\n ): string {\r\n const account =\r\n request.account ||\r\n this.getAccount({\r\n loginHint: request.loginHint,\r\n sid: request.sid,\r\n }) ||\r\n this.getActiveAccount();\r\n\r\n return (account && account.nativeAccountId) || \"\";\r\n }\r\n\r\n /**\r\n * Returns new instance of the Popup Interaction Client\r\n * @param correlationId\r\n */\r\n public createPopupClient(correlationId?: string): PopupClient {\r\n return new PopupClient(\r\n this.config,\r\n this.browserStorage,\r\n this.browserCrypto,\r\n this.logger,\r\n this.eventHandler,\r\n this.navigationClient,\r\n this.performanceClient,\r\n this.nativeInternalStorage,\r\n this.platformAuthProvider,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Returns new instance of the Redirect Interaction Client\r\n * @param correlationId\r\n */\r\n protected createRedirectClient(correlationId?: string): RedirectClient {\r\n return new RedirectClient(\r\n this.config,\r\n this.browserStorage,\r\n this.browserCrypto,\r\n this.logger,\r\n this.eventHandler,\r\n this.navigationClient,\r\n this.performanceClient,\r\n this.nativeInternalStorage,\r\n this.platformAuthProvider,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Returns new instance of the Silent Iframe Interaction Client\r\n * @param correlationId\r\n */\r\n public createSilentIframeClient(\r\n correlationId?: string\r\n ): SilentIframeClient {\r\n return new SilentIframeClient(\r\n this.config,\r\n this.browserStorage,\r\n this.browserCrypto,\r\n this.logger,\r\n this.eventHandler,\r\n this.navigationClient,\r\n ApiId.ssoSilent,\r\n this.performanceClient,\r\n this.nativeInternalStorage,\r\n this.platformAuthProvider,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Returns new instance of the Silent Cache Interaction Client\r\n */\r\n protected createSilentCacheClient(\r\n correlationId?: string\r\n ): SilentCacheClient {\r\n return new SilentCacheClient(\r\n this.config,\r\n this.browserStorage,\r\n this.browserCrypto,\r\n this.logger,\r\n this.eventHandler,\r\n this.navigationClient,\r\n this.performanceClient,\r\n this.platformAuthProvider,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Returns new instance of the Silent Refresh Interaction Client\r\n */\r\n protected createSilentRefreshClient(\r\n correlationId?: string\r\n ): SilentRefreshClient {\r\n return new SilentRefreshClient(\r\n this.config,\r\n this.browserStorage,\r\n this.browserCrypto,\r\n this.logger,\r\n this.eventHandler,\r\n this.navigationClient,\r\n this.performanceClient,\r\n this.platformAuthProvider,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Returns new instance of the Silent AuthCode Interaction Client\r\n */\r\n protected createSilentAuthCodeClient(\r\n correlationId?: string\r\n ): SilentAuthCodeClient {\r\n return new SilentAuthCodeClient(\r\n this.config,\r\n this.browserStorage,\r\n this.browserCrypto,\r\n this.logger,\r\n this.eventHandler,\r\n this.navigationClient,\r\n ApiId.acquireTokenByCode,\r\n this.performanceClient,\r\n this.platformAuthProvider,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Adds event callbacks to array\r\n * @param callback\r\n */\r\n addEventCallback(\r\n callback: EventCallbackFunction,\r\n eventTypes?: Array\r\n ): string | null {\r\n return this.eventHandler.addEventCallback(callback, eventTypes);\r\n }\r\n\r\n /**\r\n * Removes callback with provided id from callback array\r\n * @param callbackId\r\n */\r\n removeEventCallback(callbackId: string): void {\r\n this.eventHandler.removeEventCallback(callbackId);\r\n }\r\n\r\n /**\r\n * Registers a callback to receive performance events.\r\n *\r\n * @param {PerformanceCallbackFunction} callback\r\n * @returns {string}\r\n */\r\n addPerformanceCallback(callback: PerformanceCallbackFunction): string {\r\n BrowserUtils.blockNonBrowserEnvironment();\r\n return this.performanceClient.addPerformanceCallback(callback);\r\n }\r\n\r\n /**\r\n * Removes a callback registered with addPerformanceCallback.\r\n *\r\n * @param {string} callbackId\r\n * @returns {boolean}\r\n */\r\n removePerformanceCallback(callbackId: string): boolean {\r\n return this.performanceClient.removePerformanceCallback(callbackId);\r\n }\r\n\r\n /**\r\n * Adds event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\r\n * @deprecated These events will be raised by default and this method will be removed in a future major version.\r\n */\r\n enableAccountStorageEvents(): void {\r\n if (\r\n this.config.cache.cacheLocation !==\r\n BrowserCacheLocation.LocalStorage\r\n ) {\r\n this.logger.info(\r\n \"Account storage events are only available when cacheLocation is set to localStorage\"\r\n );\r\n return;\r\n }\r\n\r\n this.eventHandler.subscribeCrossTab();\r\n }\r\n\r\n /**\r\n * Removes event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\r\n * @deprecated These events will be raised by default and this method will be removed in a future major version.\r\n */\r\n disableAccountStorageEvents(): void {\r\n if (\r\n this.config.cache.cacheLocation !==\r\n BrowserCacheLocation.LocalStorage\r\n ) {\r\n this.logger.info(\r\n \"Account storage events are only available when cacheLocation is set to localStorage\"\r\n );\r\n return;\r\n }\r\n\r\n this.eventHandler.unsubscribeCrossTab();\r\n }\r\n\r\n /**\r\n * Gets the token cache for the application.\r\n */\r\n getTokenCache(): ITokenCache {\r\n return this.tokenCache;\r\n }\r\n\r\n /**\r\n * Returns the logger instance\r\n */\r\n public getLogger(): Logger {\r\n return this.logger;\r\n }\r\n\r\n /**\r\n * Replaces the default logger set in configurations with new Logger with new configurations\r\n * @param logger Logger instance\r\n */\r\n setLogger(logger: Logger): void {\r\n this.logger = logger;\r\n }\r\n\r\n /**\r\n * Called by wrapper libraries (Angular & React) to set SKU and Version passed down to telemetry, logger, etc.\r\n * @param sku\r\n * @param version\r\n */\r\n initializeWrapperLibrary(sku: WrapperSKU, version: string): void {\r\n // Validate the SKU passed in is one we expect\r\n this.browserStorage.setWrapperMetadata(sku, version);\r\n }\r\n\r\n /**\r\n * Sets navigation client\r\n * @param navigationClient\r\n */\r\n setNavigationClient(navigationClient: INavigationClient): void {\r\n this.navigationClient = navigationClient;\r\n }\r\n\r\n /**\r\n * Returns the configuration object\r\n */\r\n public getConfiguration(): BrowserConfiguration {\r\n return this.config;\r\n }\r\n\r\n /**\r\n * Returns the performance client\r\n */\r\n public getPerformanceClient(): IPerformanceClient {\r\n return this.performanceClient;\r\n }\r\n\r\n /**\r\n * Returns the browser env indicator\r\n */\r\n public isBrowserEnv(): boolean {\r\n return this.isBrowserEnvironment;\r\n }\r\n\r\n /**\r\n * Generates a correlation id for a request if none is provided.\r\n *\r\n * @protected\r\n * @param {?Partial} [request]\r\n * @returns {string}\r\n */\r\n protected getRequestCorrelationId(\r\n request?: Partial\r\n ): string {\r\n if (request?.correlationId) {\r\n return request.correlationId;\r\n }\r\n\r\n if (this.isBrowserEnvironment) {\r\n return createNewGuid();\r\n }\r\n\r\n /*\r\n * Included for fallback for non-browser environments,\r\n * and to ensure this method always returns a string.\r\n */\r\n return Constants.EMPTY_STRING;\r\n }\r\n\r\n // #endregion\r\n\r\n /**\r\n * Use when initiating the login process by redirecting the user's browser to the authorization endpoint. This function redirects the page, so\r\n * any code that follows this function will not execute.\r\n *\r\n * IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current\r\n * browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.\r\n *\r\n * @param request\r\n */\r\n async loginRedirect(request?: RedirectRequest): Promise {\r\n const correlationId: string = this.getRequestCorrelationId(request);\r\n this.logger.verbose(\"loginRedirect called\", correlationId);\r\n return this.acquireTokenRedirect({\r\n correlationId,\r\n ...(request || DEFAULT_REQUEST),\r\n });\r\n }\r\n\r\n /**\r\n * Use when initiating the login process via opening a popup window in the user's browser\r\n *\r\n * @param request\r\n *\r\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\r\n */\r\n loginPopup(request?: PopupRequest): Promise {\r\n const correlationId: string = this.getRequestCorrelationId(request);\r\n this.logger.verbose(\"loginPopup called\", correlationId);\r\n return this.acquireTokenPopup({\r\n correlationId,\r\n ...(request || DEFAULT_REQUEST),\r\n });\r\n }\r\n\r\n /**\r\n * Silently acquire an access token for a given set of scopes. Returns currently processing promise if parallel requests are made.\r\n *\r\n * @param {@link (SilentRequest:type)}\r\n * @returns {Promise.} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse} object\r\n */\r\n async acquireTokenSilent(\r\n request: SilentRequest\r\n ): Promise {\r\n const correlationId = this.getRequestCorrelationId(request);\r\n const atsMeasurement = this.performanceClient.startMeasurement(\r\n PerformanceEvents.AcquireTokenSilent,\r\n correlationId\r\n );\r\n atsMeasurement.add({\r\n cacheLookupPolicy: request.cacheLookupPolicy,\r\n scenarioId: request.scenarioId,\r\n });\r\n\r\n preflightCheck(this.initialized, atsMeasurement);\r\n this.logger.verbose(\"acquireTokenSilent called\", correlationId);\r\n\r\n const account = request.account || this.getActiveAccount();\r\n if (!account) {\r\n throw createBrowserAuthError(BrowserAuthErrorCodes.noAccountError);\r\n }\r\n atsMeasurement.add({ accountType: getAccountType(account) });\r\n\r\n return this.acquireTokenSilentDeduped(request, account, correlationId)\r\n .then((result) => {\r\n atsMeasurement.end({\r\n success: true,\r\n fromCache: result.fromCache,\r\n accessTokenSize: result.accessToken.length,\r\n idTokenSize: result.idToken.length,\r\n });\r\n return {\r\n ...result,\r\n state: request.state,\r\n correlationId: correlationId, // Ensures PWB scenarios can correctly match request to response\r\n };\r\n })\r\n .catch((error: Error) => {\r\n if (error instanceof AuthError) {\r\n // Ensures PWB scenarios can correctly match request to response\r\n error.setCorrelationId(correlationId);\r\n }\r\n\r\n atsMeasurement.end(\r\n {\r\n success: false,\r\n },\r\n error\r\n );\r\n throw error;\r\n });\r\n }\r\n\r\n /**\r\n * Checks if identical request is already in flight and returns reference to the existing promise or fires off a new one if this is the first\r\n * @param request\r\n * @param account\r\n * @param correlationId\r\n * @returns\r\n */\r\n private async acquireTokenSilentDeduped(\r\n request: SilentRequest,\r\n account: AccountInfo,\r\n correlationId: string\r\n ): Promise {\r\n const thumbprint = getRequestThumbprint(\r\n this.config.auth.clientId,\r\n {\r\n ...request,\r\n authority: request.authority || this.config.auth.authority,\r\n correlationId: correlationId,\r\n },\r\n account.homeAccountId\r\n );\r\n const silentRequestKey = JSON.stringify(thumbprint);\r\n\r\n const inProgressRequest =\r\n this.activeSilentTokenRequests.get(silentRequestKey);\r\n\r\n if (typeof inProgressRequest === \"undefined\") {\r\n this.logger.verbose(\r\n \"acquireTokenSilent called for the first time, storing active request\",\r\n correlationId\r\n );\r\n this.performanceClient.addFields({ deduped: false }, correlationId);\r\n\r\n const activeRequest = invokeAsync(\r\n this.acquireTokenSilentAsync.bind(this),\r\n PerformanceEvents.AcquireTokenSilentAsync,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(\r\n {\r\n ...request,\r\n correlationId,\r\n },\r\n account\r\n );\r\n this.activeSilentTokenRequests.set(silentRequestKey, activeRequest);\r\n\r\n return activeRequest.finally(() => {\r\n this.activeSilentTokenRequests.delete(silentRequestKey);\r\n });\r\n } else {\r\n this.logger.verbose(\r\n \"acquireTokenSilent has been called previously, returning the result from the first call\",\r\n correlationId\r\n );\r\n this.performanceClient.addFields({ deduped: true }, correlationId);\r\n return inProgressRequest;\r\n }\r\n }\r\n\r\n /**\r\n * Silently acquire an access token for a given set of scopes. Will use cached token if available, otherwise will attempt to acquire a new token from the network via refresh token.\r\n * @param {@link (SilentRequest:type)}\r\n * @param {@link (AccountInfo:type)}\r\n * @returns {Promise.} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthResponse}\r\n */\r\n protected async acquireTokenSilentAsync(\r\n request: SilentRequest & { correlationId: string },\r\n account: AccountInfo\r\n ): Promise {\r\n const trackPageVisibility = () =>\r\n this.trackPageVisibility(request.correlationId);\r\n this.performanceClient.addQueueMeasurement(\r\n PerformanceEvents.AcquireTokenSilentAsync,\r\n request.correlationId\r\n );\r\n\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_START,\r\n InteractionType.Silent,\r\n request\r\n );\r\n\r\n if (request.correlationId) {\r\n this.performanceClient.incrementFields(\r\n { visibilityChangeCount: 0 },\r\n request.correlationId\r\n );\r\n }\r\n\r\n document.addEventListener(\"visibilitychange\", trackPageVisibility);\r\n\r\n const silentRequest = await invokeAsync(\r\n initializeSilentRequest,\r\n PerformanceEvents.InitializeSilentRequest,\r\n this.logger,\r\n this.performanceClient,\r\n request.correlationId\r\n )(request, account, this.config, this.performanceClient, this.logger);\r\n const cacheLookupPolicy =\r\n request.cacheLookupPolicy || CacheLookupPolicy.Default;\r\n\r\n const result = this.acquireTokenSilentNoIframe(\r\n silentRequest,\r\n cacheLookupPolicy\r\n ).catch(async (refreshTokenError: AuthError) => {\r\n const shouldTryToResolveSilently =\r\n checkIfRefreshTokenErrorCanBeResolvedSilently(\r\n refreshTokenError,\r\n cacheLookupPolicy\r\n );\r\n\r\n if (shouldTryToResolveSilently) {\r\n if (!this.activeIframeRequest) {\r\n let _resolve: (result: boolean) => void;\r\n // Always set the active request tracker immediately after checking it to prevent races\r\n this.activeIframeRequest = [\r\n new Promise((resolve) => {\r\n _resolve = resolve;\r\n }),\r\n silentRequest.correlationId,\r\n ];\r\n this.logger.verbose(\r\n \"Refresh token expired/invalid or CacheLookupPolicy is set to Skip, attempting acquire token by iframe.\",\r\n silentRequest.correlationId\r\n );\r\n return invokeAsync(\r\n this.acquireTokenBySilentIframe.bind(this),\r\n PerformanceEvents.AcquireTokenBySilentIframe,\r\n this.logger,\r\n this.performanceClient,\r\n silentRequest.correlationId\r\n )(silentRequest)\r\n .then((iframeResult) => {\r\n _resolve(true);\r\n return iframeResult;\r\n })\r\n .catch((e) => {\r\n _resolve(false);\r\n throw e;\r\n })\r\n .finally(() => {\r\n this.activeIframeRequest = undefined;\r\n });\r\n } else if (cacheLookupPolicy !== CacheLookupPolicy.Skip) {\r\n const [activePromise, activeCorrelationId] =\r\n this.activeIframeRequest;\r\n this.logger.verbose(\r\n `Iframe request is already in progress, awaiting resolution for request with correlationId: ${activeCorrelationId}`,\r\n silentRequest.correlationId\r\n );\r\n const awaitConcurrentIframeMeasure =\r\n this.performanceClient.startMeasurement(\r\n PerformanceEvents.AwaitConcurrentIframe,\r\n silentRequest.correlationId\r\n );\r\n awaitConcurrentIframeMeasure.add({\r\n awaitIframeCorrelationId: activeCorrelationId,\r\n });\r\n\r\n const activePromiseResult = await activePromise;\r\n awaitConcurrentIframeMeasure.end({\r\n success: activePromiseResult,\r\n });\r\n if (activePromiseResult) {\r\n this.logger.verbose(\r\n `Parallel iframe request with correlationId: ${activeCorrelationId} succeeded. Retrying cache and/or RT redemption`,\r\n silentRequest.correlationId\r\n );\r\n // Retry cache lookup and/or RT exchange after iframe completes\r\n return this.acquireTokenSilentNoIframe(\r\n silentRequest,\r\n cacheLookupPolicy\r\n );\r\n } else {\r\n this.logger.info(\r\n `Iframe request with correlationId: ${activeCorrelationId} failed. Interaction is required.`\r\n );\r\n // If previous iframe request failed, it's unlikely to succeed this time. Throw original error.\r\n throw refreshTokenError;\r\n }\r\n } else {\r\n // Cache policy set to skip and another iframe request is already in progress\r\n this.logger.warning(\r\n \"Another iframe request is currently in progress and CacheLookupPolicy is set to Skip. This may result in degraded performance and/or reliability for both calls. Please consider changing the CacheLookupPolicy to take advantage of request queuing and token cache.\",\r\n silentRequest.correlationId\r\n );\r\n return invokeAsync(\r\n this.acquireTokenBySilentIframe.bind(this),\r\n PerformanceEvents.AcquireTokenBySilentIframe,\r\n this.logger,\r\n this.performanceClient,\r\n silentRequest.correlationId\r\n )(silentRequest);\r\n }\r\n } else {\r\n // Error cannot be silently resolved or iframe renewal is not allowed, interaction required\r\n throw refreshTokenError;\r\n }\r\n });\r\n\r\n return result\r\n .then((response) => {\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_SUCCESS,\r\n InteractionType.Silent,\r\n response\r\n );\r\n if (request.correlationId) {\r\n this.performanceClient.addFields(\r\n {\r\n fromCache: response.fromCache,\r\n },\r\n request.correlationId\r\n );\r\n }\r\n\r\n return response;\r\n })\r\n .catch((tokenRenewalError: Error) => {\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_FAILURE,\r\n InteractionType.Silent,\r\n null,\r\n tokenRenewalError\r\n );\r\n throw tokenRenewalError;\r\n })\r\n .finally(() => {\r\n document.removeEventListener(\r\n \"visibilitychange\",\r\n trackPageVisibility\r\n );\r\n });\r\n }\r\n\r\n /**\r\n * AcquireTokenSilent without the iframe fallback. This is used to enable the correct fallbacks in cases where there's a potential for multiple silent requests to be made in parallel and prevent those requests from making concurrent iframe requests.\r\n * @param silentRequest\r\n * @param cacheLookupPolicy\r\n * @returns\r\n */\r\n private async acquireTokenSilentNoIframe(\r\n silentRequest: CommonSilentFlowRequest,\r\n cacheLookupPolicy: CacheLookupPolicy\r\n ): Promise {\r\n // if the cache policy is set to access_token only, we should not be hitting the native layer yet\r\n if (\r\n isPlatformAuthAllowed(\r\n this.config,\r\n this.logger,\r\n this.platformAuthProvider,\r\n silentRequest.authenticationScheme\r\n ) &&\r\n silentRequest.account.nativeAccountId\r\n ) {\r\n this.logger.verbose(\r\n \"acquireTokenSilent - attempting to acquire token from native platform\"\r\n );\r\n this.performanceClient.addFields(\r\n { isPlatformBrokerRequest: true },\r\n silentRequest.correlationId\r\n );\r\n return this.acquireTokenNative(\r\n silentRequest,\r\n ApiId.acquireTokenSilent_silentFlow,\r\n silentRequest.account.nativeAccountId,\r\n cacheLookupPolicy\r\n ).catch(async (e: AuthError) => {\r\n this.performanceClient.addFields(\r\n {\r\n brokerErrorName: e.name,\r\n brokerErrorCode: e.errorCode,\r\n },\r\n silentRequest.correlationId\r\n );\r\n // If native token acquisition fails for availability reasons fallback to web flow\r\n if (e instanceof NativeAuthError && isFatalNativeAuthError(e)) {\r\n this.logger.verbose(\r\n \"acquireTokenSilent - native platform unavailable, falling back to web flow\"\r\n );\r\n this.platformAuthProvider = undefined; // Prevent future requests from continuing to attempt\r\n // Cache will not contain tokens, given that previous WAM requests succeeded. Skip cache and RT renewal and go straight to iframe renewal\r\n throw createClientAuthError(\r\n ClientAuthErrorCodes.tokenRefreshRequired\r\n );\r\n }\r\n throw e;\r\n });\r\n } else {\r\n this.logger.verbose(\r\n \"acquireTokenSilent - attempting to acquire token from web flow\"\r\n );\r\n // add logs to identify embedded cache retrieval\r\n if (cacheLookupPolicy === CacheLookupPolicy.AccessToken) {\r\n this.logger.verbose(\r\n \"acquireTokenSilent - cache lookup policy set to AccessToken, attempting to acquire token from local cache\"\r\n );\r\n }\r\n return invokeAsync(\r\n this.acquireTokenFromCache.bind(this),\r\n PerformanceEvents.AcquireTokenFromCache,\r\n this.logger,\r\n this.performanceClient,\r\n silentRequest.correlationId\r\n )(silentRequest, cacheLookupPolicy).catch(\r\n (cacheError: AuthError) => {\r\n if (cacheLookupPolicy === CacheLookupPolicy.AccessToken) {\r\n throw cacheError;\r\n }\r\n\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_NETWORK_START,\r\n InteractionType.Silent,\r\n silentRequest\r\n );\r\n\r\n return invokeAsync(\r\n this.acquireTokenByRefreshToken.bind(this),\r\n PerformanceEvents.AcquireTokenByRefreshToken,\r\n this.logger,\r\n this.performanceClient,\r\n silentRequest.correlationId\r\n )(silentRequest, cacheLookupPolicy);\r\n }\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Pre-generates PKCE codes and stores it in local variable\r\n * @param correlationId\r\n */\r\n private async preGeneratePkceCodes(correlationId: string): Promise {\r\n this.logger.verbose(\"Generating new PKCE codes\");\r\n this.pkceCode = await invokeAsync(\r\n generatePkceCodes,\r\n PerformanceEvents.GeneratePkceCodes,\r\n this.logger,\r\n this.performanceClient,\r\n correlationId\r\n )(this.performanceClient, this.logger, correlationId);\r\n return Promise.resolve();\r\n }\r\n\r\n /**\r\n * Provides pre-generated PKCE codes, if any\r\n * @param correlationId\r\n */\r\n private getPreGeneratedPkceCodes(\r\n correlationId: string\r\n ): PkceCodes | undefined {\r\n this.logger.verbose(\"Attempting to pick up pre-generated PKCE codes\");\r\n const res = this.pkceCode ? { ...this.pkceCode } : undefined;\r\n this.pkceCode = undefined;\r\n this.logger.verbose(\r\n `${res ? \"Found\" : \"Did not find\"} pre-generated PKCE codes`\r\n );\r\n this.performanceClient.addFields(\r\n { usePreGeneratedPkce: !!res },\r\n correlationId\r\n );\r\n return res;\r\n }\r\n\r\n private logMultipleInstances(\r\n performanceEvent: InProgressPerformanceEvent\r\n ): void {\r\n const clientId = this.config.auth.clientId;\r\n\r\n if (!window) return;\r\n // @ts-ignore\r\n window.msal = window.msal || {};\r\n // @ts-ignore\r\n window.msal.clientIds = window.msal.clientIds || [];\r\n\r\n // @ts-ignore\r\n const clientIds: string[] = window.msal.clientIds;\r\n\r\n if (clientIds.length > 0) {\r\n this.logger.verbose(\r\n \"There is already an instance of MSAL.js in the window.\"\r\n );\r\n }\r\n // @ts-ignore\r\n window.msal.clientIds.push(clientId);\r\n collectInstanceStats(clientId, performanceEvent, this.logger);\r\n }\r\n}\r\n\r\n/**\r\n * Determines whether an error thrown by the refresh token endpoint can be resolved without interaction\r\n * @param refreshTokenError\r\n * @param silentRequest\r\n * @param cacheLookupPolicy\r\n * @returns\r\n */\r\nfunction checkIfRefreshTokenErrorCanBeResolvedSilently(\r\n refreshTokenError: AuthError,\r\n cacheLookupPolicy: CacheLookupPolicy\r\n): boolean {\r\n const noInteractionRequired = !(\r\n refreshTokenError instanceof InteractionRequiredAuthError &&\r\n // For refresh token errors, bad_token does not always require interaction (silently resolvable)\r\n refreshTokenError.subError !==\r\n InteractionRequiredAuthErrorCodes.badToken\r\n );\r\n\r\n // Errors that result when the refresh token needs to be replaced\r\n const refreshTokenRefreshRequired =\r\n refreshTokenError.errorCode === BrowserConstants.INVALID_GRANT_ERROR ||\r\n refreshTokenError.errorCode ===\r\n ClientAuthErrorCodes.tokenRefreshRequired;\r\n\r\n // Errors that may be resolved before falling back to interaction (through iframe renewal)\r\n const isSilentlyResolvable =\r\n (noInteractionRequired && refreshTokenRefreshRequired) ||\r\n refreshTokenError.errorCode ===\r\n InteractionRequiredAuthErrorCodes.noTokensFound ||\r\n refreshTokenError.errorCode ===\r\n InteractionRequiredAuthErrorCodes.refreshTokenExpired;\r\n\r\n // Only these policies allow for an iframe renewal attempt\r\n const tryIframeRenewal = iFrameRenewalPolicies.includes(cacheLookupPolicy);\r\n\r\n return isSilentlyResolvable && tryIframeRenewal;\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { BridgeStatusCode } from \"./BridgeStatusCode.js\";\r\n\r\nexport type BridgeError = {\r\n status: BridgeStatusCode;\r\n code?: string; // auth_flow_last_error such as invalid_grant\r\n subError?: string; // server_suberror_code such as consent_required\r\n description?: string;\r\n properties?: object; // additional telemetry info\r\n};\r\n\r\nexport function isBridgeError(error: unknown): error is BridgeError {\r\n return (error as BridgeError).status !== undefined;\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { TokenRequest } from \"../TokenRequest.js\";\r\nimport { AccountInfo as NaaAccountInfo } from \"../AccountInfo.js\";\r\nimport { RedirectRequest } from \"../../request/RedirectRequest.js\";\r\nimport { PopupRequest } from \"../../request/PopupRequest.js\";\r\nimport {\r\n AccountInfo as MsalAccountInfo,\r\n AuthError,\r\n ClientAuthError,\r\n ClientConfigurationError,\r\n InteractionRequiredAuthError,\r\n ServerError,\r\n ICrypto,\r\n Logger,\r\n AuthToken,\r\n TokenClaims,\r\n ClientAuthErrorCodes,\r\n AuthenticationScheme,\r\n RequestParameterBuilder,\r\n StringUtils,\r\n createClientAuthError,\r\n OIDC_DEFAULT_SCOPES,\r\n AccountInfo,\r\n IdTokenEntity,\r\n AccessTokenEntity,\r\n TenantProfile,\r\n buildTenantProfile,\r\n TimeUtils,\r\n} from \"@azure/msal-common/browser\";\r\nimport { isBridgeError } from \"../BridgeError.js\";\r\nimport { BridgeStatusCode } from \"../BridgeStatusCode.js\";\r\nimport { AuthenticationResult } from \"../../response/AuthenticationResult.js\";\r\nimport {} from \"../../error/BrowserAuthErrorCodes.js\";\r\nimport { AuthResult } from \"../AuthResult.js\";\r\nimport { SsoSilentRequest } from \"../../request/SsoSilentRequest.js\";\r\nimport { SilentRequest } from \"../../request/SilentRequest.js\";\r\n\r\nexport class NestedAppAuthAdapter {\r\n protected crypto: ICrypto;\r\n protected logger: Logger;\r\n protected clientId: string;\r\n protected clientCapabilities: string[];\r\n\r\n constructor(\r\n clientId: string,\r\n clientCapabilities: string[],\r\n crypto: ICrypto,\r\n logger: Logger\r\n ) {\r\n this.clientId = clientId;\r\n this.clientCapabilities = clientCapabilities;\r\n this.crypto = crypto;\r\n this.logger = logger;\r\n }\r\n\r\n public toNaaTokenRequest(\r\n request:\r\n | PopupRequest\r\n | RedirectRequest\r\n | SilentRequest\r\n | SsoSilentRequest\r\n ): TokenRequest {\r\n let extraParams: Map;\r\n if (request.extraQueryParameters === undefined) {\r\n extraParams = new Map();\r\n } else {\r\n extraParams = new Map(\r\n Object.entries(request.extraQueryParameters)\r\n );\r\n }\r\n\r\n const correlationId =\r\n request.correlationId || this.crypto.createNewGuid();\r\n const claims = RequestParameterBuilder.addClientCapabilitiesToClaims(\r\n request.claims,\r\n this.clientCapabilities\r\n );\r\n const scopes = request.scopes || OIDC_DEFAULT_SCOPES;\r\n const tokenRequest: TokenRequest = {\r\n platformBrokerId: request.account?.homeAccountId,\r\n clientId: this.clientId,\r\n authority: request.authority,\r\n scope: scopes.join(\" \"),\r\n correlationId,\r\n claims: !StringUtils.isEmptyObj(claims) ? claims : undefined,\r\n state: request.state,\r\n authenticationScheme:\r\n request.authenticationScheme || AuthenticationScheme.BEARER,\r\n extraParameters: extraParams,\r\n };\r\n\r\n return tokenRequest;\r\n }\r\n\r\n public fromNaaTokenResponse(\r\n request: TokenRequest,\r\n response: AuthResult,\r\n reqTimestamp: number\r\n ): AuthenticationResult {\r\n if (!response.token.id_token || !response.token.access_token) {\r\n throw createClientAuthError(ClientAuthErrorCodes.nullOrEmptyToken);\r\n }\r\n\r\n // Request timestamp and AuthResult expires_in are in seconds, converting to Date for AuthenticationResult\r\n const expiresOn = TimeUtils.toDateFromSeconds(\r\n reqTimestamp + (response.token.expires_in || 0)\r\n );\r\n const idTokenClaims = AuthToken.extractTokenClaims(\r\n response.token.id_token,\r\n this.crypto.base64Decode\r\n );\r\n const account = this.fromNaaAccountInfo(\r\n response.account,\r\n response.token.id_token,\r\n idTokenClaims\r\n );\r\n const scopes = response.token.scope || request.scope;\r\n\r\n const authenticationResult: AuthenticationResult = {\r\n authority: response.token.authority || account.environment,\r\n uniqueId: account.localAccountId,\r\n tenantId: account.tenantId,\r\n scopes: scopes.split(\" \"),\r\n account,\r\n idToken: response.token.id_token,\r\n idTokenClaims,\r\n accessToken: response.token.access_token,\r\n fromCache: false,\r\n expiresOn: expiresOn,\r\n tokenType:\r\n request.authenticationScheme || AuthenticationScheme.BEARER,\r\n correlationId: request.correlationId,\r\n extExpiresOn: expiresOn,\r\n state: request.state,\r\n };\r\n\r\n return authenticationResult;\r\n }\r\n\r\n /*\r\n * export type AccountInfo = {\r\n * homeAccountId: string;\r\n * environment: string;\r\n * tenantId: string;\r\n * username: string;\r\n * localAccountId: string;\r\n * name?: string;\r\n * idToken?: string;\r\n * idTokenClaims?: TokenClaims & {\r\n * [key: string]:\r\n * | string\r\n * | number\r\n * | string[]\r\n * | object\r\n * | undefined\r\n * | unknown;\r\n * };\r\n * nativeAccountId?: string;\r\n * authorityType?: string;\r\n * };\r\n */\r\n public fromNaaAccountInfo(\r\n fromAccount: NaaAccountInfo,\r\n idToken?: string,\r\n idTokenClaims?: TokenClaims\r\n ): MsalAccountInfo {\r\n const effectiveIdTokenClaims =\r\n idTokenClaims || (fromAccount.idTokenClaims as TokenClaims);\r\n\r\n const localAccountId =\r\n fromAccount.localAccountId ||\r\n effectiveIdTokenClaims?.oid ||\r\n effectiveIdTokenClaims?.sub ||\r\n \"\";\r\n\r\n const tenantId =\r\n fromAccount.tenantId || effectiveIdTokenClaims?.tid || \"\";\r\n\r\n const homeAccountId =\r\n fromAccount.homeAccountId || `${localAccountId}.${tenantId}`;\r\n\r\n const username =\r\n fromAccount.username ||\r\n effectiveIdTokenClaims?.preferred_username ||\r\n \"\";\r\n\r\n const name = fromAccount.name || effectiveIdTokenClaims?.name;\r\n\r\n const loginHint =\r\n fromAccount.loginHint || effectiveIdTokenClaims?.login_hint;\r\n\r\n const tenantProfiles = new Map();\r\n\r\n const tenantProfile = buildTenantProfile(\r\n homeAccountId,\r\n localAccountId,\r\n tenantId,\r\n effectiveIdTokenClaims\r\n );\r\n tenantProfiles.set(tenantId, tenantProfile);\r\n\r\n const account: MsalAccountInfo = {\r\n homeAccountId,\r\n environment: fromAccount.environment,\r\n tenantId,\r\n username,\r\n localAccountId,\r\n name,\r\n loginHint,\r\n idToken: idToken,\r\n idTokenClaims: effectiveIdTokenClaims,\r\n tenantProfiles,\r\n };\r\n\r\n return account;\r\n }\r\n\r\n /**\r\n *\r\n * @param error BridgeError\r\n * @returns AuthError, ClientAuthError, ClientConfigurationError, ServerError, InteractionRequiredError\r\n */\r\n public fromBridgeError(\r\n error: unknown\r\n ):\r\n | AuthError\r\n | ClientAuthError\r\n | ClientConfigurationError\r\n | ServerError\r\n | InteractionRequiredAuthError {\r\n if (isBridgeError(error)) {\r\n switch (error.status) {\r\n case BridgeStatusCode.UserCancel:\r\n return new ClientAuthError(\r\n ClientAuthErrorCodes.userCanceled\r\n );\r\n case BridgeStatusCode.NoNetwork:\r\n return new ClientAuthError(\r\n ClientAuthErrorCodes.noNetworkConnectivity\r\n );\r\n case BridgeStatusCode.AccountUnavailable:\r\n return new ClientAuthError(\r\n ClientAuthErrorCodes.noAccountFound\r\n );\r\n case BridgeStatusCode.Disabled:\r\n return new ClientAuthError(\r\n ClientAuthErrorCodes.nestedAppAuthBridgeDisabled\r\n );\r\n case BridgeStatusCode.NestedAppAuthUnavailable:\r\n return new ClientAuthError(\r\n error.code ||\r\n ClientAuthErrorCodes.nestedAppAuthBridgeDisabled,\r\n error.description\r\n );\r\n case BridgeStatusCode.TransientError:\r\n case BridgeStatusCode.PersistentError:\r\n return new ServerError(error.code, error.description);\r\n case BridgeStatusCode.UserInteractionRequired:\r\n return new InteractionRequiredAuthError(\r\n error.code,\r\n error.description\r\n );\r\n default:\r\n return new AuthError(error.code, error.description);\r\n }\r\n } else {\r\n return new AuthError(\"unknown_error\", \"An unknown error occurred\");\r\n }\r\n }\r\n\r\n /**\r\n * Returns an AuthenticationResult from the given cache items\r\n *\r\n * @param account\r\n * @param idToken\r\n * @param accessToken\r\n * @param reqTimestamp\r\n * @returns\r\n */\r\n public toAuthenticationResultFromCache(\r\n account: AccountInfo,\r\n idToken: IdTokenEntity,\r\n accessToken: AccessTokenEntity,\r\n request: SilentRequest,\r\n correlationId: string\r\n ): AuthenticationResult {\r\n if (!idToken || !accessToken) {\r\n throw createClientAuthError(ClientAuthErrorCodes.nullOrEmptyToken);\r\n }\r\n\r\n const idTokenClaims = AuthToken.extractTokenClaims(\r\n idToken.secret,\r\n this.crypto.base64Decode\r\n );\r\n\r\n const scopes = accessToken.target || request.scopes.join(\" \");\r\n\r\n const authenticationResult: AuthenticationResult = {\r\n authority: accessToken.environment || account.environment,\r\n uniqueId: account.localAccountId,\r\n tenantId: account.tenantId,\r\n scopes: scopes.split(\" \"),\r\n account,\r\n idToken: idToken.secret,\r\n idTokenClaims: idTokenClaims || {},\r\n accessToken: accessToken.secret,\r\n fromCache: true,\r\n expiresOn: TimeUtils.toDateFromSeconds(accessToken.expiresOn),\r\n extExpiresOn: TimeUtils.toDateFromSeconds(\r\n accessToken.extendedExpiresOn\r\n ),\r\n tokenType:\r\n request.authenticationScheme || AuthenticationScheme.BEARER,\r\n correlationId,\r\n state: request.state,\r\n };\r\n\r\n return authenticationResult;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthError } from \"@azure/msal-common/browser\";\r\n\r\n/**\r\n * NestedAppAuthErrorMessage class containing string constants used by error codes and messages.\r\n */\r\nexport const NestedAppAuthErrorMessage = {\r\n unsupportedMethod: {\r\n code: \"unsupported_method\",\r\n desc: \"This method is not supported in nested app environment.\",\r\n },\r\n};\r\n\r\nexport class NestedAppAuthError extends AuthError {\r\n constructor(errorCode: string, errorMessage?: string) {\r\n super(errorCode, errorMessage);\r\n\r\n Object.setPrototypeOf(this, NestedAppAuthError.prototype);\r\n this.name = \"NestedAppAuthError\";\r\n }\r\n\r\n public static createUnsupportedError(): NestedAppAuthError {\r\n return new NestedAppAuthError(\r\n NestedAppAuthErrorMessage.unsupportedMethod.code,\r\n NestedAppAuthErrorMessage.unsupportedMethod.desc\r\n );\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n CommonAuthorizationUrlRequest,\r\n CommonSilentFlowRequest,\r\n PerformanceCallbackFunction,\r\n AccountInfo,\r\n Logger,\r\n ICrypto,\r\n IPerformanceClient,\r\n DEFAULT_CRYPTO_IMPLEMENTATION,\r\n PerformanceEvents,\r\n TimeUtils,\r\n buildStaticAuthorityOptions,\r\n AccountEntity,\r\n OIDC_DEFAULT_SCOPES,\r\n BaseAuthRequest,\r\n AccountFilter,\r\n AuthError,\r\n} from \"@azure/msal-common/browser\";\r\nimport { ITokenCache } from \"../cache/ITokenCache.js\";\r\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\r\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\r\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\r\nimport { EndSessionPopupRequest } from \"../request/EndSessionPopupRequest.js\";\r\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\r\nimport { PopupRequest } from \"../request/PopupRequest.js\";\r\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\r\nimport { SilentRequest } from \"../request/SilentRequest.js\";\r\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\r\nimport {\r\n ApiId,\r\n WrapperSKU,\r\n InteractionType,\r\n DEFAULT_REQUEST,\r\n CacheLookupPolicy,\r\n} from \"../utils/BrowserConstants.js\";\r\nimport { IController } from \"./IController.js\";\r\nimport { NestedAppOperatingContext } from \"../operatingcontext/NestedAppOperatingContext.js\";\r\nimport { IBridgeProxy } from \"../naa/IBridgeProxy.js\";\r\nimport { CryptoOps } from \"../crypto/CryptoOps.js\";\r\nimport { NestedAppAuthAdapter } from \"../naa/mapping/NestedAppAuthAdapter.js\";\r\nimport { NestedAppAuthError } from \"../error/NestedAppAuthError.js\";\r\nimport { EventHandler } from \"../event/EventHandler.js\";\r\nimport { EventType } from \"../event/EventType.js\";\r\nimport { EventCallbackFunction, EventError } from \"../event/EventMessage.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport {\r\n BrowserCacheManager,\r\n DEFAULT_BROWSER_CACHE_MANAGER,\r\n} from \"../cache/BrowserCacheManager.js\";\r\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\r\nimport * as AccountManager from \"../cache/AccountManager.js\";\r\nimport { AccountContext } from \"../naa/BridgeAccountContext.js\";\r\nimport { InitializeApplicationRequest } from \"../request/InitializeApplicationRequest.js\";\r\nimport { createNewGuid } from \"../crypto/BrowserCrypto.js\";\r\n\r\nexport class NestedAppAuthController implements IController {\r\n // OperatingContext\r\n protected readonly operatingContext: NestedAppOperatingContext;\r\n\r\n // BridgeProxy\r\n protected readonly bridgeProxy: IBridgeProxy;\r\n\r\n // Crypto interface implementation\r\n protected readonly browserCrypto: ICrypto;\r\n\r\n // Input configuration by developer/user\r\n protected readonly config: BrowserConfiguration;\r\n\r\n // Storage interface implementation\r\n protected readonly browserStorage!: BrowserCacheManager;\r\n\r\n // Logger\r\n protected logger: Logger;\r\n\r\n // Performance telemetry client\r\n protected readonly performanceClient: IPerformanceClient;\r\n\r\n // EventHandler\r\n protected readonly eventHandler: EventHandler;\r\n\r\n // NestedAppAuthAdapter\r\n protected readonly nestedAppAuthAdapter: NestedAppAuthAdapter;\r\n\r\n // currentAccount for NAA apps\r\n protected currentAccountContext: AccountContext | null;\r\n\r\n constructor(operatingContext: NestedAppOperatingContext) {\r\n this.operatingContext = operatingContext;\r\n const proxy = this.operatingContext.getBridgeProxy();\r\n if (proxy !== undefined) {\r\n this.bridgeProxy = proxy;\r\n } else {\r\n throw new Error(\"unexpected: bridgeProxy is undefined\");\r\n }\r\n\r\n // Set the configuration.\r\n this.config = operatingContext.getConfig();\r\n\r\n // Initialize logger\r\n this.logger = this.operatingContext.getLogger();\r\n\r\n // Initialize performance client\r\n this.performanceClient = this.config.telemetry.client;\r\n\r\n // Initialize the crypto class.\r\n this.browserCrypto = operatingContext.isBrowserEnvironment()\r\n ? new CryptoOps(this.logger, this.performanceClient, true)\r\n : DEFAULT_CRYPTO_IMPLEMENTATION;\r\n\r\n this.eventHandler = new EventHandler(this.logger);\r\n // Initialize the browser storage class.\r\n this.browserStorage = this.operatingContext.isBrowserEnvironment()\r\n ? new BrowserCacheManager(\r\n this.config.auth.clientId,\r\n this.config.cache,\r\n this.browserCrypto,\r\n this.logger,\r\n this.performanceClient,\r\n this.eventHandler,\r\n buildStaticAuthorityOptions(this.config.auth)\r\n )\r\n : DEFAULT_BROWSER_CACHE_MANAGER(\r\n this.config.auth.clientId,\r\n this.logger,\r\n this.performanceClient,\r\n this.eventHandler\r\n );\r\n\r\n this.nestedAppAuthAdapter = new NestedAppAuthAdapter(\r\n this.config.auth.clientId,\r\n this.config.auth.clientCapabilities,\r\n this.browserCrypto,\r\n this.logger\r\n );\r\n\r\n // Set the active account if available\r\n const accountContext = this.bridgeProxy.getAccountContext();\r\n this.currentAccountContext = accountContext ? accountContext : null;\r\n }\r\n\r\n /**\r\n * Factory function to create a new instance of NestedAppAuthController\r\n * @param operatingContext\r\n * @returns Promise\r\n */\r\n static async createController(\r\n operatingContext: NestedAppOperatingContext\r\n ): Promise {\r\n const controller = new NestedAppAuthController(operatingContext);\r\n return Promise.resolve(controller);\r\n }\r\n\r\n /**\r\n * Specific implementation of initialize function for NestedAppAuthController\r\n * @returns\r\n */\r\n async initialize(\r\n request?: InitializeApplicationRequest,\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n isBroker?: boolean\r\n ): Promise {\r\n const initCorrelationId = request?.correlationId || createNewGuid();\r\n await this.browserStorage.initialize(initCorrelationId);\r\n return Promise.resolve();\r\n }\r\n\r\n /**\r\n * Validate the incoming request and add correlationId if not present\r\n * @param request\r\n * @returns\r\n */\r\n private ensureValidRequest<\r\n T extends\r\n | SsoSilentRequest\r\n | SilentRequest\r\n | PopupRequest\r\n | RedirectRequest\r\n >(request: T): T {\r\n if (request?.correlationId) {\r\n return request;\r\n }\r\n return {\r\n ...request,\r\n correlationId: this.browserCrypto.createNewGuid(),\r\n };\r\n }\r\n\r\n /**\r\n * Internal implementation of acquireTokenInteractive flow\r\n * @param request\r\n * @returns\r\n */\r\n private async acquireTokenInteractive(\r\n request: PopupRequest | RedirectRequest\r\n ): Promise {\r\n const validRequest = this.ensureValidRequest(request);\r\n\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_START,\r\n InteractionType.Popup,\r\n validRequest\r\n );\r\n\r\n const atPopupMeasurement = this.performanceClient.startMeasurement(\r\n PerformanceEvents.AcquireTokenPopup,\r\n validRequest.correlationId\r\n );\r\n\r\n atPopupMeasurement?.add({ nestedAppAuthRequest: true });\r\n\r\n try {\r\n const naaRequest =\r\n this.nestedAppAuthAdapter.toNaaTokenRequest(validRequest);\r\n const reqTimestamp = TimeUtils.nowSeconds();\r\n const response = await this.bridgeProxy.getTokenInteractive(\r\n naaRequest\r\n );\r\n const result: AuthenticationResult = {\r\n ...this.nestedAppAuthAdapter.fromNaaTokenResponse(\r\n naaRequest,\r\n response,\r\n reqTimestamp\r\n ),\r\n };\r\n\r\n // cache the tokens in the response\r\n try {\r\n // cache hydration can fail in JS Runtime scenario that doesn't support full crypto API\r\n await this.hydrateCache(result, request);\r\n } catch (error) {\r\n this.logger.warningPii(\r\n `Failed to hydrate cache. Error: ${error}`,\r\n validRequest.correlationId\r\n );\r\n }\r\n\r\n // cache the account context in memory after successful token fetch\r\n this.currentAccountContext = {\r\n homeAccountId: result.account.homeAccountId,\r\n environment: result.account.environment,\r\n tenantId: result.account.tenantId,\r\n };\r\n\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_SUCCESS,\r\n InteractionType.Popup,\r\n result\r\n );\r\n\r\n atPopupMeasurement.add({\r\n accessTokenSize: result.accessToken.length,\r\n idTokenSize: result.idToken.length,\r\n });\r\n\r\n atPopupMeasurement.end({\r\n success: true,\r\n requestId: result.requestId,\r\n });\r\n\r\n return result;\r\n } catch (e) {\r\n const error =\r\n e instanceof AuthError\r\n ? e\r\n : this.nestedAppAuthAdapter.fromBridgeError(e);\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_FAILURE,\r\n InteractionType.Popup,\r\n null,\r\n e as EventError\r\n );\r\n\r\n atPopupMeasurement.end(\r\n {\r\n success: false,\r\n },\r\n e\r\n );\r\n\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Internal implementation of acquireTokenSilent flow\r\n * @param request\r\n * @returns\r\n */\r\n private async acquireTokenSilentInternal(\r\n request: SilentRequest\r\n ): Promise {\r\n const validRequest = this.ensureValidRequest(request);\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_START,\r\n InteractionType.Silent,\r\n validRequest\r\n );\r\n\r\n // Look for tokens in the cache first\r\n const result = await this.acquireTokenFromCache(validRequest);\r\n if (result) {\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_SUCCESS,\r\n InteractionType.Silent,\r\n result\r\n );\r\n return result;\r\n }\r\n\r\n // proceed with acquiring tokens via the host\r\n const ssoSilentMeasurement = this.performanceClient.startMeasurement(\r\n PerformanceEvents.SsoSilent,\r\n validRequest.correlationId\r\n );\r\n\r\n ssoSilentMeasurement?.increment({\r\n visibilityChangeCount: 0,\r\n });\r\n\r\n ssoSilentMeasurement?.add({\r\n nestedAppAuthRequest: true,\r\n });\r\n\r\n try {\r\n const naaRequest =\r\n this.nestedAppAuthAdapter.toNaaTokenRequest(validRequest);\r\n const reqTimestamp = TimeUtils.nowSeconds();\r\n const response = await this.bridgeProxy.getTokenSilent(naaRequest);\r\n\r\n const result: AuthenticationResult =\r\n this.nestedAppAuthAdapter.fromNaaTokenResponse(\r\n naaRequest,\r\n response,\r\n reqTimestamp\r\n );\r\n\r\n // cache the tokens in the response\r\n try {\r\n // cache hydration can fail in JS Runtime scenario that doesn't support full crypto API\r\n await this.hydrateCache(result, request);\r\n } catch (error) {\r\n this.logger.warningPii(\r\n `Failed to hydrate cache. Error: ${error}`,\r\n validRequest.correlationId\r\n );\r\n }\r\n\r\n // cache the account context in memory after successful token fetch\r\n this.currentAccountContext = {\r\n homeAccountId: result.account.homeAccountId,\r\n environment: result.account.environment,\r\n tenantId: result.account.tenantId,\r\n };\r\n\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_SUCCESS,\r\n InteractionType.Silent,\r\n result\r\n );\r\n ssoSilentMeasurement?.add({\r\n accessTokenSize: result.accessToken.length,\r\n idTokenSize: result.idToken.length,\r\n });\r\n ssoSilentMeasurement?.end({\r\n success: true,\r\n requestId: result.requestId,\r\n });\r\n return result;\r\n } catch (e) {\r\n const error =\r\n e instanceof AuthError\r\n ? e\r\n : this.nestedAppAuthAdapter.fromBridgeError(e);\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_FAILURE,\r\n InteractionType.Silent,\r\n null,\r\n e as EventError\r\n );\r\n ssoSilentMeasurement?.end(\r\n {\r\n success: false,\r\n },\r\n e\r\n );\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * acquires tokens from cache\r\n * @param request\r\n * @returns\r\n */\r\n private async acquireTokenFromCache(\r\n request: SilentRequest\r\n ): Promise {\r\n const atsMeasurement = this.performanceClient.startMeasurement(\r\n PerformanceEvents.AcquireTokenSilent,\r\n request.correlationId\r\n );\r\n\r\n atsMeasurement?.add({\r\n nestedAppAuthRequest: true,\r\n });\r\n\r\n // if the request has claims, we cannot look up in the cache\r\n if (request.claims) {\r\n this.logger.verbose(\r\n \"Claims are present in the request, skipping cache lookup\"\r\n );\r\n return null;\r\n }\r\n\r\n // if the request has forceRefresh, we cannot look up in the cache\r\n if (request.forceRefresh) {\r\n this.logger.verbose(\r\n \"forceRefresh is set to true, skipping cache lookup\"\r\n );\r\n return null;\r\n }\r\n\r\n // respect cache lookup policy\r\n let result: AuthenticationResult | null = null;\r\n if (!request.cacheLookupPolicy) {\r\n request.cacheLookupPolicy = CacheLookupPolicy.Default;\r\n }\r\n\r\n switch (request.cacheLookupPolicy) {\r\n case CacheLookupPolicy.Default:\r\n case CacheLookupPolicy.AccessToken:\r\n case CacheLookupPolicy.AccessTokenAndRefreshToken:\r\n result = await this.acquireTokenFromCacheInternal(request);\r\n break;\r\n default:\r\n return null;\r\n }\r\n\r\n if (result) {\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_SUCCESS,\r\n InteractionType.Silent,\r\n result\r\n );\r\n atsMeasurement?.add({\r\n accessTokenSize: result?.accessToken.length,\r\n idTokenSize: result?.idToken.length,\r\n });\r\n atsMeasurement?.end({\r\n success: true,\r\n });\r\n return result;\r\n }\r\n\r\n this.logger.warning(\r\n \"Cached tokens are not found for the account, proceeding with silent token request.\"\r\n );\r\n\r\n this.eventHandler.emitEvent(\r\n EventType.ACQUIRE_TOKEN_FAILURE,\r\n InteractionType.Silent,\r\n null\r\n );\r\n atsMeasurement?.end({\r\n success: false,\r\n });\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n *\r\n * @param request\r\n * @returns\r\n */\r\n private async acquireTokenFromCacheInternal(\r\n request: SilentRequest\r\n ): Promise {\r\n // always prioritize the account context from the bridge\r\n const accountContext =\r\n this.bridgeProxy.getAccountContext() || this.currentAccountContext;\r\n let currentAccount: AccountInfo | null = null;\r\n const correlationId =\r\n request.correlationId || this.browserCrypto.createNewGuid();\r\n if (accountContext) {\r\n currentAccount = AccountManager.getAccount(\r\n accountContext,\r\n this.logger,\r\n this.browserStorage,\r\n correlationId\r\n );\r\n }\r\n\r\n // fall back to brokering if no cached account is found\r\n if (!currentAccount) {\r\n this.logger.verbose(\r\n \"No active account found, falling back to the host\"\r\n );\r\n return Promise.resolve(null);\r\n }\r\n\r\n this.logger.verbose(\r\n \"active account found, attempting to acquire token silently\"\r\n );\r\n\r\n const authRequest: BaseAuthRequest = {\r\n ...request,\r\n correlationId:\r\n request.correlationId || this.browserCrypto.createNewGuid(),\r\n authority: request.authority || currentAccount.environment,\r\n scopes: request.scopes?.length\r\n ? request.scopes\r\n : [...OIDC_DEFAULT_SCOPES],\r\n };\r\n\r\n // fetch access token and check for expiry\r\n const tokenKeys = this.browserStorage.getTokenKeys();\r\n const cachedAccessToken = this.browserStorage.getAccessToken(\r\n currentAccount,\r\n authRequest,\r\n tokenKeys,\r\n currentAccount.tenantId\r\n );\r\n\r\n // If there is no access token, log it and return null\r\n if (!cachedAccessToken) {\r\n this.logger.verbose(\"No cached access token found\");\r\n return Promise.resolve(null);\r\n } else if (\r\n TimeUtils.wasClockTurnedBack(cachedAccessToken.cachedAt) ||\r\n TimeUtils.isTokenExpired(\r\n cachedAccessToken.expiresOn,\r\n this.config.system.tokenRenewalOffsetSeconds\r\n )\r\n ) {\r\n this.logger.verbose(\"Cached access token has expired\");\r\n return Promise.resolve(null);\r\n }\r\n\r\n const cachedIdToken = this.browserStorage.getIdToken(\r\n currentAccount,\r\n authRequest.correlationId,\r\n tokenKeys,\r\n currentAccount.tenantId,\r\n this.performanceClient\r\n );\r\n\r\n if (!cachedIdToken) {\r\n this.logger.verbose(\"No cached id token found\");\r\n return Promise.resolve(null);\r\n }\r\n\r\n return this.nestedAppAuthAdapter.toAuthenticationResultFromCache(\r\n currentAccount,\r\n cachedIdToken,\r\n cachedAccessToken,\r\n authRequest,\r\n authRequest.correlationId\r\n );\r\n }\r\n\r\n /**\r\n * acquireTokenPopup flow implementation\r\n * @param request\r\n * @returns\r\n */\r\n async acquireTokenPopup(\r\n request: PopupRequest\r\n ): Promise {\r\n return this.acquireTokenInteractive(request);\r\n }\r\n\r\n /**\r\n * acquireTokenRedirect flow is not supported in nested app auth\r\n * @param request\r\n */\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n acquireTokenRedirect(request: RedirectRequest): Promise {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n\r\n /**\r\n * acquireTokenSilent flow implementation\r\n * @param silentRequest\r\n * @returns\r\n */\r\n async acquireTokenSilent(\r\n silentRequest: SilentRequest\r\n ): Promise {\r\n return this.acquireTokenSilentInternal(silentRequest);\r\n }\r\n\r\n /**\r\n * Hybrid flow is not currently supported in nested app auth\r\n * @param request\r\n */\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n acquireTokenByCode(\r\n request: AuthorizationCodeRequest // eslint-disable-line @typescript-eslint/no-unused-vars\r\n ): Promise {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n\r\n /**\r\n * acquireTokenNative flow is not currently supported in nested app auth\r\n * @param request\r\n * @param apiId\r\n * @param accountId\r\n */\r\n acquireTokenNative(\r\n request: // eslint-disable-line @typescript-eslint/no-unused-vars\r\n | SilentRequest\r\n | Partial<\r\n Omit<\r\n CommonAuthorizationUrlRequest,\r\n | \"requestedClaimsHash\"\r\n | \"responseMode\"\r\n | \"earJwk\"\r\n | \"codeChallenge\"\r\n | \"codeChallengeMethod\"\r\n | \"platformBroker\"\r\n >\r\n >\r\n | PopupRequest,\r\n apiId: ApiId, // eslint-disable-line @typescript-eslint/no-unused-vars\r\n accountId?: string | undefined // eslint-disable-line @typescript-eslint/no-unused-vars\r\n ): Promise {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n\r\n /**\r\n * acquireTokenByRefreshToken flow is not currently supported in nested app auth\r\n * @param commonRequest\r\n * @param silentRequest\r\n */\r\n acquireTokenByRefreshToken(\r\n commonRequest: CommonSilentFlowRequest, // eslint-disable-line @typescript-eslint/no-unused-vars\r\n silentRequest: SilentRequest // eslint-disable-line @typescript-eslint/no-unused-vars\r\n ): Promise {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n\r\n /**\r\n * Adds event callbacks to array\r\n * @param callback\r\n * @param eventTypes\r\n */\r\n addEventCallback(\r\n callback: EventCallbackFunction,\r\n eventTypes?: Array\r\n ): string | null {\r\n return this.eventHandler.addEventCallback(callback, eventTypes);\r\n }\r\n\r\n /**\r\n * Removes callback with provided id from callback array\r\n * @param callbackId\r\n */\r\n removeEventCallback(callbackId: string): void {\r\n this.eventHandler.removeEventCallback(callbackId);\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n addPerformanceCallback(callback: PerformanceCallbackFunction): string {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n removePerformanceCallback(callbackId: string): boolean {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n\r\n enableAccountStorageEvents(): void {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n\r\n disableAccountStorageEvents(): void {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n\r\n // #region Account APIs\r\n\r\n /**\r\n * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.\r\n * @param accountFilter - (Optional) filter to narrow down the accounts returned\r\n * @returns Array of AccountInfo objects in cache\r\n */\r\n getAllAccounts(accountFilter?: AccountFilter): AccountInfo[] {\r\n const correlationId = this.browserCrypto.createNewGuid();\r\n return AccountManager.getAllAccounts(\r\n this.logger,\r\n this.browserStorage,\r\n this.isBrowserEnv(),\r\n correlationId,\r\n accountFilter\r\n );\r\n }\r\n\r\n /**\r\n * Returns the first account found in the cache that matches the account filter passed in.\r\n * @param accountFilter\r\n * @returns The first account found in the cache matching the provided filter or null if no account could be found.\r\n */\r\n getAccount(accountFilter: AccountFilter): AccountInfo | null {\r\n const correlationId = this.browserCrypto.createNewGuid();\r\n return AccountManager.getAccount(\r\n accountFilter,\r\n this.logger,\r\n this.browserStorage,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching username.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found.\r\n * This API is provided for convenience but getAccountById should be used for best reliability\r\n * @param username\r\n * @returns The account object stored in MSAL\r\n */\r\n getAccountByUsername(username: string): AccountInfo | null {\r\n const correlationId = this.browserCrypto.createNewGuid();\r\n return AccountManager.getAccountByUsername(\r\n username,\r\n this.logger,\r\n this.browserStorage,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching homeAccountId.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found\r\n * @param homeAccountId\r\n * @returns The account object stored in MSAL\r\n */\r\n getAccountByHomeId(homeAccountId: string): AccountInfo | null {\r\n const correlationId = this.browserCrypto.createNewGuid();\r\n return AccountManager.getAccountByHomeId(\r\n homeAccountId,\r\n this.logger,\r\n this.browserStorage,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching localAccountId.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found\r\n * @param localAccountId\r\n * @returns The account object stored in MSAL\r\n */\r\n getAccountByLocalId(localAccountId: string): AccountInfo | null {\r\n const correlationId = this.browserCrypto.createNewGuid();\r\n return AccountManager.getAccountByLocalId(\r\n localAccountId,\r\n this.logger,\r\n this.browserStorage,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Sets the account to use as the active account. If no account is passed to the acquireToken APIs, then MSAL will use this active account.\r\n * @param account\r\n */\r\n setActiveAccount(account: AccountInfo | null): void {\r\n /*\r\n * StandardController uses this to allow the developer to set the active account\r\n * in the nested app auth scenario the active account is controlled by the app hosting the nested app\r\n */\r\n const correlationId = this.browserCrypto.createNewGuid();\r\n return AccountManager.setActiveAccount(\r\n account,\r\n this.browserStorage,\r\n correlationId\r\n );\r\n }\r\n\r\n /**\r\n * Gets the currently active account\r\n */\r\n getActiveAccount(): AccountInfo | null {\r\n const correlationId = this.browserCrypto.createNewGuid();\r\n return AccountManager.getActiveAccount(\r\n this.browserStorage,\r\n correlationId\r\n );\r\n }\r\n\r\n // #endregion\r\n\r\n handleRedirectPromise(\r\n hash?: string | undefined // eslint-disable-line @typescript-eslint/no-unused-vars\r\n ): Promise {\r\n return Promise.resolve(null);\r\n }\r\n loginPopup(\r\n request?: PopupRequest | undefined // eslint-disable-line @typescript-eslint/no-unused-vars\r\n ): Promise {\r\n return this.acquireTokenInteractive(request || DEFAULT_REQUEST);\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n loginRedirect(request?: RedirectRequest | undefined): Promise {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n logout(logoutRequest?: EndSessionRequest | undefined): Promise {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n logoutRedirect(\r\n logoutRequest?: EndSessionRequest | undefined // eslint-disable-line @typescript-eslint/no-unused-vars\r\n ): Promise {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n logoutPopup(\r\n logoutRequest?: EndSessionPopupRequest | undefined // eslint-disable-line @typescript-eslint/no-unused-vars\r\n ): Promise {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n ssoSilent(\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n request: Partial<\r\n Omit<\r\n CommonAuthorizationUrlRequest,\r\n | \"requestedClaimsHash\"\r\n | \"responseMode\"\r\n | \"earJwk\"\r\n | \"codeChallenge\"\r\n | \"codeChallengeMethod\"\r\n | \"platformBroker\"\r\n >\r\n >\r\n ): Promise {\r\n return this.acquireTokenSilentInternal(request as SilentRequest);\r\n }\r\n getTokenCache(): ITokenCache {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n\r\n /**\r\n * Returns the logger instance\r\n */\r\n public getLogger(): Logger {\r\n return this.logger;\r\n }\r\n\r\n /**\r\n * Replaces the default logger set in configurations with new Logger with new configurations\r\n * @param logger Logger instance\r\n */\r\n setLogger(logger: Logger): void {\r\n this.logger = logger;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n initializeWrapperLibrary(sku: WrapperSKU, version: string): void {\r\n /*\r\n * Standard controller uses this to set the sku and version of the wrapper library in the storage\r\n * we do nothing here\r\n */\r\n return;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n setNavigationClient(navigationClient: INavigationClient): void {\r\n this.logger.warning(\r\n \"setNavigationClient is not supported in nested app auth\"\r\n );\r\n }\r\n\r\n getConfiguration(): BrowserConfiguration {\r\n return this.config;\r\n }\r\n\r\n isBrowserEnv(): boolean {\r\n return this.operatingContext.isBrowserEnvironment();\r\n }\r\n\r\n getBrowserCrypto(): ICrypto {\r\n return this.browserCrypto;\r\n }\r\n\r\n getPerformanceClient(): IPerformanceClient {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n\r\n getRedirectResponse(): Map> {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n async clearCache(logoutRequest?: ClearCacheRequest): Promise {\r\n throw NestedAppAuthError.createUnsupportedError();\r\n }\r\n\r\n async hydrateCache(\r\n result: AuthenticationResult,\r\n request:\r\n | SilentRequest\r\n | SsoSilentRequest\r\n | RedirectRequest\r\n | PopupRequest\r\n ): Promise {\r\n this.logger.verbose(\"hydrateCache called\");\r\n\r\n const accountEntity = AccountEntity.createFromAccountInfo(\r\n result.account,\r\n result.cloudGraphHostName,\r\n result.msGraphHost\r\n );\r\n await this.browserStorage.setAccount(\r\n accountEntity,\r\n result.correlationId\r\n );\r\n return this.browserStorage.hydrateCache(result, request);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { NestedAppOperatingContext } from \"../operatingcontext/NestedAppOperatingContext.js\";\r\nimport { StandardOperatingContext } from \"../operatingcontext/StandardOperatingContext.js\";\r\nimport { IController } from \"./IController.js\";\r\nimport { Configuration } from \"../config/Configuration.js\";\r\nimport { StandardController } from \"./StandardController.js\";\r\nimport { NestedAppAuthController } from \"./NestedAppAuthController.js\";\r\nimport { InitializeApplicationRequest } from \"../request/InitializeApplicationRequest.js\";\r\n\r\nexport async function createV3Controller(\r\n config: Configuration,\r\n request?: InitializeApplicationRequest\r\n): Promise {\r\n const standard = new StandardOperatingContext(config);\r\n\r\n await standard.initialize();\r\n return StandardController.createController(standard, request);\r\n}\r\n\r\nexport async function createController(\r\n config: Configuration\r\n): Promise {\r\n const standard = new StandardOperatingContext(config);\r\n const nestedApp = new NestedAppOperatingContext(config);\r\n\r\n const operatingContexts = [standard.initialize(), nestedApp.initialize()];\r\n\r\n await Promise.all(operatingContexts);\r\n\r\n if (nestedApp.isAvailable() && config.auth.supportsNestedAppAuth) {\r\n return NestedAppAuthController.createController(nestedApp);\r\n } else if (standard.isAvailable()) {\r\n return StandardController.createController(standard);\r\n } else {\r\n // Since neither of the actual operating contexts are available keep the UnknownOperatingContextController\r\n return null;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { ITokenCache } from \"../cache/ITokenCache.js\";\r\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\r\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\r\nimport { PopupRequest } from \"../request/PopupRequest.js\";\r\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\r\nimport { SilentRequest } from \"../request/SilentRequest.js\";\r\nimport { WrapperSKU } from \"../utils/BrowserConstants.js\";\r\nimport { IPublicClientApplication } from \"./IPublicClientApplication.js\";\r\nimport { IController } from \"../controllers/IController.js\";\r\nimport {\r\n PerformanceCallbackFunction,\r\n AccountInfo,\r\n AccountFilter,\r\n Logger,\r\n} from \"@azure/msal-common/browser\";\r\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\r\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\r\nimport * as ControllerFactory from \"../controllers/ControllerFactory.js\";\r\nimport { StandardController } from \"../controllers/StandardController.js\";\r\nimport {\r\n BrowserConfiguration,\r\n Configuration,\r\n} from \"../config/Configuration.js\";\r\nimport { StandardOperatingContext } from \"../operatingcontext/StandardOperatingContext.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { EventCallbackFunction } from \"../event/EventMessage.js\";\r\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\r\nimport { EndSessionPopupRequest } from \"../request/EndSessionPopupRequest.js\";\r\nimport { NestedAppAuthController } from \"../controllers/NestedAppAuthController.js\";\r\nimport { NestedAppOperatingContext } from \"../operatingcontext/NestedAppOperatingContext.js\";\r\nimport { InitializeApplicationRequest } from \"../request/InitializeApplicationRequest.js\";\r\nimport { EventType } from \"../event/EventType.js\";\r\n\r\n/**\r\n * The PublicClientApplication class is the object exposed by the library to perform authentication and authorization functions in Single Page Applications\r\n * to obtain JWT tokens as described in the OAuth 2.0 Authorization Code Flow with PKCE specification.\r\n */\r\nexport class PublicClientApplication implements IPublicClientApplication {\r\n protected controller: IController;\r\n protected isBroker: boolean = false;\r\n\r\n /**\r\n * Creates StandardController and passes it to the PublicClientApplication\r\n *\r\n * @param configuration {Configuration}\r\n */\r\n public static async createPublicClientApplication(\r\n configuration: Configuration\r\n ): Promise {\r\n const controller = await ControllerFactory.createV3Controller(\r\n configuration\r\n );\r\n const pca = new PublicClientApplication(configuration, controller);\r\n\r\n return pca;\r\n }\r\n\r\n /**\r\n * @constructor\r\n * Constructor for the PublicClientApplication used to instantiate the PublicClientApplication object\r\n *\r\n * Important attributes in the Configuration object for auth are:\r\n * - clientID: the application ID of your application. You can obtain one by registering your application with our Application registration portal : https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredAppsPreview\r\n * - authority: the authority URL for your application.\r\n * - redirect_uri: the uri of your application registered in the portal.\r\n *\r\n * In Azure AD, authority is a URL indicating the Azure active directory that MSAL uses to obtain tokens.\r\n * It is of the form https://login.microsoftonline.com/{Enter_the_Tenant_Info_Here}\r\n * If your application supports Accounts in one organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with the Tenant Id or Tenant name (for example, contoso.microsoft.com).\r\n * If your application supports Accounts in any organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with organizations.\r\n * If your application supports Accounts in any organizational directory and personal Microsoft accounts, replace \"Enter_the_Tenant_Info_Here\" value with common.\r\n * To restrict support to Personal Microsoft accounts only, replace \"Enter_the_Tenant_Info_Here\" value with consumers.\r\n *\r\n * In Azure B2C, authority is of the form https://{instance}/tfp/{tenant}/{policyName}/\r\n * Full B2C functionality will be available in this library in future versions.\r\n *\r\n * @param configuration Object for the MSAL PublicClientApplication instance\r\n * @param IController Optional parameter to explictly set the controller. (Will be removed when we remove public constructor)\r\n */\r\n public constructor(configuration: Configuration, controller?: IController) {\r\n this.controller =\r\n controller ||\r\n new StandardController(new StandardOperatingContext(configuration));\r\n }\r\n\r\n /**\r\n * Initializer function to perform async startup tasks such as connecting to WAM extension\r\n * @param request {?InitializeApplicationRequest}\r\n */\r\n async initialize(request?: InitializeApplicationRequest): Promise {\r\n return this.controller.initialize(request, this.isBroker);\r\n }\r\n\r\n /**\r\n * Use when you want to obtain an access_token for your API via opening a popup window in the user's browser\r\n *\r\n * @param request\r\n *\r\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\r\n */\r\n async acquireTokenPopup(\r\n request: PopupRequest\r\n ): Promise {\r\n return this.controller.acquireTokenPopup(request);\r\n }\r\n\r\n /**\r\n * Use when you want to obtain an access_token for your API by redirecting the user's browser window to the authorization endpoint. This function redirects\r\n * the page, so any code that follows this function will not execute.\r\n *\r\n * IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current\r\n * browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.\r\n *\r\n * @param request\r\n */\r\n acquireTokenRedirect(request: RedirectRequest): Promise {\r\n return this.controller.acquireTokenRedirect(request);\r\n }\r\n\r\n /**\r\n * Silently acquire an access token for a given set of scopes. Returns currently processing promise if parallel requests are made.\r\n *\r\n * @param {@link (SilentRequest:type)}\r\n * @returns {Promise.} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthenticationResult} object\r\n */\r\n acquireTokenSilent(\r\n silentRequest: SilentRequest\r\n ): Promise {\r\n return this.controller.acquireTokenSilent(silentRequest);\r\n }\r\n\r\n /**\r\n * This function redeems an authorization code (passed as code) from the eSTS token endpoint.\r\n * This authorization code should be acquired server-side using a confidential client to acquire a spa_code.\r\n * This API is not indended for normal authorization code acquisition and redemption.\r\n *\r\n * Redemption of this authorization code will not require PKCE, as it was acquired by a confidential client.\r\n *\r\n * @param request {@link AuthorizationCodeRequest}\r\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\r\n */\r\n acquireTokenByCode(\r\n request: AuthorizationCodeRequest\r\n ): Promise {\r\n return this.controller.acquireTokenByCode(request);\r\n }\r\n\r\n /**\r\n * Adds event callbacks to array\r\n * @param callback\r\n * @param eventTypes\r\n */\r\n addEventCallback(\r\n callback: EventCallbackFunction,\r\n eventTypes?: Array\r\n ): string | null {\r\n return this.controller.addEventCallback(callback, eventTypes);\r\n }\r\n\r\n /**\r\n * Removes callback with provided id from callback array\r\n * @param callbackId\r\n */\r\n removeEventCallback(callbackId: string): void {\r\n return this.controller.removeEventCallback(callbackId);\r\n }\r\n\r\n /**\r\n * Registers a callback to receive performance events.\r\n *\r\n * @param {PerformanceCallbackFunction} callback\r\n * @returns {string}\r\n */\r\n addPerformanceCallback(callback: PerformanceCallbackFunction): string {\r\n return this.controller.addPerformanceCallback(callback);\r\n }\r\n\r\n /**\r\n * Removes a callback registered with addPerformanceCallback.\r\n *\r\n * @param {string} callbackId\r\n * @returns {boolean}\r\n */\r\n removePerformanceCallback(callbackId: string): boolean {\r\n return this.controller.removePerformanceCallback(callbackId);\r\n }\r\n\r\n /**\r\n * Adds event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\r\n */\r\n enableAccountStorageEvents(): void {\r\n this.controller.enableAccountStorageEvents();\r\n }\r\n\r\n /**\r\n * Removes event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\r\n */\r\n disableAccountStorageEvents(): void {\r\n this.controller.disableAccountStorageEvents();\r\n }\r\n\r\n /**\r\n * Returns the first account found in the cache that matches the account filter passed in.\r\n * @param accountFilter\r\n * @returns The first account found in the cache matching the provided filter or null if no account could be found.\r\n */\r\n getAccount(accountFilter: AccountFilter): AccountInfo | null {\r\n return this.controller.getAccount(accountFilter);\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching homeAccountId.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found\r\n * @param homeAccountId\r\n * @returns The account object stored in MSAL\r\n * @deprecated - Use getAccount instead\r\n */\r\n getAccountByHomeId(homeAccountId: string): AccountInfo | null {\r\n return this.controller.getAccountByHomeId(homeAccountId);\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching localAccountId.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found\r\n * @param localAccountId\r\n * @returns The account object stored in MSAL\r\n * @deprecated - Use getAccount instead\r\n */\r\n getAccountByLocalId(localId: string): AccountInfo | null {\r\n return this.controller.getAccountByLocalId(localId);\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching username.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found.\r\n * This API is provided for convenience but getAccountById should be used for best reliability\r\n * @param userName\r\n * @returns The account object stored in MSAL\r\n * @deprecated - Use getAccount instead\r\n */\r\n getAccountByUsername(userName: string): AccountInfo | null {\r\n return this.controller.getAccountByUsername(userName);\r\n }\r\n\r\n /**\r\n * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.\r\n * @param accountFilter - (Optional) filter to narrow down the accounts returned\r\n * @returns Array of AccountInfo objects in cache\r\n */\r\n getAllAccounts(accountFilter?: AccountFilter): AccountInfo[] {\r\n return this.controller.getAllAccounts(accountFilter);\r\n }\r\n\r\n /**\r\n * Event handler function which allows users to fire events after the PublicClientApplication object\r\n * has loaded during redirect flows. This should be invoked on all page loads involved in redirect\r\n * auth flows.\r\n * @param hash Hash to process. Defaults to the current value of window.location.hash. Only needs to be provided explicitly if the response to be handled is not contained in the current value.\r\n * @returns Token response or null. If the return value is null, then no auth redirect was detected.\r\n */\r\n handleRedirectPromise(\r\n hash?: string | undefined\r\n ): Promise {\r\n return this.controller.handleRedirectPromise(hash);\r\n }\r\n\r\n /**\r\n * Use when initiating the login process via opening a popup window in the user's browser\r\n *\r\n * @param request\r\n *\r\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\r\n */\r\n loginPopup(\r\n request?: PopupRequest | undefined\r\n ): Promise {\r\n return this.controller.loginPopup(request);\r\n }\r\n\r\n /**\r\n * Use when initiating the login process by redirecting the user's browser to the authorization endpoint. This function redirects the page, so\r\n * any code that follows this function will not execute.\r\n *\r\n * IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current\r\n * browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.\r\n *\r\n * @param request\r\n */\r\n loginRedirect(request?: RedirectRequest | undefined): Promise {\r\n return this.controller.loginRedirect(request);\r\n }\r\n\r\n /**\r\n * Deprecated logout function. Use logoutRedirect or logoutPopup instead\r\n * @param logoutRequest\r\n * @deprecated\r\n */\r\n logout(logoutRequest?: EndSessionRequest): Promise {\r\n return this.controller.logout(logoutRequest);\r\n }\r\n\r\n /**\r\n * Use to log out the current user, and redirect the user to the postLogoutRedirectUri.\r\n * Default behaviour is to redirect the user to `window.location.href`.\r\n * @param logoutRequest\r\n */\r\n logoutRedirect(logoutRequest?: EndSessionRequest): Promise {\r\n return this.controller.logoutRedirect(logoutRequest);\r\n }\r\n\r\n /**\r\n * Clears local cache for the current user then opens a popup window prompting the user to sign-out of the server\r\n * @param logoutRequest\r\n */\r\n logoutPopup(logoutRequest?: EndSessionPopupRequest): Promise {\r\n return this.controller.logoutPopup(logoutRequest);\r\n }\r\n\r\n /**\r\n * This function uses a hidden iframe to fetch an authorization code from the eSTS. There are cases where this may not work:\r\n * - Any browser using a form of Intelligent Tracking Prevention\r\n * - If there is not an established session with the service\r\n *\r\n * In these cases, the request must be done inside a popup or full frame redirect.\r\n *\r\n * For the cases where interaction is required, you cannot send a request with prompt=none.\r\n *\r\n * If your refresh token has expired, you can use this function to fetch a new set of tokens silently as long as\r\n * you session on the server still exists.\r\n * @param request {@link SsoSilentRequest}\r\n *\r\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\r\n */\r\n ssoSilent(request: SsoSilentRequest): Promise {\r\n return this.controller.ssoSilent(request);\r\n }\r\n\r\n /**\r\n * Gets the token cache for the application.\r\n */\r\n getTokenCache(): ITokenCache {\r\n return this.controller.getTokenCache();\r\n }\r\n\r\n /**\r\n * Returns the logger instance\r\n */\r\n getLogger(): Logger {\r\n return this.controller.getLogger();\r\n }\r\n\r\n /**\r\n * Replaces the default logger set in configurations with new Logger with new configurations\r\n * @param logger Logger instance\r\n */\r\n setLogger(logger: Logger): void {\r\n this.controller.setLogger(logger);\r\n }\r\n\r\n /**\r\n * Sets the account to use as the active account. If no account is passed to the acquireToken APIs, then MSAL will use this active account.\r\n * @param account\r\n */\r\n setActiveAccount(account: AccountInfo | null): void {\r\n this.controller.setActiveAccount(account);\r\n }\r\n\r\n /**\r\n * Gets the currently active account\r\n */\r\n getActiveAccount(): AccountInfo | null {\r\n return this.controller.getActiveAccount();\r\n }\r\n\r\n /**\r\n * Called by wrapper libraries (Angular & React) to set SKU and Version passed down to telemetry, logger, etc.\r\n * @param sku\r\n * @param version\r\n */\r\n initializeWrapperLibrary(sku: WrapperSKU, version: string): void {\r\n return this.controller.initializeWrapperLibrary(sku, version);\r\n }\r\n\r\n /**\r\n * Sets navigation client\r\n * @param navigationClient\r\n */\r\n setNavigationClient(navigationClient: INavigationClient): void {\r\n this.controller.setNavigationClient(navigationClient);\r\n }\r\n\r\n /**\r\n * Returns the configuration object\r\n * @internal\r\n */\r\n getConfiguration(): BrowserConfiguration {\r\n return this.controller.getConfiguration();\r\n }\r\n\r\n /**\r\n * Hydrates cache with the tokens and account in the AuthenticationResult object\r\n * @param result\r\n * @param request - The request object that was used to obtain the AuthenticationResult\r\n * @returns\r\n */\r\n async hydrateCache(\r\n result: AuthenticationResult,\r\n request:\r\n | SilentRequest\r\n | SsoSilentRequest\r\n | RedirectRequest\r\n | PopupRequest\r\n ): Promise {\r\n return this.controller.hydrateCache(result, request);\r\n }\r\n\r\n /**\r\n * Clears tokens and account from the browser cache.\r\n * @param logoutRequest\r\n */\r\n clearCache(logoutRequest?: ClearCacheRequest): Promise {\r\n return this.controller.clearCache(logoutRequest);\r\n }\r\n}\r\n\r\n/**\r\n * creates NestedAppAuthController and passes it to the PublicClientApplication,\r\n * falls back to StandardController if NestedAppAuthController is not available\r\n *\r\n * @param configuration\r\n * @returns IPublicClientApplication\r\n *\r\n */\r\nexport async function createNestablePublicClientApplication(\r\n configuration: Configuration\r\n): Promise {\r\n const nestedAppAuth = new NestedAppOperatingContext(configuration);\r\n await nestedAppAuth.initialize();\r\n\r\n if (nestedAppAuth.isAvailable()) {\r\n const controller = new NestedAppAuthController(nestedAppAuth);\r\n const nestablePCA = new PublicClientApplication(\r\n configuration,\r\n controller\r\n );\r\n await nestablePCA.initialize();\r\n return nestablePCA;\r\n }\r\n\r\n return createStandardPublicClientApplication(configuration);\r\n}\r\n\r\n/**\r\n * creates PublicClientApplication using StandardController\r\n *\r\n * @param configuration\r\n * @returns IPublicClientApplication\r\n *\r\n */\r\nexport async function createStandardPublicClientApplication(\r\n configuration: Configuration\r\n): Promise {\r\n const pca = new PublicClientApplication(configuration);\r\n await pca.initialize();\r\n return pca;\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n CommonAuthorizationUrlRequest,\r\n CommonSilentFlowRequest,\r\n PerformanceCallbackFunction,\r\n AccountInfo,\r\n Logger,\r\n ICrypto,\r\n IPerformanceClient,\r\n DEFAULT_CRYPTO_IMPLEMENTATION,\r\n AccountFilter,\r\n} from \"@azure/msal-common/browser\";\r\nimport { ITokenCache } from \"../cache/ITokenCache.js\";\r\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\r\nimport {\r\n BrowserCacheManager,\r\n DEFAULT_BROWSER_CACHE_MANAGER,\r\n} from \"../cache/BrowserCacheManager.js\";\r\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\r\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\r\nimport { EndSessionPopupRequest } from \"../request/EndSessionPopupRequest.js\";\r\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\r\nimport { PopupRequest } from \"../request/PopupRequest.js\";\r\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\r\nimport { SilentRequest } from \"../request/SilentRequest.js\";\r\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { ApiId, WrapperSKU } from \"../utils/BrowserConstants.js\";\r\nimport { IController } from \"./IController.js\";\r\nimport { UnknownOperatingContext } from \"../operatingcontext/UnknownOperatingContext.js\";\r\nimport { CryptoOps } from \"../crypto/CryptoOps.js\";\r\nimport {\r\n blockAPICallsBeforeInitialize,\r\n blockNonBrowserEnvironment,\r\n} from \"../utils/BrowserUtils.js\";\r\nimport { EventCallbackFunction } from \"../event/EventMessage.js\";\r\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\r\nimport { EventType } from \"../event/EventType.js\";\r\nimport { EventHandler } from \"../event/EventHandler.js\";\r\n\r\n/**\r\n * UnknownOperatingContextController class\r\n *\r\n * - Until initialize method is called, this controller is the default\r\n * - AFter initialize method is called, this controller will be swapped out for the appropriate controller\r\n * if the operating context can be determined; otherwise this controller will continued be used\r\n *\r\n * - Why do we have this? We don't want to dynamically import (download) all of the code in StandardController if we don't need to.\r\n *\r\n * - Only includes implementation for getAccounts and handleRedirectPromise\r\n * - All other methods are will throw initialization error (because either initialize method or the factory method were not used)\r\n * - This controller is necessary for React Native wrapper, server side rendering and any other scenario where we don't have a DOM\r\n *\r\n */\r\nexport class UnknownOperatingContextController implements IController {\r\n // OperatingContext\r\n protected readonly operatingContext: UnknownOperatingContext;\r\n\r\n // Logger\r\n protected logger: Logger;\r\n\r\n // Storage interface implementation\r\n protected readonly browserStorage: BrowserCacheManager;\r\n\r\n // Input configuration by developer/user\r\n protected readonly config: BrowserConfiguration;\r\n\r\n // Performance telemetry client\r\n protected readonly performanceClient: IPerformanceClient;\r\n\r\n // Event handler\r\n private readonly eventHandler: EventHandler;\r\n\r\n // Crypto interface implementation\r\n protected readonly browserCrypto: ICrypto;\r\n\r\n // Flag to indicate if in browser environment\r\n protected isBrowserEnvironment: boolean;\r\n\r\n // Flag representing whether or not the initialize API has been called and completed\r\n protected initialized: boolean = false;\r\n\r\n constructor(operatingContext: UnknownOperatingContext) {\r\n this.operatingContext = operatingContext;\r\n\r\n this.isBrowserEnvironment =\r\n this.operatingContext.isBrowserEnvironment();\r\n\r\n this.config = operatingContext.getConfig();\r\n\r\n this.logger = operatingContext.getLogger();\r\n\r\n // Initialize performance client\r\n this.performanceClient = this.config.telemetry.client;\r\n\r\n // Initialize the crypto class.\r\n this.browserCrypto = this.isBrowserEnvironment\r\n ? new CryptoOps(this.logger, this.performanceClient)\r\n : DEFAULT_CRYPTO_IMPLEMENTATION;\r\n\r\n this.eventHandler = new EventHandler(this.logger);\r\n\r\n // Initialize the browser storage class.\r\n this.browserStorage = this.isBrowserEnvironment\r\n ? new BrowserCacheManager(\r\n this.config.auth.clientId,\r\n this.config.cache,\r\n this.browserCrypto,\r\n this.logger,\r\n this.performanceClient,\r\n this.eventHandler,\r\n undefined\r\n )\r\n : DEFAULT_BROWSER_CACHE_MANAGER(\r\n this.config.auth.clientId,\r\n this.logger,\r\n this.performanceClient,\r\n this.eventHandler\r\n );\r\n }\r\n getBrowserStorage(): BrowserCacheManager {\r\n return this.browserStorage;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n getAccount(accountFilter: AccountFilter): AccountInfo | null {\r\n return null;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n getAccountByHomeId(homeAccountId: string): AccountInfo | null {\r\n return null;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n getAccountByLocalId(localAccountId: string): AccountInfo | null {\r\n return null;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n getAccountByUsername(username: string): AccountInfo | null {\r\n return null;\r\n }\r\n getAllAccounts(): AccountInfo[] {\r\n return [];\r\n }\r\n initialize(): Promise {\r\n this.initialized = true;\r\n return Promise.resolve();\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n acquireTokenPopup(request: PopupRequest): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as Promise;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n acquireTokenRedirect(request: RedirectRequest): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return Promise.resolve();\r\n }\r\n acquireTokenSilent(\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n silentRequest: SilentRequest\r\n ): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as Promise;\r\n }\r\n acquireTokenByCode(\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n request: AuthorizationCodeRequest\r\n ): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as Promise;\r\n }\r\n acquireTokenNative(\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n request:\r\n | PopupRequest\r\n | SilentRequest\r\n | Partial<\r\n Omit<\r\n CommonAuthorizationUrlRequest,\r\n | \"responseMode\"\r\n | \"earJwk\"\r\n | \"codeChallenge\"\r\n | \"codeChallengeMethod\"\r\n | \"requestedClaimsHash\"\r\n | \"platformBroker\"\r\n >\r\n >,\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n apiId: ApiId,\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n accountId?: string | undefined\r\n ): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as Promise;\r\n }\r\n acquireTokenByRefreshToken(\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n commonRequest: CommonSilentFlowRequest,\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n silentRequest: SilentRequest\r\n ): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as Promise;\r\n }\r\n addEventCallback(\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n callback: EventCallbackFunction,\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n eventTypes?: Array\r\n ): string | null {\r\n return null;\r\n }\r\n removeEventCallback(\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n callbackId: string\r\n ): void {}\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n addPerformanceCallback(callback: PerformanceCallbackFunction): string {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return \"\";\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n removePerformanceCallback(callbackId: string): boolean {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return true;\r\n }\r\n enableAccountStorageEvents(): void {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n }\r\n disableAccountStorageEvents(): void {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n }\r\n\r\n handleRedirectPromise(\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n hash?: string | undefined\r\n ): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n return Promise.resolve(null);\r\n }\r\n loginPopup(\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n request?: PopupRequest | undefined\r\n ): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as Promise;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n loginRedirect(request?: RedirectRequest | undefined): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as Promise;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n logout(logoutRequest?: EndSessionRequest | undefined): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as Promise;\r\n }\r\n logoutRedirect(\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n logoutRequest?: EndSessionRequest | undefined\r\n ): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as Promise;\r\n }\r\n logoutPopup(\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n logoutRequest?: EndSessionPopupRequest | undefined\r\n ): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as Promise;\r\n }\r\n ssoSilent(\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n request: Partial<\r\n Omit<\r\n CommonAuthorizationUrlRequest,\r\n | \"responseMode\"\r\n | \"earJwk\"\r\n | \"codeChallenge\"\r\n | \"codeChallengeMethod\"\r\n | \"requestedClaimsHash\"\r\n | \"platformBroker\"\r\n >\r\n >\r\n ): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as Promise;\r\n }\r\n getTokenCache(): ITokenCache {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as ITokenCache;\r\n }\r\n getLogger(): Logger {\r\n return this.logger;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n setLogger(logger: Logger): void {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n setActiveAccount(account: AccountInfo | null): void {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n }\r\n getActiveAccount(): AccountInfo | null {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return null;\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n initializeWrapperLibrary(sku: WrapperSKU, version: string): void {\r\n this.browserStorage.setWrapperMetadata(sku, version);\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n setNavigationClient(navigationClient: INavigationClient): void {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n }\r\n getConfiguration(): BrowserConfiguration {\r\n return this.config;\r\n }\r\n isBrowserEnv(): boolean {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return true;\r\n }\r\n getBrowserCrypto(): ICrypto {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as ICrypto;\r\n }\r\n getPerformanceClient(): IPerformanceClient {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as IPerformanceClient;\r\n }\r\n getRedirectResponse(): Map> {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n return {} as Map>;\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n async clearCache(logoutRequest?: ClearCacheRequest): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n }\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n async hydrateCache(\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n result: AuthenticationResult,\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n request:\r\n | SilentRequest\r\n | SsoSilentRequest\r\n | RedirectRequest\r\n | PopupRequest\r\n ): Promise {\r\n blockAPICallsBeforeInitialize(this.initialized);\r\n blockNonBrowserEnvironment();\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { BaseOperatingContext } from \"./BaseOperatingContext.js\";\r\n\r\nexport class UnknownOperatingContext extends BaseOperatingContext {\r\n /*\r\n * TODO: Once we have determine the bundling code return here to specify the name of the bundle\r\n * containing the implementation for this operating context\r\n */\r\n static readonly MODULE_NAME: string = \"\";\r\n\r\n /**\r\n * Unique identifier for the operating context\r\n */\r\n static readonly ID: string = \"UnknownOperatingContext\";\r\n\r\n /**\r\n * Returns the unique identifier for this operating context\r\n * @returns string\r\n */\r\n getId(): string {\r\n return UnknownOperatingContext.ID;\r\n }\r\n\r\n /**\r\n * Return the module name. Intended for use with import() to enable dynamic import\r\n * of the implementation associated with this operating context\r\n * @returns\r\n */\r\n getModuleName(): string {\r\n return UnknownOperatingContext.MODULE_NAME;\r\n }\r\n\r\n /**\r\n * Checks whether the operating context is available.\r\n * Confirms that the code is running a browser rather. This is required.\r\n * @returns Promise indicating whether this operating context is currently available.\r\n */\r\n async initialize(): Promise {\r\n /**\r\n * This operating context is in use when we have not checked for what the operating context is.\r\n * The context is unknown until we check it.\r\n */\r\n return true;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { ITokenCache } from \"../cache/ITokenCache.js\";\r\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\r\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\r\nimport { PopupRequest } from \"../request/PopupRequest.js\";\r\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\r\nimport { SilentRequest } from \"../request/SilentRequest.js\";\r\nimport { WrapperSKU } from \"../utils/BrowserConstants.js\";\r\nimport { IPublicClientApplication } from \"./IPublicClientApplication.js\";\r\nimport { IController } from \"../controllers/IController.js\";\r\nimport {\r\n PerformanceCallbackFunction,\r\n AccountInfo,\r\n AccountFilter,\r\n Logger,\r\n} from \"@azure/msal-common/browser\";\r\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\r\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\r\nimport * as ControllerFactory from \"../controllers/ControllerFactory.js\";\r\nimport {\r\n BrowserConfiguration,\r\n Configuration,\r\n} from \"../config/Configuration.js\";\r\nimport { EventCallbackFunction } from \"../event/EventMessage.js\";\r\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { UnknownOperatingContextController } from \"../controllers/UnknownOperatingContextController.js\";\r\nimport { UnknownOperatingContext } from \"../operatingcontext/UnknownOperatingContext.js\";\r\nimport { EventType } from \"../event/EventType.js\";\r\n\r\n/**\r\n * PublicClientNext is an early look at the planned implementation of PublicClientApplication in the next major version of MSAL.js.\r\n * It contains support for multiple API implementations based on the runtime environment that it is running in.\r\n *\r\n * The goals of these changes are to provide a clean separation of behavior between different operating contexts (Nested App Auth, Platform Brokers, Plain old Browser, etc.)\r\n * while still providing a consistent API surface for developers.\r\n *\r\n * Please use PublicClientApplication for any prod/real-world scenarios.\r\n * Note: PublicClientNext is experimental and subject to breaking changes without following semver\r\n *\r\n */\r\nexport class PublicClientNext implements IPublicClientApplication {\r\n /*\r\n * Definite assignment assertion used below\r\n * https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#definite-assignment-assertions\r\n */\r\n protected controller!: IController;\r\n protected configuration: Configuration;\r\n\r\n public static async createPublicClientApplication(\r\n configuration: Configuration\r\n ): Promise {\r\n const controller = await ControllerFactory.createController(\r\n configuration\r\n );\r\n let pca;\r\n if (controller !== null) {\r\n pca = new PublicClientNext(configuration, controller);\r\n } else {\r\n pca = new PublicClientNext(configuration);\r\n }\r\n return pca;\r\n }\r\n\r\n /**\r\n * @constructor\r\n * Constructor for the PublicClientNext used to instantiate the PublicClientNext object\r\n *\r\n * Important attributes in the Configuration object for auth are:\r\n * - clientID: the application ID of your application. You can obtain one by registering your application with our Application registration portal : https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredAppsPreview\r\n * - authority: the authority URL for your application.\r\n * - redirect_uri: the uri of your application registered in the portal.\r\n *\r\n * In Azure AD, authority is a URL indicating the Azure active directory that MSAL uses to obtain tokens.\r\n * It is of the form https://login.microsoftonline.com/{Enter_the_Tenant_Info_Here}\r\n * If your application supports Accounts in one organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with the Tenant Id or Tenant name (for example, contoso.microsoft.com).\r\n * If your application supports Accounts in any organizational directory, replace \"Enter_the_Tenant_Info_Here\" value with organizations.\r\n * If your application supports Accounts in any organizational directory and personal Microsoft accounts, replace \"Enter_the_Tenant_Info_Here\" value with common.\r\n * To restrict support to Personal Microsoft accounts only, replace \"Enter_the_Tenant_Info_Here\" value with consumers.\r\n *\r\n * In Azure B2C, authority is of the form https://{instance}/tfp/{tenant}/{policyName}/\r\n * Full B2C functionality will be available in this library in future versions.\r\n *\r\n * @param configuration Object for the MSAL PublicClientApplication instance\r\n * @param IController Optional parameter to explictly set the controller. (Will be removed when we remove public constructor)\r\n */\r\n private constructor(\r\n configuration: Configuration,\r\n controller?: IController\r\n ) {\r\n this.configuration = configuration;\r\n if (controller) {\r\n this.controller = controller;\r\n } else {\r\n const operatingContext = new UnknownOperatingContext(configuration);\r\n this.controller = new UnknownOperatingContextController(\r\n operatingContext\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Initializer function to perform async startup tasks such as connecting to WAM extension\r\n */\r\n async initialize(): Promise {\r\n if (this.controller instanceof UnknownOperatingContextController) {\r\n const result = await ControllerFactory.createController(\r\n this.configuration\r\n );\r\n if (result !== null) {\r\n this.controller = result;\r\n }\r\n return this.controller.initialize();\r\n }\r\n return Promise.resolve();\r\n }\r\n\r\n /**\r\n * Use when you want to obtain an access_token for your API via opening a popup window in the user's browser\r\n *\r\n * @param request\r\n *\r\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\r\n */\r\n async acquireTokenPopup(\r\n request: PopupRequest\r\n ): Promise {\r\n return this.controller.acquireTokenPopup(request);\r\n }\r\n\r\n /**\r\n * Use when you want to obtain an access_token for your API by redirecting the user's browser window to the authorization endpoint. This function redirects\r\n * the page, so any code that follows this function will not execute.\r\n *\r\n * IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current\r\n * browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.\r\n *\r\n * @param request\r\n */\r\n acquireTokenRedirect(request: RedirectRequest): Promise {\r\n return this.controller.acquireTokenRedirect(request);\r\n }\r\n\r\n /**\r\n * Silently acquire an access token for a given set of scopes. Returns currently processing promise if parallel requests are made.\r\n *\r\n * @param {@link (SilentRequest:type)}\r\n * @returns {Promise.} - a promise that is fulfilled when this function has completed, or rejected if an error was raised. Returns the {@link AuthenticationResult} object\r\n */\r\n acquireTokenSilent(\r\n silentRequest: SilentRequest\r\n ): Promise {\r\n return this.controller.acquireTokenSilent(silentRequest);\r\n }\r\n\r\n /**\r\n * This function redeems an authorization code (passed as code) from the eSTS token endpoint.\r\n * This authorization code should be acquired server-side using a confidential client to acquire a spa_code.\r\n * This API is not indended for normal authorization code acquisition and redemption.\r\n *\r\n * Redemption of this authorization code will not require PKCE, as it was acquired by a confidential client.\r\n *\r\n * @param request {@link AuthorizationCodeRequest}\r\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\r\n */\r\n acquireTokenByCode(\r\n request: AuthorizationCodeRequest\r\n ): Promise {\r\n return this.controller.acquireTokenByCode(request);\r\n }\r\n\r\n /**\r\n * Adds event callbacks to array\r\n * @param callback\r\n */\r\n addEventCallback(\r\n callback: EventCallbackFunction,\r\n eventTypes?: Array\r\n ): string | null {\r\n return this.controller.addEventCallback(callback, eventTypes);\r\n }\r\n\r\n /**\r\n * Removes callback with provided id from callback array\r\n * @param callbackId\r\n */\r\n removeEventCallback(callbackId: string): void {\r\n return this.controller.removeEventCallback(callbackId);\r\n }\r\n\r\n /**\r\n * Registers a callback to receive performance events.\r\n *\r\n * @param {PerformanceCallbackFunction} callback\r\n * @returns {string}\r\n */\r\n addPerformanceCallback(callback: PerformanceCallbackFunction): string {\r\n return this.controller.addPerformanceCallback(callback);\r\n }\r\n\r\n /**\r\n * Removes a callback registered with addPerformanceCallback.\r\n *\r\n * @param {string} callbackId\r\n * @returns {boolean}\r\n */\r\n removePerformanceCallback(callbackId: string): boolean {\r\n return this.controller.removePerformanceCallback(callbackId);\r\n }\r\n\r\n /**\r\n * Adds event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\r\n */\r\n enableAccountStorageEvents(): void {\r\n this.controller.enableAccountStorageEvents();\r\n }\r\n\r\n /**\r\n * Removes event listener that emits an event when a user account is added or removed from localstorage in a different browser tab or window\r\n */\r\n disableAccountStorageEvents(): void {\r\n this.controller.disableAccountStorageEvents();\r\n }\r\n\r\n /**\r\n * Returns the first account found in the cache that matches the account filter passed in.\r\n * @param accountFilter\r\n * @returns The first account found in the cache matching the provided filter or null if no account could be found.\r\n */\r\n getAccount(accountFilter: AccountFilter): AccountInfo | null {\r\n return this.controller.getAccount(accountFilter);\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching homeAccountId.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found\r\n * @param homeAccountId\r\n * @returns The account object stored in MSAL\r\n * @deprecated - Use getAccount instead\r\n */\r\n getAccountByHomeId(homeAccountId: string): AccountInfo | null {\r\n return this.controller.getAccountByHomeId(homeAccountId);\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching localAccountId.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found\r\n * @param localAccountId\r\n * @returns The account object stored in MSAL\r\n * @deprecated - Use getAccount instead\r\n */\r\n getAccountByLocalId(localId: string): AccountInfo | null {\r\n return this.controller.getAccountByLocalId(localId);\r\n }\r\n\r\n /**\r\n * Returns the signed in account matching username.\r\n * (the account object is created at the time of successful login)\r\n * or null when no matching account is found.\r\n * This API is provided for convenience but getAccountById should be used for best reliability\r\n * @param userName\r\n * @returns The account object stored in MSAL\r\n * @deprecated - Use getAccount instead\r\n */\r\n getAccountByUsername(userName: string): AccountInfo | null {\r\n return this.controller.getAccountByUsername(userName);\r\n }\r\n\r\n /**\r\n * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.\r\n * @param accountFilter - (Optional) filter to narrow down the accounts returned\r\n * @returns Array of AccountInfo objects in cache\r\n */\r\n getAllAccounts(accountFilter?: AccountFilter): AccountInfo[] {\r\n return this.controller.getAllAccounts(accountFilter);\r\n }\r\n\r\n /**\r\n * Event handler function which allows users to fire events after the PublicClientApplication object\r\n * has loaded during redirect flows. This should be invoked on all page loads involved in redirect\r\n * auth flows.\r\n * @param hash Hash to process. Defaults to the current value of window.location.hash. Only needs to be provided explicitly if the response to be handled is not contained in the current value.\r\n * @returns Token response or null. If the return value is null, then no auth redirect was detected.\r\n */\r\n handleRedirectPromise(\r\n hash?: string | undefined\r\n ): Promise {\r\n return this.controller.handleRedirectPromise(hash);\r\n }\r\n\r\n /**\r\n * Use when initiating the login process via opening a popup window in the user's browser\r\n *\r\n * @param request\r\n *\r\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\r\n */\r\n loginPopup(\r\n request?: PopupRequest | undefined\r\n ): Promise {\r\n return this.controller.loginPopup(request);\r\n }\r\n\r\n /**\r\n * Use when initiating the login process by redirecting the user's browser to the authorization endpoint. This function redirects the page, so\r\n * any code that follows this function will not execute.\r\n *\r\n * IMPORTANT: It is NOT recommended to have code that is dependent on the resolution of the Promise. This function will navigate away from the current\r\n * browser window. It currently returns a Promise in order to reflect the asynchronous nature of the code running in this function.\r\n *\r\n * @param request\r\n */\r\n loginRedirect(request?: RedirectRequest | undefined): Promise {\r\n return this.controller.loginRedirect(request);\r\n }\r\n\r\n /**\r\n * Deprecated logout function. Use logoutRedirect or logoutPopup instead\r\n * @param logoutRequest\r\n * @deprecated\r\n */\r\n logout(logoutRequest?: EndSessionRequest): Promise {\r\n return this.controller.logout(logoutRequest);\r\n }\r\n\r\n /**\r\n * Use to log out the current user, and redirect the user to the postLogoutRedirectUri.\r\n * Default behaviour is to redirect the user to `window.location.href`.\r\n * @param logoutRequest\r\n */\r\n logoutRedirect(logoutRequest?: EndSessionRequest): Promise {\r\n return this.controller.logoutRedirect(logoutRequest);\r\n }\r\n\r\n /**\r\n * Clears local cache for the current user then opens a popup window prompting the user to sign-out of the server\r\n * @param logoutRequest\r\n */\r\n logoutPopup(logoutRequest?: EndSessionRequest): Promise {\r\n return this.controller.logoutPopup(logoutRequest);\r\n }\r\n\r\n /**\r\n * This function uses a hidden iframe to fetch an authorization code from the eSTS. There are cases where this may not work:\r\n * - Any browser using a form of Intelligent Tracking Prevention\r\n * - If there is not an established session with the service\r\n *\r\n * In these cases, the request must be done inside a popup or full frame redirect.\r\n *\r\n * For the cases where interaction is required, you cannot send a request with prompt=none.\r\n *\r\n * If your refresh token has expired, you can use this function to fetch a new set of tokens silently as long as\r\n * you session on the server still exists.\r\n * @param request {@link SsoSilentRequest}\r\n *\r\n * @returns A promise that is fulfilled when this function has completed, or rejected if an error was raised.\r\n */\r\n ssoSilent(request: SsoSilentRequest): Promise {\r\n return this.controller.ssoSilent(request);\r\n }\r\n\r\n /**\r\n * Gets the token cache for the application.\r\n */\r\n getTokenCache(): ITokenCache {\r\n return this.controller.getTokenCache();\r\n }\r\n\r\n /**\r\n * Returns the logger instance\r\n */\r\n getLogger(): Logger {\r\n return this.controller.getLogger();\r\n }\r\n\r\n /**\r\n * Replaces the default logger set in configurations with new Logger with new configurations\r\n * @param logger Logger instance\r\n */\r\n setLogger(logger: Logger): void {\r\n this.controller.setLogger(logger);\r\n }\r\n\r\n /**\r\n * Sets the account to use as the active account. If no account is passed to the acquireToken APIs, then MSAL will use this active account.\r\n * @param account\r\n */\r\n setActiveAccount(account: AccountInfo | null): void {\r\n this.controller.setActiveAccount(account);\r\n }\r\n\r\n /**\r\n * Gets the currently active account\r\n */\r\n getActiveAccount(): AccountInfo | null {\r\n return this.controller.getActiveAccount();\r\n }\r\n\r\n /**\r\n * Called by wrapper libraries (Angular & React) to set SKU and Version passed down to telemetry, logger, etc.\r\n * @param sku\r\n * @param version\r\n */\r\n initializeWrapperLibrary(sku: WrapperSKU, version: string): void {\r\n return this.controller.initializeWrapperLibrary(sku, version);\r\n }\r\n\r\n /**\r\n * Sets navigation client\r\n * @param navigationClient\r\n */\r\n setNavigationClient(navigationClient: INavigationClient): void {\r\n this.controller.setNavigationClient(navigationClient);\r\n }\r\n\r\n /**\r\n * Returns the configuration object\r\n * @internal\r\n */\r\n getConfiguration(): BrowserConfiguration {\r\n return this.controller.getConfiguration();\r\n }\r\n\r\n /**\r\n * Hydrates cache with the tokens and account in the AuthenticationResult object\r\n * @param result\r\n * @param request - The request object that was used to obtain the AuthenticationResult\r\n * @returns\r\n */\r\n async hydrateCache(\r\n result: AuthenticationResult,\r\n request:\r\n | SilentRequest\r\n | SsoSilentRequest\r\n | RedirectRequest\r\n | PopupRequest\r\n ): Promise {\r\n return this.controller.hydrateCache(result, request);\r\n }\r\n\r\n /**\r\n * Clears tokens and account from the browser cache.\r\n * @param logoutRequest\r\n */\r\n clearCache(logoutRequest?: ClearCacheRequest): Promise {\r\n return this.controller.clearCache(logoutRequest);\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n AccountFilter,\r\n AccountInfo,\r\n Logger,\r\n PerformanceCallbackFunction,\r\n} from \"@azure/msal-common/browser\";\r\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\r\nimport { PopupRequest } from \"../request/PopupRequest.js\";\r\nimport { SilentRequest } from \"../request/SilentRequest.js\";\r\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\r\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\r\nimport {\r\n BrowserConfigurationAuthErrorCodes,\r\n createBrowserConfigurationAuthError,\r\n} from \"../error/BrowserConfigurationAuthError.js\";\r\nimport { WrapperSKU } from \"../utils/BrowserConstants.js\";\r\nimport { INavigationClient } from \"../navigation/INavigationClient.js\";\r\nimport { EndSessionPopupRequest } from \"../request/EndSessionPopupRequest.js\";\r\nimport { ITokenCache } from \"../cache/ITokenCache.js\";\r\nimport { AuthorizationCodeRequest } from \"../request/AuthorizationCodeRequest.js\";\r\nimport { BrowserConfiguration } from \"../config/Configuration.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\nimport { EventCallbackFunction } from \"../event/EventMessage.js\";\r\nimport { ClearCacheRequest } from \"../request/ClearCacheRequest.js\";\r\nimport { InitializeApplicationRequest } from \"../request/InitializeApplicationRequest.js\";\r\nimport { EventType } from \"../event/EventType.js\";\r\n\r\nexport interface IPublicClientApplication {\r\n // TODO: Make request mandatory in the next major version?\r\n initialize(request?: InitializeApplicationRequest): Promise;\r\n acquireTokenPopup(request: PopupRequest): Promise;\r\n acquireTokenRedirect(request: RedirectRequest): Promise;\r\n acquireTokenSilent(\r\n silentRequest: SilentRequest\r\n ): Promise;\r\n acquireTokenByCode(\r\n request: AuthorizationCodeRequest\r\n ): Promise;\r\n addEventCallback(\r\n callback: EventCallbackFunction,\r\n eventTypes?: Array\r\n ): string | null;\r\n removeEventCallback(callbackId: string): void;\r\n addPerformanceCallback(callback: PerformanceCallbackFunction): string;\r\n removePerformanceCallback(callbackId: string): boolean;\r\n enableAccountStorageEvents(): void;\r\n disableAccountStorageEvents(): void;\r\n getAccount(accountFilter: AccountFilter): AccountInfo | null;\r\n getAccountByHomeId(homeAccountId: string): AccountInfo | null;\r\n getAccountByLocalId(localId: string): AccountInfo | null;\r\n getAccountByUsername(userName: string): AccountInfo | null;\r\n getAllAccounts(): AccountInfo[];\r\n handleRedirectPromise(hash?: string): Promise;\r\n loginPopup(request?: PopupRequest): Promise;\r\n loginRedirect(request?: RedirectRequest): Promise;\r\n logout(logoutRequest?: EndSessionRequest): Promise;\r\n logoutRedirect(logoutRequest?: EndSessionRequest): Promise;\r\n logoutPopup(logoutRequest?: EndSessionPopupRequest): Promise;\r\n ssoSilent(request: SsoSilentRequest): Promise;\r\n getTokenCache(): ITokenCache;\r\n getLogger(): Logger;\r\n setLogger(logger: Logger): void;\r\n setActiveAccount(account: AccountInfo | null): void;\r\n getActiveAccount(): AccountInfo | null;\r\n initializeWrapperLibrary(sku: WrapperSKU, version: string): void;\r\n setNavigationClient(navigationClient: INavigationClient): void;\r\n /** @internal */\r\n getConfiguration(): BrowserConfiguration;\r\n hydrateCache(\r\n result: AuthenticationResult,\r\n request:\r\n | SilentRequest\r\n | SsoSilentRequest\r\n | RedirectRequest\r\n | PopupRequest\r\n ): Promise;\r\n clearCache(logoutRequest?: ClearCacheRequest): Promise;\r\n}\r\n\r\nexport const stubbedPublicClientApplication: IPublicClientApplication = {\r\n initialize: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n acquireTokenPopup: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n acquireTokenRedirect: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n acquireTokenSilent: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n acquireTokenByCode: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n getAllAccounts: () => {\r\n return [];\r\n },\r\n getAccount: () => {\r\n return null;\r\n },\r\n getAccountByHomeId: () => {\r\n return null;\r\n },\r\n getAccountByUsername: () => {\r\n return null;\r\n },\r\n getAccountByLocalId: () => {\r\n return null;\r\n },\r\n handleRedirectPromise: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n loginPopup: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n loginRedirect: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n logout: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n logoutRedirect: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n logoutPopup: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n ssoSilent: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n addEventCallback: () => {\r\n return null;\r\n },\r\n removeEventCallback: () => {\r\n return;\r\n },\r\n addPerformanceCallback: () => {\r\n return \"\";\r\n },\r\n removePerformanceCallback: () => {\r\n return false;\r\n },\r\n enableAccountStorageEvents: () => {\r\n return;\r\n },\r\n disableAccountStorageEvents: () => {\r\n return;\r\n },\r\n getTokenCache: () => {\r\n throw createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n );\r\n },\r\n getLogger: () => {\r\n throw createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n );\r\n },\r\n setLogger: () => {\r\n return;\r\n },\r\n setActiveAccount: () => {\r\n return;\r\n },\r\n getActiveAccount: () => {\r\n return null;\r\n },\r\n initializeWrapperLibrary: () => {\r\n return;\r\n },\r\n setNavigationClient: () => {\r\n return;\r\n },\r\n getConfiguration: () => {\r\n throw createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n );\r\n },\r\n hydrateCache: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n clearCache: () => {\r\n return Promise.reject(\r\n createBrowserConfigurationAuthError(\r\n BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled\r\n )\r\n );\r\n },\r\n};\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { AuthError, AccountInfo } from \"@azure/msal-common/browser\";\r\nimport { EventType } from \"./EventType.js\";\r\nimport {\r\n InteractionStatus,\r\n InteractionType,\r\n} from \"../utils/BrowserConstants.js\";\r\nimport { PopupRequest } from \"../request/PopupRequest.js\";\r\nimport { RedirectRequest } from \"../request/RedirectRequest.js\";\r\nimport { SilentRequest } from \"../request/SilentRequest.js\";\r\nimport { SsoSilentRequest } from \"../request/SsoSilentRequest.js\";\r\nimport { EndSessionRequest } from \"../request/EndSessionRequest.js\";\r\nimport { AuthenticationResult } from \"../response/AuthenticationResult.js\";\r\n\r\nexport type EventMessage = {\r\n eventType: EventType;\r\n interactionType: InteractionType | null;\r\n payload: EventPayload;\r\n error: EventError;\r\n timestamp: number;\r\n};\r\n\r\nexport type PopupEvent = {\r\n popupWindow: Window;\r\n};\r\n\r\n/**\r\n * Payload for the BrokerConnectionEstablished event\r\n */\r\nexport type BrokerConnectionEvent = {\r\n /**\r\n * The origin of the broker that is connected to the client\r\n */\r\n pairwiseBrokerOrigin: string;\r\n};\r\n\r\nexport type EventPayload =\r\n | AccountInfo\r\n | PopupRequest\r\n | RedirectRequest\r\n | SilentRequest\r\n | SsoSilentRequest\r\n | EndSessionRequest\r\n | AuthenticationResult\r\n | PopupEvent\r\n | BrokerConnectionEvent\r\n | null;\r\n\r\nexport type EventError = AuthError | Error | null;\r\n\r\nexport type EventCallbackFunction = (message: EventMessage) => void;\r\n\r\nexport class EventMessageUtils {\r\n /**\r\n * Gets interaction status from event message\r\n * @param message\r\n * @param currentStatus\r\n */\r\n static getInteractionStatusFromEvent(\r\n message: EventMessage,\r\n currentStatus?: InteractionStatus\r\n ): InteractionStatus | null {\r\n switch (message.eventType) {\r\n case EventType.LOGIN_START:\r\n return InteractionStatus.Login;\r\n case EventType.SSO_SILENT_START:\r\n return InteractionStatus.SsoSilent;\r\n case EventType.ACQUIRE_TOKEN_START:\r\n if (\r\n message.interactionType === InteractionType.Redirect ||\r\n message.interactionType === InteractionType.Popup\r\n ) {\r\n return InteractionStatus.AcquireToken;\r\n }\r\n break;\r\n case EventType.HANDLE_REDIRECT_START:\r\n return InteractionStatus.HandleRedirect;\r\n case EventType.LOGOUT_START:\r\n return InteractionStatus.Logout;\r\n case EventType.SSO_SILENT_SUCCESS:\r\n case EventType.SSO_SILENT_FAILURE:\r\n if (\r\n currentStatus &&\r\n currentStatus !== InteractionStatus.SsoSilent\r\n ) {\r\n // Prevent this event from clearing any status other than ssoSilent\r\n break;\r\n }\r\n return InteractionStatus.None;\r\n case EventType.LOGOUT_END:\r\n if (\r\n currentStatus &&\r\n currentStatus !== InteractionStatus.Logout\r\n ) {\r\n // Prevent this event from clearing any status other than logout\r\n break;\r\n }\r\n return InteractionStatus.None;\r\n case EventType.HANDLE_REDIRECT_END:\r\n if (\r\n currentStatus &&\r\n currentStatus !== InteractionStatus.HandleRedirect\r\n ) {\r\n // Prevent this event from clearing any status other than handleRedirect\r\n break;\r\n }\r\n return InteractionStatus.None;\r\n case EventType.LOGIN_SUCCESS:\r\n case EventType.LOGIN_FAILURE:\r\n case EventType.ACQUIRE_TOKEN_SUCCESS:\r\n case EventType.ACQUIRE_TOKEN_FAILURE:\r\n case EventType.RESTORE_FROM_BFCACHE:\r\n if (\r\n message.interactionType === InteractionType.Redirect ||\r\n message.interactionType === InteractionType.Popup\r\n ) {\r\n if (\r\n currentStatus &&\r\n currentStatus !== InteractionStatus.Login &&\r\n currentStatus !== InteractionStatus.AcquireToken\r\n ) {\r\n // Prevent this event from clearing any status other than login or acquireToken\r\n break;\r\n }\r\n return InteractionStatus.None;\r\n }\r\n break;\r\n default:\r\n break;\r\n }\r\n return null;\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport { CryptoOps } from \"./CryptoOps.js\";\r\nimport {\r\n ClientAuthError,\r\n ClientAuthErrorCodes,\r\n Logger,\r\n LoggerOptions,\r\n PopTokenGenerator,\r\n SignedHttpRequestParameters,\r\n} from \"@azure/msal-common/browser\";\r\nimport { version, name } from \"../packageMetadata.js\";\r\n\r\nexport type SignedHttpRequestOptions = {\r\n loggerOptions: LoggerOptions;\r\n};\r\n\r\nexport class SignedHttpRequest {\r\n private popTokenGenerator: PopTokenGenerator;\r\n private cryptoOps: CryptoOps;\r\n private shrParameters: SignedHttpRequestParameters;\r\n private logger: Logger;\r\n\r\n constructor(\r\n shrParameters: SignedHttpRequestParameters,\r\n shrOptions?: SignedHttpRequestOptions\r\n ) {\r\n const loggerOptions = (shrOptions && shrOptions.loggerOptions) || {};\r\n this.logger = new Logger(loggerOptions, name, version);\r\n this.cryptoOps = new CryptoOps(this.logger);\r\n this.popTokenGenerator = new PopTokenGenerator(this.cryptoOps);\r\n this.shrParameters = shrParameters;\r\n }\r\n\r\n /**\r\n * Generates and caches a keypair for the given request options.\r\n * @returns Public key digest, which should be sent to the token issuer.\r\n */\r\n async generatePublicKeyThumbprint(): Promise {\r\n const { kid } = await this.popTokenGenerator.generateKid(\r\n this.shrParameters\r\n );\r\n\r\n return kid;\r\n }\r\n\r\n /**\r\n * Generates a signed http request for the given payload with the given key.\r\n * @param payload Payload to sign (e.g. access token)\r\n * @param publicKeyThumbprint Public key digest (from generatePublicKeyThumbprint API)\r\n * @param claims Additional claims to include/override in the signed JWT\r\n * @returns Pop token signed with the corresponding private key\r\n */\r\n async signRequest(\r\n payload: string,\r\n publicKeyThumbprint: string,\r\n claims?: object\r\n ): Promise {\r\n return this.popTokenGenerator.signPayload(\r\n payload,\r\n publicKeyThumbprint,\r\n this.shrParameters,\r\n claims\r\n );\r\n }\r\n\r\n /**\r\n * Removes cached keys from browser for given public key thumbprint\r\n * @param publicKeyThumbprint Public key digest (from generatePublicKeyThumbprint API)\r\n * @returns If keys are properly deleted\r\n */\r\n async removeKeys(publicKeyThumbprint: string): Promise {\r\n return this.cryptoOps\r\n .removeTokenBindingKey(publicKeyThumbprint)\r\n .then(() => true)\r\n .catch((error) => {\r\n /*\r\n * @deprecated - To maintain public API signature, we return false if the error is due to the key still being present in indexedDB.\r\n */\r\n if (\r\n error instanceof ClientAuthError &&\r\n error.errorCode ===\r\n ClientAuthErrorCodes.bindingKeyNotRemoved\r\n ) {\r\n return false;\r\n }\r\n\r\n throw error;\r\n });\r\n }\r\n}\r\n", "/*\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License.\r\n */\r\n\r\nimport {\r\n Constants,\r\n InProgressPerformanceEvent,\r\n IPerformanceClient,\r\n Logger,\r\n PerformanceClient,\r\n PerformanceEvent,\r\n PerformanceEvents,\r\n PreQueueEvent,\r\n SubMeasurement,\r\n} from \"@azure/msal-common/browser\";\r\nimport { Configuration } from \"../config/Configuration.js\";\r\nimport { name, version } from \"../packageMetadata.js\";\r\nimport { BrowserCacheLocation } from \"../utils/BrowserConstants.js\";\r\nimport * as BrowserCrypto from \"../crypto/BrowserCrypto.js\";\r\nimport { BROWSER_PERF_ENABLED_KEY } from \"../cache/CacheKeys.js\";\r\n\r\n/**\r\n * Returns browser performance measurement module if session flag is enabled. Returns undefined otherwise.\r\n */\r\nfunction getPerfMeasurementModule() {\r\n let sessionStorage: Storage | undefined;\r\n try {\r\n sessionStorage = window[BrowserCacheLocation.SessionStorage];\r\n const perfEnabled = sessionStorage?.getItem(BROWSER_PERF_ENABLED_KEY);\r\n if (Number(perfEnabled) === 1) {\r\n return import(\"./BrowserPerformanceMeasurement.js\");\r\n }\r\n // Mute errors if it's a non-browser environment or cookies are blocked.\r\n } catch (e) {}\r\n\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Returns boolean, indicating whether browser supports window.performance.now() function.\r\n */\r\nfunction supportsBrowserPerformanceNow(): boolean {\r\n return (\r\n typeof window !== \"undefined\" &&\r\n typeof window.performance !== \"undefined\" &&\r\n typeof window.performance.now === \"function\"\r\n );\r\n}\r\n\r\n/**\r\n * Returns event duration in milliseconds using window performance API if available. Returns undefined otherwise.\r\n * @param startTime {DOMHighResTimeStamp | undefined}\r\n * @returns {number | undefined}\r\n */\r\nfunction getPerfDurationMs(\r\n startTime: DOMHighResTimeStamp | undefined\r\n): number | undefined {\r\n if (!startTime || !supportsBrowserPerformanceNow()) {\r\n return undefined;\r\n }\r\n\r\n return Math.round(window.performance.now() - startTime);\r\n}\r\n\r\nexport class BrowserPerformanceClient\r\n extends PerformanceClient\r\n implements IPerformanceClient\r\n{\r\n constructor(\r\n configuration: Configuration,\r\n intFields?: Set,\r\n abbreviations?: Map\r\n ) {\r\n super(\r\n configuration.auth.clientId,\r\n configuration.auth.authority || `${Constants.DEFAULT_AUTHORITY}`,\r\n new Logger(\r\n configuration.system?.loggerOptions || {},\r\n name,\r\n version\r\n ),\r\n name,\r\n version,\r\n configuration.telemetry?.application || {\r\n appName: \"\",\r\n appVersion: \"\",\r\n },\r\n intFields,\r\n abbreviations\r\n );\r\n }\r\n\r\n generateId(): string {\r\n return BrowserCrypto.createNewGuid();\r\n }\r\n\r\n private getPageVisibility(): string | null {\r\n return document.visibilityState?.toString() || null;\r\n }\r\n\r\n private deleteIncompleteSubMeasurements(\r\n inProgressEvent: InProgressPerformanceEvent\r\n ): void {\r\n void getPerfMeasurementModule()?.then((module) => {\r\n const rootEvent = this.eventsByCorrelationId.get(\r\n inProgressEvent.event.correlationId\r\n );\r\n const isRootEvent =\r\n rootEvent &&\r\n rootEvent.eventId === inProgressEvent.event.eventId;\r\n const incompleteMeasurements: SubMeasurement[] = [];\r\n if (isRootEvent && rootEvent?.incompleteSubMeasurements) {\r\n rootEvent.incompleteSubMeasurements.forEach(\r\n (subMeasurement: SubMeasurement) => {\r\n incompleteMeasurements.push({ ...subMeasurement });\r\n }\r\n );\r\n }\r\n // Clean up remaining marks for incomplete sub-measurements\r\n module.BrowserPerformanceMeasurement.flushMeasurements(\r\n inProgressEvent.event.correlationId,\r\n incompleteMeasurements\r\n );\r\n });\r\n }\r\n\r\n /**\r\n * Starts measuring performance for a given operation. Returns a function that should be used to end the measurement.\r\n * Also captures browser page visibilityState.\r\n *\r\n * @param {PerformanceEvents} measureName\r\n * @param {?string} [correlationId]\r\n * @returns {((event?: Partial) => PerformanceEvent| null)}\r\n */\r\n startMeasurement(\r\n measureName: string,\r\n correlationId?: string\r\n ): InProgressPerformanceEvent {\r\n // Capture page visibilityState and then invoke start/end measurement\r\n const startPageVisibility = this.getPageVisibility();\r\n const inProgressEvent = super.startMeasurement(\r\n measureName,\r\n correlationId\r\n );\r\n const startTime: number | undefined = supportsBrowserPerformanceNow()\r\n ? window.performance.now()\r\n : undefined;\r\n\r\n const browserMeasurement = getPerfMeasurementModule()?.then(\r\n (module) => {\r\n return new module.BrowserPerformanceMeasurement(\r\n measureName,\r\n inProgressEvent.event.correlationId\r\n );\r\n }\r\n );\r\n void browserMeasurement?.then((measurement) =>\r\n measurement.startMeasurement()\r\n );\r\n\r\n return {\r\n ...inProgressEvent,\r\n end: (\r\n event?: Partial,\r\n error?: unknown\r\n ): PerformanceEvent | null => {\r\n const res = inProgressEvent.end(\r\n {\r\n ...event,\r\n startPageVisibility,\r\n endPageVisibility: this.getPageVisibility(),\r\n durationMs: getPerfDurationMs(startTime),\r\n },\r\n error\r\n );\r\n void browserMeasurement?.then((measurement) =>\r\n measurement.endMeasurement()\r\n );\r\n this.deleteIncompleteSubMeasurements(inProgressEvent);\r\n\r\n return res;\r\n },\r\n discard: () => {\r\n inProgressEvent.discard();\r\n void browserMeasurement?.then((measurement) =>\r\n measurement.flushMeasurement()\r\n );\r\n this.deleteIncompleteSubMeasurements(inProgressEvent);\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Adds pre-queue time to preQueueTimeByCorrelationId map.\r\n * @param {PerformanceEvents} eventName\r\n * @param {?string} correlationId\r\n * @returns\r\n */\r\n setPreQueueTime(\r\n eventName: PerformanceEvents,\r\n correlationId?: string\r\n ): void {\r\n if (!supportsBrowserPerformanceNow()) {\r\n this.logger.trace(\r\n `BrowserPerformanceClient: window performance API not available, unable to set telemetry queue time for ${eventName}`\r\n );\r\n return;\r\n }\r\n\r\n if (!correlationId) {\r\n this.logger.trace(\r\n `BrowserPerformanceClient: correlationId for ${eventName} not provided, unable to set telemetry queue time`\r\n );\r\n return;\r\n }\r\n\r\n const preQueueEvent: PreQueueEvent | undefined =\r\n this.preQueueTimeByCorrelationId.get(correlationId);\r\n /**\r\n * Manually complete queue measurement if there is an incomplete pre-queue event.\r\n * Incomplete pre-queue events are instrumentation bugs that should be fixed.\r\n */\r\n if (preQueueEvent) {\r\n this.logger.trace(\r\n `BrowserPerformanceClient: Incomplete pre-queue ${preQueueEvent.name} found`,\r\n correlationId\r\n );\r\n this.addQueueMeasurement(\r\n preQueueEvent.name,\r\n correlationId,\r\n undefined,\r\n true\r\n );\r\n }\r\n this.preQueueTimeByCorrelationId.set(correlationId, {\r\n name: eventName,\r\n time: window.performance.now(),\r\n });\r\n }\r\n\r\n /**\r\n * Calculates and adds queue time measurement for given performance event.\r\n *\r\n * @param {PerformanceEvents} eventName\r\n * @param {?string} correlationId\r\n * @param {?number} queueTime\r\n * @param {?boolean} manuallyCompleted - indicator for manually completed queue measurements\r\n * @returns\r\n */\r\n addQueueMeasurement(\r\n eventName: string,\r\n correlationId?: string,\r\n queueTime?: number,\r\n manuallyCompleted?: boolean\r\n ): void {\r\n if (!supportsBrowserPerformanceNow()) {\r\n this.logger.trace(\r\n `BrowserPerformanceClient: window performance API not available, unable to add queue measurement for ${eventName}`\r\n );\r\n return;\r\n }\r\n\r\n if (!correlationId) {\r\n this.logger.trace(\r\n `BrowserPerformanceClient: correlationId for ${eventName} not provided, unable to add queue measurement`\r\n );\r\n return;\r\n }\r\n\r\n const preQueueTime = super.getPreQueueTime(eventName, correlationId);\r\n if (!preQueueTime) {\r\n return;\r\n }\r\n\r\n const currentTime = window.performance.now();\r\n const resQueueTime =\r\n queueTime || super.calculateQueuedTime(preQueueTime, currentTime);\r\n\r\n return super.addQueueMeasurement(\r\n eventName,\r\n correlationId,\r\n resQueueTime,\r\n manuallyCompleted\r\n );\r\n }\r\n}\r\n"], "mappings": "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", "names": ["AuthErrorCodes.unexpectedError", "AuthErrorCodes.postRequestFailed", "ClientAuthErrorCodes.clientInfoDecodingError", "ClientAuthErrorCodes.clientInfoEmptyError", "ClientAuthErrorCodes.tokenParsingError", "ClientAuthErrorCodes.nullOrEmptyToken", "ClientAuthErrorCodes.endpointResolutionError", "ClientAuthErrorCodes.networkError", "ClientAuthErrorCodes.openIdConfigError", "ClientAuthErrorCodes.hashNotDeserialized", "ClientAuthErrorCodes.invalidState", "ClientAuthErrorCodes.stateMismatch", "ClientAuthErrorCodes.stateNotFound", "ClientAuthErrorCodes.nonceMismatch", "ClientAuthErrorCodes.authTimeNotFound", "ClientAuthErrorCodes.maxAgeTranspired", "ClientAuthErrorCodes.multipleMatchingTokens", "ClientAuthErrorCodes.multipleMatchingAccounts", "ClientAuthErrorCodes.multipleMatchingAppMetadata", "ClientAuthErrorCodes.requestCannotBeMade", "ClientAuthErrorCodes.cannotRemoveEmptyScope", "ClientAuthErrorCodes.cannotAppendScopeSet", "ClientAuthErrorCodes.emptyInputScopeSet", "ClientAuthErrorCodes.deviceCodePollingCancelled", "ClientAuthErrorCodes.deviceCodeExpired", "ClientAuthErrorCodes.deviceCodeUnknownError", "ClientAuthErrorCodes.noAccountInSilentRequest", "ClientAuthErrorCodes.invalidCacheRecord", "ClientAuthErrorCodes.invalidCacheEnvironment", "ClientAuthErrorCodes.noAccountFound", "ClientAuthErrorCodes.noCryptoObject", "ClientAuthErrorCodes.unexpectedCredentialType", "ClientAuthErrorCodes.invalidAssertion", "ClientAuthErrorCodes.invalidClientCredential", "ClientAuthErrorCodes.tokenRefreshRequired", "ClientAuthErrorCodes.userTimeoutReached", "ClientAuthErrorCodes.tokenClaimsCnfRequiredForSignedJwt", "ClientAuthErrorCodes.authorizationCodeMissingFromServerResponse", "ClientAuthErrorCodes.bindingKeyNotRemoved", "ClientAuthErrorCodes.endSessionEndpointNotSupported", "ClientAuthErrorCodes.keyIdMissing", "ClientAuthErrorCodes.noNetworkConnectivity", "ClientAuthErrorCodes.userCanceled", "ClientAuthErrorCodes.missingTenantIdError", "ClientAuthErrorCodes.methodNotImplemented", "ClientAuthErrorCodes.nestedAppAuthBridgeDisabled", "ClientAuthErrorCodes.methodNotImplemented", "LogLevel", "ClientConfigurationErrorCodes.redirectUriEmpty", "ClientConfigurationErrorCodes.claimsRequestParsingError", "ClientConfigurationErrorCodes.authorityUriInsecure", "ClientConfigurationErrorCodes.urlParseError", "ClientConfigurationErrorCodes.urlEmptyError", "ClientConfigurationErrorCodes.emptyInputScopesError", "ClientConfigurationErrorCodes.invalidClaims", "ClientConfigurationErrorCodes.tokenRequestEmpty", "ClientConfigurationErrorCodes.logoutRequestEmpty", "ClientConfigurationErrorCodes.invalidCodeChallengeMethod", "ClientConfigurationErrorCodes.pkceParamsMissing", "ClientConfigurationErrorCodes.invalidCloudDiscoveryMetadata", "ClientConfigurationErrorCodes.invalidAuthorityMetadata", "ClientConfigurationErrorCodes.untrustedAuthority", "ClientConfigurationErrorCodes.missingSshJwk", "ClientConfigurationErrorCodes.missingSshKid", "ClientConfigurationErrorCodes.missingNonceAuthenticationHeader", "ClientConfigurationErrorCodes.invalidAuthenticationHeader", "ClientConfigurationErrorCodes.cannotSetOIDCOptions", "ClientConfigurationErrorCodes.cannotAllowPlatformBroker", "ClientConfigurationErrorCodes.authorityMismatch", "ClientConfigurationErrorCodes.invalidAuthorizePostBodyParameters", "ClientConfigurationErrorCodes.invalidRequestMethodForEAR", "ClientConfigurationErrorCodes.emptyInputScopesError", "ClientAuthErrorCodes.cannotAppendScopeSet", "ClientAuthErrorCodes.cannotRemoveEmptyScope", "ClientAuthErrorCodes.emptyInputScopeSet", "name", "tenantId", "base64Decode", "ClientAuthErrorCodes.tokenParsingError", "ClientAuthErrorCodes.nullOrEmptyToken", "ClientAuthErrorCodes.maxAgeTranspired", "ClientAuthErrorCodes.hashNotDeserialized", "ClientConfigurationErrorCodes.urlEmptyError", "ClientConfigurationErrorCodes.urlParseError", "ClientConfigurationErrorCodes.authorityUriInsecure", "UrlUtils.getDeserializedResponse", "CacheErrorCodes.cacheQuotaExceeded", "CacheErrorCodes.cacheErrorUnknown", "ClientAuthErrorCodes.invalidCacheRecord", "ClientAuthErrorCodes.multipleMatchingAppMetadata", "name", "ClientAuthErrorCodes.methodNotImplemented", "ClientAuthErrorCodes.methodNotImplemented", "base64Decode", "ClientAuthErrorCodes.clientInfoEmptyError", "ClientAuthErrorCodes.clientInfoDecodingError", "CLIENT_INFO", "AADServerParamKeys.CLIENT_ID", "AADServerParamKeys.BROKER_CLIENT_ID", "AADServerParamKeys.REDIRECT_URI", "AADServerParamKeys.RESPONSE_TYPE", "AADServerParamKeys.RESPONSE_MODE", "AADServerParamKeys.NATIVE_BROKER", "AADServerParamKeys.SCOPE", "AADServerParamKeys.POST_LOGOUT_URI", "AADServerParamKeys.ID_TOKEN_HINT", "AADServerParamKeys.DOMAIN_HINT", "AADServerParamKeys.LOGIN_HINT", "AADServerParamKeys.SID", "ClientConfigurationErrorCodes.invalidClaims", "AADServerParamKeys.CLAIMS", "AADServerParamKeys.CLIENT_REQUEST_ID", "AADServerParamKeys.X_CLIENT_SKU", "AADServerParamKeys.X_CLIENT_VER", "AADServerParamKeys.X_CLIENT_OS", "AADServerParamKeys.X_CLIENT_CPU", "AADServerParamKeys.X_APP_NAME", "AADServerParamKeys.X_APP_VER", "AADServerParamKeys.PROMPT", "AADServerParamKeys.STATE", "AADServerParamKeys.NONCE", "AADServerParamKeys.CODE_CHALLENGE", "AADServerParamKeys.CODE_CHALLENGE_METHOD", "ClientConfigurationErrorCodes.pkceParamsMissing", "AADServerParamKeys.CODE", "AADServerParamKeys.DEVICE_CODE", "AADServerParamKeys.REFRESH_TOKEN", "AADServerParamKeys.CODE_VERIFIER", "AADServerParamKeys.CLIENT_SECRET", "AADServerParamKeys.CLIENT_ASSERTION", "AADServerParamKeys.CLIENT_ASSERTION_TYPE", "AADServerParamKeys.OBO_ASSERTION", "AADServerParamKeys.REQUESTED_TOKEN_USE", "AADServerParamKeys.GRANT_TYPE", "AADServerParamKeys.INSTANCE_AWARE", "AADServerParamKeys.TOKEN_TYPE", "AADServerParamKeys.REQ_CNF", "AADServerParamKeys.X_CLIENT_CURR_TELEM", "AADServerParamKeys.X_CLIENT_LAST_TELEM", "AADServerParamKeys.X_MS_LIB_CAPABILITY", "AADServerParamKeys.LOGOUT_HINT", "AADServerParamKeys.BROKER_REDIRECT_URI", "AADServerParamKeys.EAR_JWK", "AADServerParamKeys.EAR_JWE_CRYPTO", "e", "version", "base64Decode", "TimeUtils.nowSeconds", "ClientAuthErrorCodes.tokenClaimsCnfRequiredForSignedJwt", "ClientAuthErrorCodes.endpointResolutionError", "ClientAuthErrorCodes.endSessionEndpointNotSupported", "CacheHelpers.generateAuthorityMetadataExpiresAt", "CacheHelpers.updateAuthorityEndpointMetadata", "ClientAuthErrorCodes.openIdConfigError", "CacheHelpers.isAuthorityMetadataExpired", "ClientConfigurationErrorCodes.invalidAuthorityMetadata", "CacheHelpers.updateCloudDiscoveryMetadata", "ClientConfigurationErrorCodes.untrustedAuthority", "ClientConfigurationErrorCodes.invalidCloudDiscoveryMetadata", "ClientAuthErrorCodes.endpointResolutionError", "ClientAuthErrorCodes.networkError", "RequestParameterBuilder.addBrokerParameters", "RequestParameterBuilder.addExtraQueryParameters", "RequestParameterBuilder.addCorrelationId", "RequestParameterBuilder.instrumentBrokerParams", "UrlUtils.mapToQueryString", "base64Decode", "ClientAuthErrorCodes.invalidCacheEnvironment", "InteractionRequiredAuthErrorCodes.interactionRequired", "InteractionRequiredAuthErrorCodes.consentRequired", "InteractionRequiredAuthErrorCodes.loginRequired", "InteractionRequiredAuthErrorCodes.badToken", "InteractionRequiredAuthErrorCodes.uxNotAllowed", "InteractionRequiredAuthErrorCodes.noTokensFound", "InteractionRequiredAuthErrorCodes.nativeAccountUnavailable", "InteractionRequiredAuthErrorCodes.refreshTokenExpired", "ClientAuthErrorCodes.noCryptoObject", "ClientAuthErrorCodes.invalidState", "TimeUtils.nowSeconds", "ClientAuthErrorCodes.nonceMismatch", "ClientAuthErrorCodes.authTimeNotFound", "ClientAuthErrorCodes.invalidCacheEnvironment", "CacheHelpers.createIdTokenEntity", "CacheHelpers.createAccessTokenEntity", "CacheHelpers.createRefreshTokenEntity", "ClientAuthErrorCodes.keyIdMissing", "TimeUtils.toDateFromSeconds", "base64Decode", "ClientAuthErrorCodes.requestCannotBeMade", "TimeUtils.nowSeconds", "ClientConfigurationErrorCodes.logoutRequestEmpty", "RequestParameterBuilder.addClientId", "AADServerParamKeys.CLIENT_ID", "ClientConfigurationErrorCodes.redirectUriEmpty", "RequestParameterBuilder.addRedirectUri", "RequestParameterBuilder.addScopes", "RequestParameterBuilder.addAuthorizationCode", "RequestParameterBuilder.addLibraryInfo", "RequestParameterBuilder.addApplicationTelemetry", "RequestParameterBuilder.addThrottling", "RequestParameterBuilder.addServerTelemetry", "RequestParameterBuilder.addCodeVerifier", "RequestParameterBuilder.addClientSecret", "RequestParameterBuilder.addClientAssertion", "RequestParameterBuilder.addClientAssertionType", "RequestParameterBuilder.addGrantType", "RequestParameterBuilder.addClientInfo", "RequestParameterBuilder.addPopToken", "RequestParameterBuilder.addSshJwk", "ClientConfigurationErrorCodes.missingSshJwk", "RequestParameterBuilder.addClaims", "RequestParameterBuilder.addCcsOid", "RequestParameterBuilder.addCcsUpn", "RequestParameterBuilder.addBrokerParameters", "RequestParameterBuilder.addExtraQueryParameters", "AADServerParamKeys.RETURN_SPA_CODE", "RequestParameterBuilder.instrumentBrokerParams", "UrlUtils.mapToQueryString", "RequestParameterBuilder.addPostLogoutRedirectUri", "RequestParameterBuilder.addCorrelationId", "RequestParameterBuilder.addIdTokenHint", "RequestParameterBuilder.addState", "RequestParameterBuilder.addLogoutHint", "RequestParameterBuilder.addInstanceAware", "TimeUtils.nowSeconds", "ClientConfigurationErrorCodes.tokenRequestEmpty", "ClientAuthErrorCodes.noAccountInSilentRequest", "InteractionRequiredAuthErrorCodes.noTokensFound", "TimeUtils.isTokenExpired", "InteractionRequiredAuthErrorCodes.refreshTokenExpired", "InteractionRequiredAuthErrorCodes.badToken", "RequestParameterBuilder.addClientId", "AADServerParamKeys.CLIENT_ID", "RequestParameterBuilder.addRedirectUri", "RequestParameterBuilder.addScopes", "RequestParameterBuilder.addGrantType", "RequestParameterBuilder.addClientInfo", "RequestParameterBuilder.addLibraryInfo", "RequestParameterBuilder.addApplicationTelemetry", "RequestParameterBuilder.addThrottling", "RequestParameterBuilder.addServerTelemetry", "RequestParameterBuilder.addRefreshToken", "RequestParameterBuilder.addClientSecret", "RequestParameterBuilder.addClientAssertion", "RequestParameterBuilder.addClientAssertionType", "RequestParameterBuilder.addPopToken", "RequestParameterBuilder.addSshJwk", "ClientConfigurationErrorCodes.missingSshJwk", "RequestParameterBuilder.addClaims", "RequestParameterBuilder.addCcsOid", "RequestParameterBuilder.addCcsUpn", "RequestParameterBuilder.addBrokerParameters", "RequestParameterBuilder.addExtraQueryParameters", "RequestParameterBuilder.instrumentBrokerParams", "UrlUtils.mapToQueryString", "ClientAuthErrorCodes.tokenRefreshRequired", "ClientAuthErrorCodes.noAccountInSilentRequest", "TimeUtils.wasClockTurnedBack", "TimeUtils.isTokenExpired", "ClientAuthErrorCodes.authTimeNotFound", "ClientAuthErrorCodes.methodNotImplemented", "RequestParameterBuilder.addClientId", "AADServerParamKeys.CLIENT_ID", "RequestParameterBuilder.addScopes", "RequestParameterBuilder.addRedirectUri", "RequestParameterBuilder.addCorrelationId", "RequestParameterBuilder.addResponseMode", "RequestParameterBuilder.addClientInfo", "RequestParameterBuilder.addPrompt", "RequestParameterBuilder.addDomainHint", "RequestParameterBuilder.addSid", "RequestParameterBuilder.addLoginHint", "RequestParameterBuilder.addCcsOid", "RequestParameterBuilder.addCcsUpn", "RequestParameterBuilder.addNonce", "RequestParameterBuilder.addState", "RequestParameterBuilder.addClaims", "RequestParameterBuilder.addBrokerParameters", "AADServerParamKeys.INSTANCE_AWARE", "RequestParameterBuilder.addInstanceAware", "ClientAuthErrorCodes.authorizationCodeMissingFromServerResponse", "ClientAuthErrorCodes.stateNotFound", "ClientAuthErrorCodes.invalidState", "ClientAuthErrorCodes.stateMismatch", "ClientConfigurationErrorCodes.invalidAuthenticationHeader", "ClientConfigurationErrorCodes.missingNonceAuthenticationHeader", "JoseHeaderErrorCodes.missingKidError", "JoseHeaderErrorCodes.missingAlgError", "JoseHeaderErrorCodes.missingKidError", "JoseHeaderErrorCodes.missingAlgError", "stack", "noNetworkConnectivity", "postRequestFailed", "BrowserAuthErrorCodes.pkceNotCreated", "BrowserAuthErrorCodes.earJwkEmpty", "BrowserAuthErrorCodes.earJweEmpty", "BrowserAuthErrorCodes.cryptoNonExistent", "BrowserAuthErrorCodes.emptyNavigateUri", "BrowserAuthErrorCodes.hashEmptyError", "BrowserAuthErrorCodes.noStateInHash", "BrowserAuthErrorCodes.hashDoesNotContainKnownProperties", "BrowserAuthErrorCodes.unableToParseState", "BrowserAuthErrorCodes.stateInteractionTypeMismatch", "BrowserAuthErrorCodes.interactionInProgress", "BrowserAuthErrorCodes.popupWindowError", "BrowserAuthErrorCodes.emptyWindowError", "BrowserAuthErrorCodes.userCancelled", "BrowserAuthErrorCodes.monitorPopupTimeout", "BrowserAuthErrorCodes.monitorWindowTimeout", "BrowserAuthErrorCodes.redirectInIframe", "BrowserAuthErrorCodes.blockIframeReload", "BrowserAuthErrorCodes.blockNestedPopups", "BrowserAuthErrorCodes.iframeClosedPrematurely", "BrowserAuthErrorCodes.silentLogoutUnsupported", "BrowserAuthErrorCodes.noAccountError", "BrowserAuthErrorCodes.silentPromptValueError", "BrowserAuthErrorCodes.noTokenRequestCacheError", "BrowserAuthErrorCodes.unableToParseTokenRequestCacheError", "BrowserAuthErrorCodes.authRequestNotSetError", "BrowserAuthErrorCodes.invalidCacheType", "BrowserAuthErrorCodes.nonBrowserEnvironment", "BrowserAuthErrorCodes.databaseNotOpen", "BrowserAuthErrorCodes.noNetworkConnectivity", "BrowserAuthErrorCodes.postRequestFailed", "BrowserAuthErrorCodes.getRequestFailed", "BrowserAuthErrorCodes.failedToParseResponse", "BrowserAuthErrorCodes.unableToLoadToken", "BrowserAuthErrorCodes.cryptoKeyNotFound", "BrowserAuthErrorCodes.authCodeRequired", "BrowserAuthErrorCodes.authCodeOrNativeAccountIdRequired", "BrowserAuthErrorCodes.spaCodeAndNativeAccountIdPresent", "BrowserAuthErrorCodes.databaseUnavailable", "BrowserAuthErrorCodes.unableToAcquireTokenFromNativePlatform", "BrowserAuthErrorCodes.nativeHandshakeTimeout", "BrowserAuthErrorCodes.nativeExtensionNotInstalled", "BrowserAuthErrorCodes.nativeConnectionNotEstablished", "BrowserAuthErrorCodes.uninitializedPublicClientApplication", "BrowserAuthErrorCodes.nativePromptNotSupported", "BrowserAuthErrorCodes.invalidBase64String", "BrowserAuthErrorCodes.invalidPopTokenRequest", "BrowserAuthErrorCodes.failedToBuildHeaders", "BrowserAuthErrorCodes.failedToParseHeaders", "BrowserAuthErrorCodes.failedToDecryptEarResponse", "BrowserAuthErrorCodes.timedOut", "InteractionType", "BrowserAuthErrorCodes.invalidBase64String", "BrowserAuthErrorCodes.nonBrowserEnvironment", "BrowserAuthErrorCodes.cryptoNonExistent", "BrowserAuthErrorCodes.failedToDecryptEarResponse", "BrowserConfigurationAuthErrorCodes.storageNotSupported", "BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled", "BrowserConfigurationAuthErrorCodes.inMemRedirectUnavailable", "BrowserConfigurationAuthErrorCodes\r\n .stubbedPublicClientApplicationCalled", "BrowserAuthErrorCodes.blockIframeReload", "BrowserAuthErrorCodes.redirectInIframe", "BrowserAuthErrorCodes.blockNestedPopups", "BrowserAuthErrorCodes.nonBrowserEnvironment", "BrowserAuthErrorCodes.uninitializedPublicClientApplication", "BrowserConfigurationAuthErrorCodes.inMemRedirectUnavailable", "BrowserCrypto.createNewGuid", "addClientCapabilitiesToClaims", "BrowserAuthErrorCodes.timedOut", "BrowserAuthErrorCodes.getRequestFailed", "BrowserAuthErrorCodes.noNetworkConnectivity", "BrowserAuthErrorCodes.failedToParseResponse", "BrowserAuthErrorCodes.postRequestFailed", "BrowserAuthErrorCodes.failedToBuildHeaders", "BrowserAuthErrorCodes.failedToParseHeaders", "BrowserUtils.getCurrentUri", "DEFAULT_CACHE_OPTIONS", "DEFAULT_TELEMETRY_OPTIONS", "name", "version", "name", "version", "BrowserCrypto.createNewGuid", "version", "BrowserAuthErrorCodes.databaseUnavailable", "BrowserAuthErrorCodes.databaseNotOpen", "BrowserAuthErrorCodes.databaseUnavailable", "BrowserCrypto.validateCryptoAvailable", "BrowserCrypto.createNewGuid", "BrowserCrypto.generateKeyPair", "BrowserCrypto.exportJwk", "BrowserCrypto.importJwk", "BrowserAuthErrorCodes.cryptoKeyNotFound", "BrowserCrypto.sign", "BrowserCrypto.hashString", "name", "key", "CacheKeys.getAccountKeysCacheKey", "CacheKeys.getTokenKeysCacheKey", "BrowserConfigurationAuthErrorCodes.storageNotSupported", "BrowserAuthErrorCodes.uninitializedPublicClientApplication", "CacheKeys.PREFIX", "CacheKeys.getAccountKeysCacheKey", "CacheKeys.getTokenKeysCacheKey", "BrowserConfigurationAuthErrorCodes.storageNotSupported", "CacheKeys.ACCOUNT_SCHEMA_VERSION", "CacheKeys.CREDENTIAL_SCHEMA_VERSION", "CacheKeys.getAccountKeysCacheKey", "CacheKeys.PREFIX", "CacheKeys.CACHE_KEY_SEPARATOR", "CacheKeys.VERSION_CACHE_KEY", "version", "CacheKeys.getTokenKeysCacheKey", "BrowserAuthErrorCodes.noTokenRequestCacheError", "BrowserAuthErrorCodes.unableToParseTokenRequestCacheError", "BrowserAuthErrorCodes.interactionInProgress", "e", "BROADCAST_CHANNEL_NAME", "version", "BrowserUtils.getCurrentUri", "BrowserUtils.getCurrentUri", "version", "BrowserAuthErrorCodes.hashEmptyError", "BrowserAuthErrorCodes.hashDoesNotContainKnownProperties", "BrowserAuthErrorCodes.noStateInHash", "BrowserAuthErrorCodes.unableToParseState", "BrowserAuthErrorCodes.stateInteractionTypeMismatch", "BrowserAuthErrorCodes.userCancelled", "NativeAuthErrorCodes.userSwitch", "NativeStatusCodes.DISABLED", "NativeAuthErrorCodes.contentError", "NativeStatusCodes.ACCOUNT_UNAVAILABLE", "NativeStatusCodes.USER_INTERACTION_REQUIRED", "NativeStatusCodes.USER_CANCEL", "BrowserAuthErrorCodes.userCancelled", "NativeStatusCodes.NO_NETWORK", "BrowserAuthErrorCodes.noNetworkConnectivity", "NativeStatusCodes.UX_NOT_ALLOWED", "BrowserAuthErrorCodes.cryptoKeyNotFound", "version", "NativeAuthErrorCodes.userSwitch", "BrowserAuthErrorCodes.invalidPopTokenRequest", "BrowserAuthErrorCodes.nativePromptNotSupported", "version", "BrowserAuthErrorCodes.earJwkEmpty", "BrowserAuthErrorCodes.nativeConnectionNotEstablished", "BrowserAuthErrorCodes.earJweEmpty", "BrowserAuthErrorCodes.pkceNotCreated", "BrowserAuthErrorCodes.nativeHandshakeTimeout", "BrowserAuthErrorCodes.nativeExtensionNotInstalled", "name", "version", "BrowserUtils.preconnect", "Authorize.getAuthCodeRequestUrl", "ResponseHandler.deserializeResponse", "Authorize.handleResponseCode", "Authorize.getEARForm", "Authorize.handleResponseEAR", "Authorize.getCodeForm", "BrowserUtils.getCurrentUri", "BrowserAuthErrorCodes.emptyNavigateUri", "BrowserAuthErrorCodes.userCancelled", "BrowserAuthErrorCodes.emptyWindowError", "BrowserAuthErrorCodes.popupWindowError", "Authorize.getAuthCodeRequestUrl", "Authorize.getEARForm", "BrowserAuthErrorCodes.timedOut", "Authorize.getCodeForm", "BrowserUtils.replaceHash", "BrowserUtils.isInIframe", "BrowserUtils.getHomepage", "ResponseHandler.validateInteractionType", "BrowserUtils.clearHash", "BrowserAuthErrorCodes.noStateInHash", "Authorize.handleResponseEAR", "Authorize.handleResponseCode", "BrowserAuthErrorCodes.emptyNavigateUri", "BrowserUtils.getCurrentUri", "BrowserAuthErrorCodes.emptyNavigateUri", "BrowserAuthErrorCodes.monitorWindowTimeout", "BrowserUtils.preconnect", "ResponseHandler.deserializeResponse", "Authorize.handleResponseEAR", "BrowserAuthErrorCodes.silentLogoutUnsupported", "Authorize.getAuthCodeRequestUrl", "Authorize.handleResponseCode", "BrowserAuthErrorCodes.silentLogoutUnsupported", "BrowserAuthErrorCodes.nonBrowserEnvironment", "BrowserCrypto.createNewGuid", "BrowserAuthErrorCodes.unableToLoadToken", "BrowserAuthErrorCodes.authCodeRequired", "BrowserAuthErrorCodes.silentLogoutUnsupported", "preflightCheck", "BrowserUtils.preflightCheck", "BrowserUtils.blockAPICallsBeforeInitialize", "BrowserUtils.redirectPreflightCheck", "result", "_a", "BrowserAuthErrorCodes.spaCodeAndNativeAccountIdPresent", "BrowserAuthErrorCodes.unableToAcquireTokenFromNativePlatform", "BrowserAuthErrorCodes.authCodeOrNativeAccountIdRequired", "AccountManager.getAllAccounts", "AccountManager.getAccount", "AccountManager.getAccountByUsername", "AccountManager.getAccountByHomeId", "AccountManager.getAccountByLocalId", "AccountManager.setActiveAccount", "AccountManager.getActiveAccount", "BrowserAuthErrorCodes.nativeConnectionNotEstablished", "BrowserUtils.blockNonBrowserEnvironment", "version", "BrowserAuthErrorCodes.noAccountError", "name", "result", "AccountManager.getAccount", "AccountManager.getAllAccounts", "AccountManager.getAccountByUsername", "AccountManager.getAccountByHomeId", "AccountManager.getAccountByLocalId", "AccountManager.setActiveAccount", "AccountManager.getActiveAccount", "version", "ControllerFactory.createV3Controller", "version", "version", "ControllerFactory.createController", "version", "BrowserConfigurationAuthErrorCodes.stubbedPublicClientApplicationCalled", "name", "version", "name", "version", "BrowserCrypto.createNewGuid"] } diff --git a/GTF/project/node_modules/.vite/deps/BrowserPerformanceMeasurement-5UJNI4WV.js b/GTF/project/node_modules/.vite/deps/BrowserPerformanceMeasurement-5VDOVMRB.js similarity index 55% rename from GTF/project/node_modules/.vite/deps/BrowserPerformanceMeasurement-5UJNI4WV.js rename to GTF/project/node_modules/.vite/deps/BrowserPerformanceMeasurement-5VDOVMRB.js index fac2e124..1b14fd80 100644 --- a/GTF/project/node_modules/.vite/deps/BrowserPerformanceMeasurement-5UJNI4WV.js +++ b/GTF/project/node_modules/.vite/deps/BrowserPerformanceMeasurement-5VDOVMRB.js @@ -1,8 +1,8 @@ import { BrowserPerformanceMeasurement -} from "./chunk-BXCAR3JX.js"; +} from "./chunk-5VK5IHOT.js"; import "./chunk-G3PMV62Z.js"; export { BrowserPerformanceMeasurement }; -//# sourceMappingURL=BrowserPerformanceMeasurement-5UJNI4WV.js.map +//# sourceMappingURL=BrowserPerformanceMeasurement-5VDOVMRB.js.map diff --git a/GTF/project/node_modules/.vite/deps/BrowserPerformanceMeasurement-5UJNI4WV.js.map b/GTF/project/node_modules/.vite/deps/BrowserPerformanceMeasurement-5VDOVMRB.js.map similarity index 100% rename from GTF/project/node_modules/.vite/deps/BrowserPerformanceMeasurement-5UJNI4WV.js.map rename to GTF/project/node_modules/.vite/deps/BrowserPerformanceMeasurement-5VDOVMRB.js.map diff --git a/GTF/project/node_modules/.vite/deps/_metadata.json b/GTF/project/node_modules/.vite/deps/_metadata.json index ab230389..bbf56146 100644 --- a/GTF/project/node_modules/.vite/deps/_metadata.json +++ b/GTF/project/node_modules/.vite/deps/_metadata.json @@ -1,58 +1,58 @@ { - "hash": "0db3536e", - "configHash": "dc00d83f", - "lockfileHash": "14011340", - "browserHash": "672592a0", + "hash": "1e9c2bee", + "configHash": "451161ff", + "lockfileHash": "b1ec30a4", + "browserHash": "57e609ed", "optimized": { "react": { "src": "../../react/index.js", "file": "react.js", - "fileHash": "8ad7db99", + "fileHash": "4348729b", "needsInterop": true }, "react/jsx-dev-runtime": { "src": "../../react/jsx-dev-runtime.js", "file": "react_jsx-dev-runtime.js", - "fileHash": "ec7323e1", + "fileHash": "9694e297", "needsInterop": true }, "react/jsx-runtime": { "src": "../../react/jsx-runtime.js", "file": "react_jsx-runtime.js", - "fileHash": "7307506d", + "fileHash": "4fa96245", "needsInterop": true }, + "@azure/msal-browser": { + "src": "../../@azure/msal-browser/dist/index.mjs", + "file": "@azure_msal-browser.js", + "fileHash": "8be31f82", + "needsInterop": false + }, "react-dom/client": { "src": "../../react-dom/client.js", "file": "react-dom_client.js", - "fileHash": "e3d0ad6f", + "fileHash": "8aa9b52d", "needsInterop": true }, "react-router-dom": { "src": "../../../../node_modules/react-router-dom/dist/index.mjs", "file": "react-router-dom.js", - "fileHash": "ca3428cd", - "needsInterop": false - }, - "@azure/msal-browser": { - "src": "../../@azure/msal-browser/dist/index.mjs", - "file": "@azure_msal-browser.js", - "fileHash": "72740ae2", + "fileHash": "f4ac1124", "needsInterop": false } }, "chunks": { - "chunk-6BKLQ22S": { - "file": "chunk-6BKLQ22S.js" + "chunk-4W2RIJ36": { + "file": "chunk-4W2RIJ36.js" }, - "chunk-DRWLMN53": { - "file": "chunk-DRWLMN53.js" + "chunk-QRULMDK5": { + "file": "chunk-QRULMDK5.js" }, - "BrowserPerformanceMeasurement-5UJNI4WV": { - "file": "BrowserPerformanceMeasurement-5UJNI4WV.js" + "BrowserPerformanceMeasurement-5VDOVMRB": { + "file": "BrowserPerformanceMeasurement-5VDOVMRB.js" }, - "chunk-BXCAR3JX": { - "file": "chunk-BXCAR3JX.js" + "chunk-5VK5IHOT": { + "file": "chunk-5VK5IHOT.js" }, "chunk-G3PMV62Z": { "file": "chunk-G3PMV62Z.js" diff --git a/GTF/project/node_modules/.vite/deps/chunk-6BKLQ22S.js b/GTF/project/node_modules/.vite/deps/chunk-4W2RIJ36.js similarity index 99% rename from GTF/project/node_modules/.vite/deps/chunk-6BKLQ22S.js rename to GTF/project/node_modules/.vite/deps/chunk-4W2RIJ36.js index acaeeec5..a2f296d8 100644 --- a/GTF/project/node_modules/.vite/deps/chunk-6BKLQ22S.js +++ b/GTF/project/node_modules/.vite/deps/chunk-4W2RIJ36.js @@ -1,6 +1,6 @@ import { require_react -} from "./chunk-DRWLMN53.js"; +} from "./chunk-QRULMDK5.js"; import { __commonJS } from "./chunk-G3PMV62Z.js"; @@ -21626,4 +21626,4 @@ react-dom/cjs/react-dom.development.js: * @license Modernizr 3.0.0pre (Custom Build) | MIT *) */ -//# sourceMappingURL=chunk-6BKLQ22S.js.map +//# sourceMappingURL=chunk-4W2RIJ36.js.map diff --git a/GTF/project/node_modules/.vite/deps/chunk-4W2RIJ36.js.map b/GTF/project/node_modules/.vite/deps/chunk-4W2RIJ36.js.map new file mode 100644 index 00000000..e8fa2246 --- /dev/null +++ b/GTF/project/node_modules/.vite/deps/chunk-4W2RIJ36.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../../scheduler/cjs/scheduler.development.js", "../../scheduler/index.js", "../../react-dom/cjs/react-dom.development.js", "../../react-dom/index.js"], + "sourcesContent": ["/**\r\n * @license React\r\n * scheduler.development.js\r\n *\r\n * Copyright (c) Facebook, Inc. and its affiliates.\r\n *\r\n * This source code is licensed under the MIT license found in the\r\n * LICENSE file in the root directory of this source tree.\r\n */\r\n\r\n'use strict';\r\n\r\nif (process.env.NODE_ENV !== \"production\") {\r\n (function() {\r\n\r\n 'use strict';\r\n\r\n/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\r\nif (\r\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&\r\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart ===\r\n 'function'\r\n) {\r\n __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());\r\n}\r\n var enableSchedulerDebugging = false;\r\nvar enableProfiling = false;\r\nvar frameYieldMs = 5;\r\n\r\nfunction push(heap, node) {\r\n var index = heap.length;\r\n heap.push(node);\r\n siftUp(heap, node, index);\r\n}\r\nfunction peek(heap) {\r\n return heap.length === 0 ? null : heap[0];\r\n}\r\nfunction pop(heap) {\r\n if (heap.length === 0) {\r\n return null;\r\n }\r\n\r\n var first = heap[0];\r\n var last = heap.pop();\r\n\r\n if (last !== first) {\r\n heap[0] = last;\r\n siftDown(heap, last, 0);\r\n }\r\n\r\n return first;\r\n}\r\n\r\nfunction siftUp(heap, node, i) {\r\n var index = i;\r\n\r\n while (index > 0) {\r\n var parentIndex = index - 1 >>> 1;\r\n var parent = heap[parentIndex];\r\n\r\n if (compare(parent, node) > 0) {\r\n // The parent is larger. Swap positions.\r\n heap[parentIndex] = node;\r\n heap[index] = parent;\r\n index = parentIndex;\r\n } else {\r\n // The parent is smaller. Exit.\r\n return;\r\n }\r\n }\r\n}\r\n\r\nfunction siftDown(heap, node, i) {\r\n var index = i;\r\n var length = heap.length;\r\n var halfLength = length >>> 1;\r\n\r\n while (index < halfLength) {\r\n var leftIndex = (index + 1) * 2 - 1;\r\n var left = heap[leftIndex];\r\n var rightIndex = leftIndex + 1;\r\n var right = heap[rightIndex]; // If the left or right node is smaller, swap with the smaller of those.\r\n\r\n if (compare(left, node) < 0) {\r\n if (rightIndex < length && compare(right, left) < 0) {\r\n heap[index] = right;\r\n heap[rightIndex] = node;\r\n index = rightIndex;\r\n } else {\r\n heap[index] = left;\r\n heap[leftIndex] = node;\r\n index = leftIndex;\r\n }\r\n } else if (rightIndex < length && compare(right, node) < 0) {\r\n heap[index] = right;\r\n heap[rightIndex] = node;\r\n index = rightIndex;\r\n } else {\r\n // Neither child is smaller. Exit.\r\n return;\r\n }\r\n }\r\n}\r\n\r\nfunction compare(a, b) {\r\n // Compare sort index first, then task id.\r\n var diff = a.sortIndex - b.sortIndex;\r\n return diff !== 0 ? diff : a.id - b.id;\r\n}\r\n\r\n// TODO: Use symbols?\r\nvar ImmediatePriority = 1;\r\nvar UserBlockingPriority = 2;\r\nvar NormalPriority = 3;\r\nvar LowPriority = 4;\r\nvar IdlePriority = 5;\r\n\r\nfunction markTaskErrored(task, ms) {\r\n}\r\n\r\n/* eslint-disable no-var */\r\n\r\nvar hasPerformanceNow = typeof performance === 'object' && typeof performance.now === 'function';\r\n\r\nif (hasPerformanceNow) {\r\n var localPerformance = performance;\r\n\r\n exports.unstable_now = function () {\r\n return localPerformance.now();\r\n };\r\n} else {\r\n var localDate = Date;\r\n var initialTime = localDate.now();\r\n\r\n exports.unstable_now = function () {\r\n return localDate.now() - initialTime;\r\n };\r\n} // Max 31 bit integer. The max integer size in V8 for 32-bit systems.\r\n// Math.pow(2, 30) - 1\r\n// 0b111111111111111111111111111111\r\n\r\n\r\nvar maxSigned31BitInt = 1073741823; // Times out immediately\r\n\r\nvar IMMEDIATE_PRIORITY_TIMEOUT = -1; // Eventually times out\r\n\r\nvar USER_BLOCKING_PRIORITY_TIMEOUT = 250;\r\nvar NORMAL_PRIORITY_TIMEOUT = 5000;\r\nvar LOW_PRIORITY_TIMEOUT = 10000; // Never times out\r\n\r\nvar IDLE_PRIORITY_TIMEOUT = maxSigned31BitInt; // Tasks are stored on a min heap\r\n\r\nvar taskQueue = [];\r\nvar timerQueue = []; // Incrementing id counter. Used to maintain insertion order.\r\n\r\nvar taskIdCounter = 1; // Pausing the scheduler is useful for debugging.\r\nvar currentTask = null;\r\nvar currentPriorityLevel = NormalPriority; // This is set while performing work, to prevent re-entrance.\r\n\r\nvar isPerformingWork = false;\r\nvar isHostCallbackScheduled = false;\r\nvar isHostTimeoutScheduled = false; // Capture local references to native APIs, in case a polyfill overrides them.\r\n\r\nvar localSetTimeout = typeof setTimeout === 'function' ? setTimeout : null;\r\nvar localClearTimeout = typeof clearTimeout === 'function' ? clearTimeout : null;\r\nvar localSetImmediate = typeof setImmediate !== 'undefined' ? setImmediate : null; // IE and Node.js + jsdom\r\n\r\nvar isInputPending = typeof navigator !== 'undefined' && navigator.scheduling !== undefined && navigator.scheduling.isInputPending !== undefined ? navigator.scheduling.isInputPending.bind(navigator.scheduling) : null;\r\n\r\nfunction advanceTimers(currentTime) {\r\n // Check for tasks that are no longer delayed and add them to the queue.\r\n var timer = peek(timerQueue);\r\n\r\n while (timer !== null) {\r\n if (timer.callback === null) {\r\n // Timer was cancelled.\r\n pop(timerQueue);\r\n } else if (timer.startTime <= currentTime) {\r\n // Timer fired. Transfer to the task queue.\r\n pop(timerQueue);\r\n timer.sortIndex = timer.expirationTime;\r\n push(taskQueue, timer);\r\n } else {\r\n // Remaining timers are pending.\r\n return;\r\n }\r\n\r\n timer = peek(timerQueue);\r\n }\r\n}\r\n\r\nfunction handleTimeout(currentTime) {\r\n isHostTimeoutScheduled = false;\r\n advanceTimers(currentTime);\r\n\r\n if (!isHostCallbackScheduled) {\r\n if (peek(taskQueue) !== null) {\r\n isHostCallbackScheduled = true;\r\n requestHostCallback(flushWork);\r\n } else {\r\n var firstTimer = peek(timerQueue);\r\n\r\n if (firstTimer !== null) {\r\n requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction flushWork(hasTimeRemaining, initialTime) {\r\n\r\n\r\n isHostCallbackScheduled = false;\r\n\r\n if (isHostTimeoutScheduled) {\r\n // We scheduled a timeout but it's no longer needed. Cancel it.\r\n isHostTimeoutScheduled = false;\r\n cancelHostTimeout();\r\n }\r\n\r\n isPerformingWork = true;\r\n var previousPriorityLevel = currentPriorityLevel;\r\n\r\n try {\r\n if (enableProfiling) {\r\n try {\r\n return workLoop(hasTimeRemaining, initialTime);\r\n } catch (error) {\r\n if (currentTask !== null) {\r\n var currentTime = exports.unstable_now();\r\n markTaskErrored(currentTask, currentTime);\r\n currentTask.isQueued = false;\r\n }\r\n\r\n throw error;\r\n }\r\n } else {\r\n // No catch in prod code path.\r\n return workLoop(hasTimeRemaining, initialTime);\r\n }\r\n } finally {\r\n currentTask = null;\r\n currentPriorityLevel = previousPriorityLevel;\r\n isPerformingWork = false;\r\n }\r\n}\r\n\r\nfunction workLoop(hasTimeRemaining, initialTime) {\r\n var currentTime = initialTime;\r\n advanceTimers(currentTime);\r\n currentTask = peek(taskQueue);\r\n\r\n while (currentTask !== null && !(enableSchedulerDebugging )) {\r\n if (currentTask.expirationTime > currentTime && (!hasTimeRemaining || shouldYieldToHost())) {\r\n // This currentTask hasn't expired, and we've reached the deadline.\r\n break;\r\n }\r\n\r\n var callback = currentTask.callback;\r\n\r\n if (typeof callback === 'function') {\r\n currentTask.callback = null;\r\n currentPriorityLevel = currentTask.priorityLevel;\r\n var didUserCallbackTimeout = currentTask.expirationTime <= currentTime;\r\n\r\n var continuationCallback = callback(didUserCallbackTimeout);\r\n currentTime = exports.unstable_now();\r\n\r\n if (typeof continuationCallback === 'function') {\r\n currentTask.callback = continuationCallback;\r\n } else {\r\n\r\n if (currentTask === peek(taskQueue)) {\r\n pop(taskQueue);\r\n }\r\n }\r\n\r\n advanceTimers(currentTime);\r\n } else {\r\n pop(taskQueue);\r\n }\r\n\r\n currentTask = peek(taskQueue);\r\n } // Return whether there's additional work\r\n\r\n\r\n if (currentTask !== null) {\r\n return true;\r\n } else {\r\n var firstTimer = peek(timerQueue);\r\n\r\n if (firstTimer !== null) {\r\n requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);\r\n }\r\n\r\n return false;\r\n }\r\n}\r\n\r\nfunction unstable_runWithPriority(priorityLevel, eventHandler) {\r\n switch (priorityLevel) {\r\n case ImmediatePriority:\r\n case UserBlockingPriority:\r\n case NormalPriority:\r\n case LowPriority:\r\n case IdlePriority:\r\n break;\r\n\r\n default:\r\n priorityLevel = NormalPriority;\r\n }\r\n\r\n var previousPriorityLevel = currentPriorityLevel;\r\n currentPriorityLevel = priorityLevel;\r\n\r\n try {\r\n return eventHandler();\r\n } finally {\r\n currentPriorityLevel = previousPriorityLevel;\r\n }\r\n}\r\n\r\nfunction unstable_next(eventHandler) {\r\n var priorityLevel;\r\n\r\n switch (currentPriorityLevel) {\r\n case ImmediatePriority:\r\n case UserBlockingPriority:\r\n case NormalPriority:\r\n // Shift down to normal priority\r\n priorityLevel = NormalPriority;\r\n break;\r\n\r\n default:\r\n // Anything lower than normal priority should remain at the current level.\r\n priorityLevel = currentPriorityLevel;\r\n break;\r\n }\r\n\r\n var previousPriorityLevel = currentPriorityLevel;\r\n currentPriorityLevel = priorityLevel;\r\n\r\n try {\r\n return eventHandler();\r\n } finally {\r\n currentPriorityLevel = previousPriorityLevel;\r\n }\r\n}\r\n\r\nfunction unstable_wrapCallback(callback) {\r\n var parentPriorityLevel = currentPriorityLevel;\r\n return function () {\r\n // This is a fork of runWithPriority, inlined for performance.\r\n var previousPriorityLevel = currentPriorityLevel;\r\n currentPriorityLevel = parentPriorityLevel;\r\n\r\n try {\r\n return callback.apply(this, arguments);\r\n } finally {\r\n currentPriorityLevel = previousPriorityLevel;\r\n }\r\n };\r\n}\r\n\r\nfunction unstable_scheduleCallback(priorityLevel, callback, options) {\r\n var currentTime = exports.unstable_now();\r\n var startTime;\r\n\r\n if (typeof options === 'object' && options !== null) {\r\n var delay = options.delay;\r\n\r\n if (typeof delay === 'number' && delay > 0) {\r\n startTime = currentTime + delay;\r\n } else {\r\n startTime = currentTime;\r\n }\r\n } else {\r\n startTime = currentTime;\r\n }\r\n\r\n var timeout;\r\n\r\n switch (priorityLevel) {\r\n case ImmediatePriority:\r\n timeout = IMMEDIATE_PRIORITY_TIMEOUT;\r\n break;\r\n\r\n case UserBlockingPriority:\r\n timeout = USER_BLOCKING_PRIORITY_TIMEOUT;\r\n break;\r\n\r\n case IdlePriority:\r\n timeout = IDLE_PRIORITY_TIMEOUT;\r\n break;\r\n\r\n case LowPriority:\r\n timeout = LOW_PRIORITY_TIMEOUT;\r\n break;\r\n\r\n case NormalPriority:\r\n default:\r\n timeout = NORMAL_PRIORITY_TIMEOUT;\r\n break;\r\n }\r\n\r\n var expirationTime = startTime + timeout;\r\n var newTask = {\r\n id: taskIdCounter++,\r\n callback: callback,\r\n priorityLevel: priorityLevel,\r\n startTime: startTime,\r\n expirationTime: expirationTime,\r\n sortIndex: -1\r\n };\r\n\r\n if (startTime > currentTime) {\r\n // This is a delayed task.\r\n newTask.sortIndex = startTime;\r\n push(timerQueue, newTask);\r\n\r\n if (peek(taskQueue) === null && newTask === peek(timerQueue)) {\r\n // All tasks are delayed, and this is the task with the earliest delay.\r\n if (isHostTimeoutScheduled) {\r\n // Cancel an existing timeout.\r\n cancelHostTimeout();\r\n } else {\r\n isHostTimeoutScheduled = true;\r\n } // Schedule a timeout.\r\n\r\n\r\n requestHostTimeout(handleTimeout, startTime - currentTime);\r\n }\r\n } else {\r\n newTask.sortIndex = expirationTime;\r\n push(taskQueue, newTask);\r\n // wait until the next time we yield.\r\n\r\n\r\n if (!isHostCallbackScheduled && !isPerformingWork) {\r\n isHostCallbackScheduled = true;\r\n requestHostCallback(flushWork);\r\n }\r\n }\r\n\r\n return newTask;\r\n}\r\n\r\nfunction unstable_pauseExecution() {\r\n}\r\n\r\nfunction unstable_continueExecution() {\r\n\r\n if (!isHostCallbackScheduled && !isPerformingWork) {\r\n isHostCallbackScheduled = true;\r\n requestHostCallback(flushWork);\r\n }\r\n}\r\n\r\nfunction unstable_getFirstCallbackNode() {\r\n return peek(taskQueue);\r\n}\r\n\r\nfunction unstable_cancelCallback(task) {\r\n // remove from the queue because you can't remove arbitrary nodes from an\r\n // array based heap, only the first one.)\r\n\r\n\r\n task.callback = null;\r\n}\r\n\r\nfunction unstable_getCurrentPriorityLevel() {\r\n return currentPriorityLevel;\r\n}\r\n\r\nvar isMessageLoopRunning = false;\r\nvar scheduledHostCallback = null;\r\nvar taskTimeoutID = -1; // Scheduler periodically yields in case there is other work on the main\r\n// thread, like user events. By default, it yields multiple times per frame.\r\n// It does not attempt to align with frame boundaries, since most tasks don't\r\n// need to be frame aligned; for those that do, use requestAnimationFrame.\r\n\r\nvar frameInterval = frameYieldMs;\r\nvar startTime = -1;\r\n\r\nfunction shouldYieldToHost() {\r\n var timeElapsed = exports.unstable_now() - startTime;\r\n\r\n if (timeElapsed < frameInterval) {\r\n // The main thread has only been blocked for a really short amount of time;\r\n // smaller than a single frame. Don't yield yet.\r\n return false;\r\n } // The main thread has been blocked for a non-negligible amount of time. We\r\n\r\n\r\n return true;\r\n}\r\n\r\nfunction requestPaint() {\r\n\r\n}\r\n\r\nfunction forceFrameRate(fps) {\r\n if (fps < 0 || fps > 125) {\r\n // Using console['error'] to evade Babel and ESLint\r\n console['error']('forceFrameRate takes a positive int between 0 and 125, ' + 'forcing frame rates higher than 125 fps is not supported');\r\n return;\r\n }\r\n\r\n if (fps > 0) {\r\n frameInterval = Math.floor(1000 / fps);\r\n } else {\r\n // reset the framerate\r\n frameInterval = frameYieldMs;\r\n }\r\n}\r\n\r\nvar performWorkUntilDeadline = function () {\r\n if (scheduledHostCallback !== null) {\r\n var currentTime = exports.unstable_now(); // Keep track of the start time so we can measure how long the main thread\r\n // has been blocked.\r\n\r\n startTime = currentTime;\r\n var hasTimeRemaining = true; // If a scheduler task throws, exit the current browser task so the\r\n // error can be observed.\r\n //\r\n // Intentionally not using a try-catch, since that makes some debugging\r\n // techniques harder. Instead, if `scheduledHostCallback` errors, then\r\n // `hasMoreWork` will remain true, and we'll continue the work loop.\r\n\r\n var hasMoreWork = true;\r\n\r\n try {\r\n hasMoreWork = scheduledHostCallback(hasTimeRemaining, currentTime);\r\n } finally {\r\n if (hasMoreWork) {\r\n // If there's more work, schedule the next message event at the end\r\n // of the preceding one.\r\n schedulePerformWorkUntilDeadline();\r\n } else {\r\n isMessageLoopRunning = false;\r\n scheduledHostCallback = null;\r\n }\r\n }\r\n } else {\r\n isMessageLoopRunning = false;\r\n } // Yielding to the browser will give it a chance to paint, so we can\r\n};\r\n\r\nvar schedulePerformWorkUntilDeadline;\r\n\r\nif (typeof localSetImmediate === 'function') {\r\n // Node.js and old IE.\r\n // There's a few reasons for why we prefer setImmediate.\r\n //\r\n // Unlike MessageChannel, it doesn't prevent a Node.js process from exiting.\r\n // (Even though this is a DOM fork of the Scheduler, you could get here\r\n // with a mix of Node.js 15+, which has a MessageChannel, and jsdom.)\r\n // https://github.com/facebook/react/issues/20756\r\n //\r\n // But also, it runs earlier which is the semantic we want.\r\n // If other browsers ever implement it, it's better to use it.\r\n // Although both of these would be inferior to native scheduling.\r\n schedulePerformWorkUntilDeadline = function () {\r\n localSetImmediate(performWorkUntilDeadline);\r\n };\r\n} else if (typeof MessageChannel !== 'undefined') {\r\n // DOM and Worker environments.\r\n // We prefer MessageChannel because of the 4ms setTimeout clamping.\r\n var channel = new MessageChannel();\r\n var port = channel.port2;\r\n channel.port1.onmessage = performWorkUntilDeadline;\r\n\r\n schedulePerformWorkUntilDeadline = function () {\r\n port.postMessage(null);\r\n };\r\n} else {\r\n // We should only fallback here in non-browser environments.\r\n schedulePerformWorkUntilDeadline = function () {\r\n localSetTimeout(performWorkUntilDeadline, 0);\r\n };\r\n}\r\n\r\nfunction requestHostCallback(callback) {\r\n scheduledHostCallback = callback;\r\n\r\n if (!isMessageLoopRunning) {\r\n isMessageLoopRunning = true;\r\n schedulePerformWorkUntilDeadline();\r\n }\r\n}\r\n\r\nfunction requestHostTimeout(callback, ms) {\r\n taskTimeoutID = localSetTimeout(function () {\r\n callback(exports.unstable_now());\r\n }, ms);\r\n}\r\n\r\nfunction cancelHostTimeout() {\r\n localClearTimeout(taskTimeoutID);\r\n taskTimeoutID = -1;\r\n}\r\n\r\nvar unstable_requestPaint = requestPaint;\r\nvar unstable_Profiling = null;\r\n\r\nexports.unstable_IdlePriority = IdlePriority;\r\nexports.unstable_ImmediatePriority = ImmediatePriority;\r\nexports.unstable_LowPriority = LowPriority;\r\nexports.unstable_NormalPriority = NormalPriority;\r\nexports.unstable_Profiling = unstable_Profiling;\r\nexports.unstable_UserBlockingPriority = UserBlockingPriority;\r\nexports.unstable_cancelCallback = unstable_cancelCallback;\r\nexports.unstable_continueExecution = unstable_continueExecution;\r\nexports.unstable_forceFrameRate = forceFrameRate;\r\nexports.unstable_getCurrentPriorityLevel = unstable_getCurrentPriorityLevel;\r\nexports.unstable_getFirstCallbackNode = unstable_getFirstCallbackNode;\r\nexports.unstable_next = unstable_next;\r\nexports.unstable_pauseExecution = unstable_pauseExecution;\r\nexports.unstable_requestPaint = unstable_requestPaint;\r\nexports.unstable_runWithPriority = unstable_runWithPriority;\r\nexports.unstable_scheduleCallback = unstable_scheduleCallback;\r\nexports.unstable_shouldYield = shouldYieldToHost;\r\nexports.unstable_wrapCallback = unstable_wrapCallback;\r\n /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\r\nif (\r\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&\r\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop ===\r\n 'function'\r\n) {\r\n __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error());\r\n}\r\n \r\n })();\r\n}\r\n", "'use strict';\r\n\r\nif (process.env.NODE_ENV === 'production') {\r\n module.exports = require('./cjs/scheduler.production.min.js');\r\n} else {\r\n module.exports = require('./cjs/scheduler.development.js');\r\n}\r\n", "/**\r\n * @license React\r\n * react-dom.development.js\r\n *\r\n * Copyright (c) Facebook, Inc. and its affiliates.\r\n *\r\n * This source code is licensed under the MIT license found in the\r\n * LICENSE file in the root directory of this source tree.\r\n */\r\n\r\n'use strict';\r\n\r\nif (process.env.NODE_ENV !== \"production\") {\r\n (function() {\r\n\r\n 'use strict';\r\n\r\n/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\r\nif (\r\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&\r\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart ===\r\n 'function'\r\n) {\r\n __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());\r\n}\r\n var React = require('react');\r\nvar Scheduler = require('scheduler');\r\n\r\nvar ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\r\n\r\nvar suppressWarning = false;\r\nfunction setSuppressWarning(newSuppressWarning) {\r\n {\r\n suppressWarning = newSuppressWarning;\r\n }\r\n} // In DEV, calls to console.warn and console.error get replaced\r\n// by calls to these methods by a Babel plugin.\r\n//\r\n// In PROD (or in packages without access to React internals),\r\n// they are left as they are instead.\r\n\r\nfunction warn(format) {\r\n {\r\n if (!suppressWarning) {\r\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\r\n args[_key - 1] = arguments[_key];\r\n }\r\n\r\n printWarning('warn', format, args);\r\n }\r\n }\r\n}\r\nfunction error(format) {\r\n {\r\n if (!suppressWarning) {\r\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\r\n args[_key2 - 1] = arguments[_key2];\r\n }\r\n\r\n printWarning('error', format, args);\r\n }\r\n }\r\n}\r\n\r\nfunction printWarning(level, format, args) {\r\n // When changing this logic, you might want to also\r\n // update consoleWithStackDev.www.js as well.\r\n {\r\n var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\r\n var stack = ReactDebugCurrentFrame.getStackAddendum();\r\n\r\n if (stack !== '') {\r\n format += '%s';\r\n args = args.concat([stack]);\r\n } // eslint-disable-next-line react-internal/safe-string-coercion\r\n\r\n\r\n var argsWithFormat = args.map(function (item) {\r\n return String(item);\r\n }); // Careful: RN currently depends on this prefix\r\n\r\n argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\r\n // breaks IE9: https://github.com/facebook/react/issues/13610\r\n // eslint-disable-next-line react-internal/no-production-logging\r\n\r\n Function.prototype.apply.call(console[level], console, argsWithFormat);\r\n }\r\n}\r\n\r\nvar FunctionComponent = 0;\r\nvar ClassComponent = 1;\r\nvar IndeterminateComponent = 2; // Before we know whether it is function or class\r\n\r\nvar HostRoot = 3; // Root of a host tree. Could be nested inside another node.\r\n\r\nvar HostPortal = 4; // A subtree. Could be an entry point to a different renderer.\r\n\r\nvar HostComponent = 5;\r\nvar HostText = 6;\r\nvar Fragment = 7;\r\nvar Mode = 8;\r\nvar ContextConsumer = 9;\r\nvar ContextProvider = 10;\r\nvar ForwardRef = 11;\r\nvar Profiler = 12;\r\nvar SuspenseComponent = 13;\r\nvar MemoComponent = 14;\r\nvar SimpleMemoComponent = 15;\r\nvar LazyComponent = 16;\r\nvar IncompleteClassComponent = 17;\r\nvar DehydratedFragment = 18;\r\nvar SuspenseListComponent = 19;\r\nvar ScopeComponent = 21;\r\nvar OffscreenComponent = 22;\r\nvar LegacyHiddenComponent = 23;\r\nvar CacheComponent = 24;\r\nvar TracingMarkerComponent = 25;\r\n\r\n// -----------------------------------------------------------------------------\r\n\r\nvar enableClientRenderFallbackOnTextMismatch = true; // TODO: Need to review this code one more time before landing\r\n// the react-reconciler package.\r\n\r\nvar enableNewReconciler = false; // Support legacy Primer support on internal FB www\r\n\r\nvar enableLazyContextPropagation = false; // FB-only usage. The new API has different semantics.\r\n\r\nvar enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber\r\n\r\nvar enableSuspenseAvoidThisFallback = false; // Enables unstable_avoidThisFallback feature in Fizz\r\n// React DOM Chopping Block\r\n//\r\n// Similar to main Chopping Block but only flags related to React DOM. These are\r\n// grouped because we will likely batch all of them into a single major release.\r\n// -----------------------------------------------------------------------------\r\n// Disable support for comment nodes as React DOM containers. Already disabled\r\n// in open source, but www codebase still relies on it. Need to remove.\r\n\r\nvar disableCommentsAsDOMContainers = true; // Disable javascript: URL strings in href for XSS protection.\r\n// and client rendering, mostly to allow JSX attributes to apply to the custom\r\n// element's object properties instead of only HTML attributes.\r\n// https://github.com/facebook/react/issues/11347\r\n\r\nvar enableCustomElementPropertySupport = false; // Disables children for