From be689fa80b350cd5e95ca030438838e176dce3ff Mon Sep 17 00:00:00 2001 From: Jan Hajek Date: Thu, 5 Jun 2025 11:07:42 +0200 Subject: [PATCH 1/3] Build fix on Windows and PCF authentication via Token Broker description. --- package.json | 6 +- src/.vuepress/config.js | 17 +++++- .../controls/FileExplorer/authentication.md | 58 ------------------- .../GeneralInformation/authentication.md | 58 +++++++++++++++++++ 4 files changed, 76 insertions(+), 63 deletions(-) delete mode 100644 src/en/developer-guide/applications/controls/FileExplorer/authentication.md create mode 100644 src/en/developer-guide/applications/controls/GeneralInformation/authentication.md diff --git a/package.json b/package.json index 073d70ae9..0d344b2d8 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,9 @@ }, "repository": "https://github.com/TALXIS/docs/TALXIS Docs", "scripts": { - "dev": "NODE_OPTIONS=--openssl-legacy-provider vuepress dev src", - "build": "NODE_OPTIONS=--openssl-legacy-provider vuepress build src", - "start": "NODE_OPTIONS=--openssl-legacy-provider vuepress dev src" + "dev": "vuepress dev src", + "build": "vuepress build src", + "start": "vuepress dev src" }, "license": "MIT", "devDependencies": { diff --git a/src/.vuepress/config.js b/src/.vuepress/config.js index a5c273b43..860dfb1d4 100644 --- a/src/.vuepress/config.js +++ b/src/.vuepress/config.js @@ -1,6 +1,13 @@ const { config } = require("vuepress-theme-hope"); const { description } = require('../../package') +// Enable support for newer Node.js versions which don't support MD4 hashing, reference: https://stackoverflow.com/questions/69394632/webpack-build-failing-with-err-ossl-evp-unsupported, https://github.com/facebook/create-react-app/issues/11562 +const crypto = require("crypto"); +const crypto_orig_createHash = crypto.createHash; +crypto.createHash = (algorithm) => { + return crypto_orig_createHash(algorithm == "md4" ? "sha256" : algorithm); +} + module.exports = config({ locales: { '/': { @@ -368,7 +375,14 @@ module.exports = config({ title: 'Controls', collapsable: true, children: [ - ['/en/developer-guide/applications/controls/general.md', 'General Information'], + { + title: 'General Information', + collapsable: true, + children: [ + ['/en/developer-guide/applications/controls/general.md', 'General'], + ['/en/developer-guide/applications/controls/GeneralInformation/authentication.md', 'Authentication'], + ] + }, ['/en/developer-guide/applications/controls/addresspicker.md', 'Address Picker'], ['/en/developer-guide/applications/controls/annotations.md', 'Annotations'], ['/en/developer-guide/applications/controls/announcementcard.md', 'Accouncement Card'], @@ -387,7 +401,6 @@ module.exports = config({ collapsable: true, children: [ ['/en/developer-guide/applications/controls/FileExplorer/general.md', 'General'], - ['/en/developer-guide/applications/controls/FileExplorer/authentication.md', 'Authentication'], ['/en/developer-guide/applications/controls/FileExplorer/actions.md', 'Actions'], ['/en/developer-guide/applications/controls/FileExplorer/collaborationworkspaces.md', 'Collaboration Workspaces'], ['/en/developer-guide/applications/controls/FileExplorer/documenttemplating.md', 'Templates & Classification'], diff --git a/src/en/developer-guide/applications/controls/FileExplorer/authentication.md b/src/en/developer-guide/applications/controls/FileExplorer/authentication.md deleted file mode 100644 index 838555151..000000000 --- a/src/en/developer-guide/applications/controls/FileExplorer/authentication.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -Author: Matěj Samler ---- - -# Authentication diagram of File Explorer - -``` mermaid -%%{init: {'theme': 'dark'}}%% -sequenceDiagram - participant U as User - participant FE as File Explorer PCF - participant AAD as AAD (Azure Active Directory) - participant AZ as Azure (TALXIS STS) - participant MG as Microsoft Graph Api - participant SP as SharePoint - - U ->> FE: Interaction in app - - FE ->> AAD: Silent SSO or Pop-Up - activate AAD - AAD -->> FE: Return token - deactivate AAD - - FE ->> FE: Use returned token - - FE ->> AZ: Call using
On-Behalf-Of Flow - activate AZ - AZ ->> AZ: - Note over AZ: TALXIS Security Tokens Service - AZ -->> FE: Return token - deactivate AZ - - FE ->> FE: Use returned token - - FE ->> MG: Authenticated request - activate MG - MG ->> SP: File read/File write - activate SP - SP -->> MG: Result - deactivate SP - MG -->> FE: Result - deactivate MG - - FE ->> U: Response -``` - -File Explorer PCF (PowerApps Component Framework) control enables secure file interactions with SharePoint via Microsoft Graph API. -For more information about neccessary app consents, please refer to [this page](/docs/src/en/customizer-guide/required-application-consent.md#talxis---pcffilepicker). - -## Security tokens service - -After a successful authentication with the consented Azure app, the token is exchanged with securitytokens.services.talxis.com, a custom atuhentication service, which exchanges the App token for a MS Graph token with desired scopes. This is done using [On-Behalf-Of-Flow pattern](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-on-behalf-of-flow) - -The Security Tokens Service (STS) is a custom service that acts as an intermediary between the File Explorer control and Microsoft Graph API. It takes the token received from Azure Active Directory (AAD) after user authentication and exchanges it for a token that has the necessary permissions to access SharePoint resources. The service itself does not store any user data or credentials; it simply facilitates the token exchange process. The biggest benefit of this approach is that we don't require the user to log in again, minimizing the need for multiple pop-ups and improving the user experience. - -That token is then used to access SharePoint resources via Microsoft Graph API, allowing the control to perform file operations such as upload, download, and delete. - -For more information, please refer to the [internal documentation](https://dev.azure.com/thenetworg/INT0015/_wiki/wikis/INT0015.wiki/4301/Authentication-Flow) diff --git a/src/en/developer-guide/applications/controls/GeneralInformation/authentication.md b/src/en/developer-guide/applications/controls/GeneralInformation/authentication.md new file mode 100644 index 000000000..a4acf91f5 --- /dev/null +++ b/src/en/developer-guide/applications/controls/GeneralInformation/authentication.md @@ -0,0 +1,58 @@ +--- +Author: Jan Hajek +--- + +Certain client-side code requires to access protected APIs - like Microsoft Graph for accessing files, TALXIS Data Feed for accessing business registers and so on. Since browsers are getting more stricter about privacy - especially in regards of [third party cookies](https://cookie-script.com/all-you-need-to-know-about-third-party-cookies.html), it is becoming much harder to achieve a true single-sign-on experience. More on this topic from Microsoft Entra ID and SSO side can be found [here](https://learn.microsoft.com/en-us/entra/identity-platform/reference-third-party-cookies-spas). + +# Handling authentication in Power Apps + +> A more technical writeup can be found [here](https://hajekj.net/2025/04/28/using-entra-authentication-in-power-apps-pcfs-and-client-scripts/). + +Since neither controls nor client scripts can interact with the authenticated session within Power Apps, each piece of client code has to handle authentication on its own. This would work fine, but however due to the third party cookies being restricted, each control has to either show its own popup or do a redirect. Redirect can disturb the user while working, and popups are fairly annoying, and there are also restrictions in place - when a popup can be open and when the popup blocker blocks it (the popup has to be open from within a [click event](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserSettings/allowPopupsForUserEvents?utm_source=chatgpt.com)). + +Since we ship many controls and there are many scenarios where multiple controls are present on the same page, the user would be overwhelmed with dialogs telling them *Click to authenticate* for each control separately. This can be extremely frustrating for the users, and even more frustrating when happening on a mobile device. + +Because of the reasons above, we resorted to leveraging a Token Broker to handle the authentication. The Token Broker is a piece of client code which loads into the page via Application Ribbon and registers authentication methods into `window.*` so other code can call it. + +The token broker acts as a client facing application which "brokers" the tokens for other clients - controls and client code. This model is nothing really new - [Microsoft Teams does something similar](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/tab-sso-overview?WT.mc_id=AZ-MVP-5003178) for Teams apps (for the same [reasons](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/tab-sso-overview?WT.mc_id=AZ-MVP-5003178#third-party-cookies-on-ios)). + +## Why did you not use ...? + +### Custom APIs +Using Custom APIs in Dataverse would certainly work for **SOME** scenarios, however it doesn't have the option to work with the user's identity, which from a security standpoint would be a huge risk - especially when accessing SharePoint files for example. This would mean that anyone accessing/working with them would have the identity of an application rather than their own, so auditing and governance would get much more complicated. + +### Asynchronous Processing +A lot of actions which we need to perform need to run to completion as soon as possible and waiting for something to complete the action sometime (this is how Power Automate works in general) is not really feasible. + +### Power Automate +While it is [possible](https://hajekj.net/2025/05/08/dynamically-executing-power-automate-flows-from-client/) to execute Power Automate directly from within client-code (or asynchronously via entity creation - see above), we would be facing the same issues with identity like with Custom APIs and also performance would be really degraded. + +### Nested App Authentication +NAA is [an emerging feature](https://learn.microsoft.com/en-us/office/dev/add-ins/develop/enable-nested-app-authentication-in-your-add-in) currently available only in some Microsoft products - Microsoft Teams and some Office apps. If you are big enough customer, tell your Microsoft executive that you want this available within Power Apps. + +# App Registration Setup + +> App registrations used by our services can be found [here](https://docs.talxis.com/en/customizer-guide/required-application-consent/) + +The scenario typically consists of 3 app registrations: + +### Shared Token Broker registration - TALXIS - Client +This is a shared app registration for every client control which wants to use the Token Broker. + +### Control client registration +This app registration is unique and specific to each of the clients based on the workload it is supposed to do. It has the Token Broker pre-configured as a known client application. + +### Control backend registration +One control can have multiple backends it is calling - for example Microsoft Graph and Data Feed API. The backend registration is usually an existing app registration (in case of Microsoft Graph or TALXIS Data Feed) or a unique one for its own API. + +### Security +The reason for this is security - if a customer wants to use Company Picker PCF (which calls Data Feed), they only consent the broker app, the client app for the PCF and the TALXIS Data Feed. If they need to use the File Picker, they only consent the broker app, the File Picker client app (Microsoft Graph is in all tenants). This means that without the consent to File Picker app, in the first scenario, the Token Broker is unable to broker tokens for the File Picker workload and thus retrieve Microsoft Graph tokens. + +# Exchanging tokens +From the nature of the authentication the Token Broker is able to exchange the token for the control client registration. The backend token has to be exchanged via the [on-behalf-of (OBO)](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-on-behalf-of-flow) flow, which requires a confidential client. This means that this cannot be done just from the frontend (it could work with NAA, but see above) and a backend code aware of the client secret has to be involved. + +## Security Token Service +In our Broker setup, the backend which performs the OBO flow is called Security Token Service. This service is shared for all our app registrations. It holds the secret (certificate) configured the control client in order to perform the OBO request and provide the token for the requested service (Microsoft Graph, Data Feed, ...) through the Token Broker to the client. + +# More information +For more information, please refer to the [internal documentation](https://dev.azure.com/thenetworg/INT0015/_wiki/wikis/INT0015.wiki/4301/Authentication-Flow) (NETWORG employees only) or [reach out to us](https://networg.com). From 2d6a9b66447b33319b3b7321a4361108205ab0ce Mon Sep 17 00:00:00 2001 From: Jan Hajek Date: Thu, 5 Jun 2025 11:21:34 +0200 Subject: [PATCH 2/3] Fix heading, add reference to File Picker. --- .../controls/FileExplorer/general.md | 3 ++ .../GeneralInformation/authentication.md | 30 ++++++++++--------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/en/developer-guide/applications/controls/FileExplorer/general.md b/src/en/developer-guide/applications/controls/FileExplorer/general.md index 6f797d23d..50d506dc9 100644 --- a/src/en/developer-guide/applications/controls/FileExplorer/general.md +++ b/src/en/developer-guide/applications/controls/FileExplorer/general.md @@ -46,6 +46,9 @@ An existing Collaboration Workspace Template record is necessary for File Explor Check [Collaboration Workspaces](./collaborationworkspaces.md) for more info. +### Authentication +If you are planning to use Microsoft Graph as a file source, you will need to provide consent for a few application registrations in order for this control to work. The whole authentication process is described [here](/en/developer-guide/applications/controls/GeneralInformation/authentication/); + ## General Overview ![File Explorer Structure](/.attachments/applications/Controls/FileExplorer/fileexplorer_overview.png) diff --git a/src/en/developer-guide/applications/controls/GeneralInformation/authentication.md b/src/en/developer-guide/applications/controls/GeneralInformation/authentication.md index a4acf91f5..06520e92a 100644 --- a/src/en/developer-guide/applications/controls/GeneralInformation/authentication.md +++ b/src/en/developer-guide/applications/controls/GeneralInformation/authentication.md @@ -2,9 +2,11 @@ Author: Jan Hajek --- +# Authentication + Certain client-side code requires to access protected APIs - like Microsoft Graph for accessing files, TALXIS Data Feed for accessing business registers and so on. Since browsers are getting more stricter about privacy - especially in regards of [third party cookies](https://cookie-script.com/all-you-need-to-know-about-third-party-cookies.html), it is becoming much harder to achieve a true single-sign-on experience. More on this topic from Microsoft Entra ID and SSO side can be found [here](https://learn.microsoft.com/en-us/entra/identity-platform/reference-third-party-cookies-spas). -# Handling authentication in Power Apps +## Handling authentication in Power Apps > A more technical writeup can be found [here](https://hajekj.net/2025/04/28/using-entra-authentication-in-power-apps-pcfs-and-client-scripts/). @@ -16,43 +18,43 @@ Because of the reasons above, we resorted to leveraging a Token Broker to handle The token broker acts as a client facing application which "brokers" the tokens for other clients - controls and client code. This model is nothing really new - [Microsoft Teams does something similar](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/tab-sso-overview?WT.mc_id=AZ-MVP-5003178) for Teams apps (for the same [reasons](https://learn.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/authentication/tab-sso-overview?WT.mc_id=AZ-MVP-5003178#third-party-cookies-on-ios)). -## Why did you not use ...? +### Why did you not use ...? -### Custom APIs +#### Custom APIs Using Custom APIs in Dataverse would certainly work for **SOME** scenarios, however it doesn't have the option to work with the user's identity, which from a security standpoint would be a huge risk - especially when accessing SharePoint files for example. This would mean that anyone accessing/working with them would have the identity of an application rather than their own, so auditing and governance would get much more complicated. -### Asynchronous Processing +#### Asynchronous Processing A lot of actions which we need to perform need to run to completion as soon as possible and waiting for something to complete the action sometime (this is how Power Automate works in general) is not really feasible. -### Power Automate +#### Power Automate While it is [possible](https://hajekj.net/2025/05/08/dynamically-executing-power-automate-flows-from-client/) to execute Power Automate directly from within client-code (or asynchronously via entity creation - see above), we would be facing the same issues with identity like with Custom APIs and also performance would be really degraded. -### Nested App Authentication +#### Nested App Authentication NAA is [an emerging feature](https://learn.microsoft.com/en-us/office/dev/add-ins/develop/enable-nested-app-authentication-in-your-add-in) currently available only in some Microsoft products - Microsoft Teams and some Office apps. If you are big enough customer, tell your Microsoft executive that you want this available within Power Apps. -# App Registration Setup +## App Registration Setup > App registrations used by our services can be found [here](https://docs.talxis.com/en/customizer-guide/required-application-consent/) The scenario typically consists of 3 app registrations: -### Shared Token Broker registration - TALXIS - Client +#### Shared Token Broker registration - TALXIS - Client This is a shared app registration for every client control which wants to use the Token Broker. -### Control client registration +#### Control client registration This app registration is unique and specific to each of the clients based on the workload it is supposed to do. It has the Token Broker pre-configured as a known client application. -### Control backend registration +#### Control backend registration One control can have multiple backends it is calling - for example Microsoft Graph and Data Feed API. The backend registration is usually an existing app registration (in case of Microsoft Graph or TALXIS Data Feed) or a unique one for its own API. -### Security +#### Security The reason for this is security - if a customer wants to use Company Picker PCF (which calls Data Feed), they only consent the broker app, the client app for the PCF and the TALXIS Data Feed. If they need to use the File Picker, they only consent the broker app, the File Picker client app (Microsoft Graph is in all tenants). This means that without the consent to File Picker app, in the first scenario, the Token Broker is unable to broker tokens for the File Picker workload and thus retrieve Microsoft Graph tokens. -# Exchanging tokens +## Exchanging tokens From the nature of the authentication the Token Broker is able to exchange the token for the control client registration. The backend token has to be exchanged via the [on-behalf-of (OBO)](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-on-behalf-of-flow) flow, which requires a confidential client. This means that this cannot be done just from the frontend (it could work with NAA, but see above) and a backend code aware of the client secret has to be involved. -## Security Token Service +### Security Token Service In our Broker setup, the backend which performs the OBO flow is called Security Token Service. This service is shared for all our app registrations. It holds the secret (certificate) configured the control client in order to perform the OBO request and provide the token for the requested service (Microsoft Graph, Data Feed, ...) through the Token Broker to the client. -# More information +## More information For more information, please refer to the [internal documentation](https://dev.azure.com/thenetworg/INT0015/_wiki/wikis/INT0015.wiki/4301/Authentication-Flow) (NETWORG employees only) or [reach out to us](https://networg.com). From faaf4abd687b85065e72d7da3a32879016aeae26 Mon Sep 17 00:00:00 2001 From: Jan Hajek Date: Thu, 5 Jun 2025 11:55:53 +0200 Subject: [PATCH 3/3] Add basic chart of high-level function --- .../GeneralInformation/authentication.md | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/en/developer-guide/applications/controls/GeneralInformation/authentication.md b/src/en/developer-guide/applications/controls/GeneralInformation/authentication.md index 06520e92a..2fb511f3e 100644 --- a/src/en/developer-guide/applications/controls/GeneralInformation/authentication.md +++ b/src/en/developer-guide/applications/controls/GeneralInformation/authentication.md @@ -56,5 +56,41 @@ From the nature of the authentication the Token Broker is able to exchange the t ### Security Token Service In our Broker setup, the backend which performs the OBO flow is called Security Token Service. This service is shared for all our app registrations. It holds the secret (certificate) configured the control client in order to perform the OBO request and provide the token for the requested service (Microsoft Graph, Data Feed, ...) through the Token Broker to the client. +## Basic flow chart + +```mermaid +graph TD + +%% Client-side components +User["User"] +Control["Client Control"] +RibbonScript["Application Ribbon Script
(loads Token Broker)"] +TokenBroker["Token Broker
(window.* interface)"] + +%% Azure Datacenter boundary +subgraph "TALXIS PROD tenant" + BrokerApp["App Registration:
TALXIS - Client (Token Broker)"] + ControlApp["App Registration:
Control Client"] + STS["Security Token Service
(performs OBO flow with client secret)"] +end + +%% External API boundary +subgraph "TALXIS PROD or 3rd party" + BackendAPI["App Registration:
Backend API"] +end + +%% Flow +User --> Control +Control -->|1. Requests token for Backend API via Control Client| TokenBroker +RibbonScript --> TokenBroker + +TokenBroker -->|2. Popup or silent refresh of token with Control Client scope| BrokerApp +BrokerApp --> ControlApp + +TokenBroker -->|3. Calls STS with obtained token from step 2.| STS +STS -->|4.1. Uses Control Client certificate for OBO| ControlApp +STS -->|4. Performs OBO request to exchange the token| BackendAPI +``` + ## More information For more information, please refer to the [internal documentation](https://dev.azure.com/thenetworg/INT0015/_wiki/wikis/INT0015.wiki/4301/Authentication-Flow) (NETWORG employees only) or [reach out to us](https://networg.com).